Move `ThreadFsInfo` from `PosixThread` to `ThreadLocal`

This commit is contained in:
jiangjianfeng 2025-08-04 09:31:53 +00:00 committed by Ruihan Li
parent b20d8461fd
commit de97644b4c
32 changed files with 125 additions and 71 deletions

View File

@ -17,7 +17,7 @@ use crate::{
},
prelude::*,
process::{
posix_thread::{AsPosixThread, AsThreadLocal},
posix_thread::AsThreadLocal,
signal::{PollHandle, Pollable},
Terminal,
},
@ -115,7 +115,6 @@ impl FileIo for PtyMaster {
}
IoctlCmd::TIOCGPTPEER => {
let current_task = Task::current().unwrap();
let posix_thread = current_task.as_posix_thread().unwrap();
let thread_local = current_task.as_thread_local().unwrap();
// TODO: Deal with `open()` flags.
@ -128,10 +127,13 @@ impl FileIo for PtyMaster {
let fs_path = FsPath::try_from(slave_name.as_str())?;
let inode_handle = {
let fs = posix_thread.fs().resolver().read();
let flags = AccessMode::O_RDWR as u32;
let mode = (InodeMode::S_IRUSR | InodeMode::S_IWUSR).bits();
fs.open(&fs_path, flags, mode)?
thread_local
.borrow_fs()
.resolver()
.read()
.open(&fs_path, flags, mode)?
};
Arc::new(inode_handle)
};

View File

@ -1155,7 +1155,8 @@ impl FsType for OverlayFsType {
}
}
let fs = ctx.posix_thread.fs().resolver().read();
let fs_ref = ctx.thread_local.borrow_fs();
let fs = fs_ref.resolver().read();
let upper = fs.lookup(&FsPath::new(AT_FDCWD, upper)?)?;
let lower = lower

View File

@ -1,5 +1,7 @@
// SPDX-License-Identifier: MPL-2.0
use ostd::task::Task;
use crate::{
fs::{
fs_resolver::{split_path, FsPath},
@ -7,14 +9,13 @@ use crate::{
utils::{InodeMode, InodeType, Permission},
},
prelude::*,
process::posix_thread::AsPosixThread,
};
pub fn lookup_socket_file(path: &str) -> Result<Dentry> {
let dentry = {
let current = current_thread!();
let current = current.as_posix_thread().unwrap();
let fs = current.fs().resolver().read();
let current = Task::current().unwrap();
let fs_ref = current.as_thread_local().unwrap().borrow_fs();
let fs = fs_ref.resolver().read();
let fs_path = FsPath::try_from(path)?;
fs.lookup(&fs_path)?
};
@ -41,9 +42,9 @@ pub fn create_socket_file(path: &str) -> Result<Dentry> {
let (parent_pathname, file_name) = split_path(path);
let parent = {
let current = current_thread!();
let current = current.as_posix_thread().unwrap();
let fs = current.fs().resolver().read();
let current = Task::current().unwrap();
let fs_ref = current.as_thread_local().unwrap().borrow_fs();
let fs = fs_ref.resolver().read();
let parent_path = FsPath::try_from(parent_pathname)?;
fs.lookup(&parent_path)?
};

View File

@ -255,7 +255,7 @@ fn clone_child_task(
let child_file_table = clone_files(thread_local.borrow_file_table().unwrap(), clone_flags);
// Clone fs
let child_fs = clone_fs(posix_thread.fs(), clone_flags);
let child_fs = clone_fs(&thread_local.borrow_fs(), clone_flags);
// Clone FPU context
let child_fpu_context = thread_local.fpu().clone_context();
@ -339,7 +339,7 @@ fn clone_child_process(
let child_file_table = clone_files(thread_local.borrow_file_table().unwrap(), clone_flags);
// Clone the filesystem information
let child_fs = clone_fs(posix_thread.fs(), clone_flags);
let child_fs = clone_fs(&thread_local.borrow_fs(), clone_flags);
// Clone signal dispositions
let child_sig_dispositions = clone_sighand(process.sig_dispositions(), clone_flags);

View File

@ -145,7 +145,6 @@ impl PosixThreadBuilder {
name: Mutex::new(thread_name),
credentials,
file_table: Mutex::new(Some(file_table.clone_ro())),
fs,
sig_mask,
sig_queues,
signalled_waker: SpinLock::new(None),
@ -169,6 +168,7 @@ impl PosixThreadBuilder {
clear_child_tid,
root_vmar,
file_table,
fs,
fpu_context,
);

View File

@ -19,7 +19,7 @@ use super::{
};
use crate::{
events::Observer,
fs::{file_table::FileTable, thread_info::ThreadFsInfo},
fs::file_table::FileTable,
prelude::*,
process::signal::constants::SIGCONT,
thread::{Thread, Tid},
@ -56,8 +56,6 @@ pub struct PosixThread {
// Files
/// File table
file_table: Mutex<Option<RoArc<FileTable>>>,
/// File system
fs: Arc<ThreadFsInfo>,
// Signal
/// Blocked signals
@ -103,10 +101,6 @@ impl PosixThread {
&self.file_table
}
pub fn fs(&self) -> &Arc<ThreadFsInfo> {
&self.fs
}
/// Get the reference to the signal mask of the thread.
///
/// Note that while this function offers mutable access to the signal mask,

View File

@ -6,7 +6,12 @@ use aster_rights::Full;
use ostd::{cpu::context::FpuContext, mm::Vaddr, sync::RwArc, task::CurrentTask};
use super::RobustListHead;
use crate::{fs::file_table::FileTable, process::signal::SigStack, vm::vmar::Vmar};
use crate::{
fs::{file_table::FileTable, thread_info::ThreadFsInfo},
prelude::*,
process::signal::SigStack,
vm::vmar::Vmar,
};
/// Local data for a POSIX thread.
pub struct ThreadLocal {
@ -23,7 +28,10 @@ pub struct ThreadLocal {
robust_list: RefCell<Option<RobustListHead>>,
// Files.
/// File table.
file_table: RefCell<Option<RwArc<FileTable>>>,
/// File system.
fs: RefCell<Arc<ThreadFsInfo>>,
// User FPU context.
fpu_context: RefCell<FpuContext>,
@ -44,6 +52,7 @@ impl ThreadLocal {
clear_child_tid: Vaddr,
root_vmar: Vmar<Full>,
file_table: RwArc<FileTable>,
fs: Arc<ThreadFsInfo>,
fpu_context: FpuContext,
) -> Self {
Self {
@ -52,6 +61,7 @@ impl ThreadLocal {
root_vmar: RefCell::new(Some(root_vmar)),
robust_list: RefCell::new(None),
file_table: RefCell::new(Some(file_table)),
fs: RefCell::new(fs),
sig_context: Cell::new(None),
sig_stack: RefCell::new(None),
fpu_context: RefCell::new(fpu_context),
@ -83,6 +93,14 @@ impl ThreadLocal {
FileTableRefMut(self.file_table.borrow_mut())
}
pub fn borrow_fs(&self) -> Ref<'_, Arc<ThreadFsInfo>> {
self.fs.borrow()
}
pub fn borrow_fs_mut(&self) -> RefMut<'_, Arc<ThreadFsInfo>> {
self.fs.borrow_mut()
}
pub fn sig_context(&self) -> &Cell<Option<Vaddr>> {
&self.sig_context
}

View File

@ -88,7 +88,8 @@ pub fn do_faccessat(
let dentry = {
let path = path.to_string_lossy();
let fs_path = FsPath::new(dirfd, path.as_ref())?;
let fs = ctx.posix_thread.fs().resolver().read();
let fs_ref = ctx.thread_local.borrow_fs();
let fs = fs_ref.resolver().read();
if flags.contains(FaccessatFlags::AT_SYMLINK_NOFOLLOW) {
fs.lookup_no_follow(&fs_path)?
} else {

View File

@ -15,7 +15,8 @@ pub fn sys_chdir(path_ptr: Vaddr, ctx: &Context) -> Result<SyscallReturn> {
let path = ctx.user_space().read_cstring(path_ptr, MAX_FILENAME_LEN)?;
debug!("path = {:?}", path);
let mut fs = ctx.posix_thread.fs().resolver().write();
let fs_ref = ctx.thread_local.borrow_fs();
let mut fs = fs_ref.resolver().write();
let dentry = {
let path = path.to_string_lossy();
if path.is_empty() {
@ -42,6 +43,7 @@ pub fn sys_fchdir(fd: FileDesc, ctx: &Context) -> Result<SyscallReturn> {
if dentry.type_() != InodeType::Dir {
return_errno_with_message!(Errno::ENOTDIR, "must be directory");
}
ctx.posix_thread.fs().resolver().write().set_cwd(dentry);
let fs_ref = ctx.thread_local.borrow_fs();
fs_ref.resolver().write().set_cwd(dentry);
Ok(SyscallReturn::Return(0))
}

View File

@ -40,7 +40,11 @@ pub fn sys_fchmodat(
return_errno_with_message!(Errno::ENOENT, "path is empty");
}
let fs_path = FsPath::new(dirfd, path.as_ref())?;
ctx.posix_thread.fs().resolver().read().lookup(&fs_path)?
ctx.thread_local
.borrow_fs()
.resolver()
.read()
.lookup(&fs_path)?
};
dentry.set_mode(InodeMode::from_bits_truncate(mode))?;
Ok(SyscallReturn::Return(0))

View File

@ -78,7 +78,8 @@ pub fn sys_fchownat(
let dentry = {
let path = path.to_string_lossy();
let fs_path = FsPath::new(dirfd, path.as_ref())?;
let fs = ctx.posix_thread.fs().resolver().read();
let fs_ref = ctx.thread_local.borrow_fs();
let fs = fs_ref.resolver().read();
if flags.contains(ChownFlags::AT_SYMLINK_NOFOLLOW) {
fs.lookup_no_follow(&fs_path)?
} else {

View File

@ -11,7 +11,8 @@ pub fn sys_chroot(path_ptr: Vaddr, ctx: &Context) -> Result<SyscallReturn> {
let path = ctx.user_space().read_cstring(path_ptr, MAX_FILENAME_LEN)?;
debug!("path = {:?}", path);
let mut fs = ctx.posix_thread.fs().resolver().write();
let fs_ref = ctx.thread_local.borrow_fs();
let mut fs = fs_ref.resolver().write();
let dentry = {
let path = path.to_string_lossy();
if path.is_empty() {

View File

@ -66,7 +66,8 @@ fn lookup_executable_file(
let file = get_file_fast!(&mut file_table, dfd);
file.as_inode_or_err()?.dentry().clone()
} else {
let fs_resolver = ctx.posix_thread.fs().resolver().read();
let fs_ref = ctx.thread_local.borrow_fs();
let fs_resolver = fs_ref.resolver().read();
let fs_path = FsPath::new(dfd, &filename)?;
if flags.contains(OpenFlags::AT_SYMLINK_NOFOLLOW) {
fs_resolver.lookup_no_follow(&fs_path)?
@ -123,9 +124,10 @@ fn do_execve(
drop(closed_files);
debug!("load program to root vmar");
let fs_resolver = &*posix_thread.fs().resolver().read();
let fs_ref = thread_local.borrow_fs();
let fs_resolver = fs_ref.resolver().read();
let program_to_load =
ProgramToLoad::build_from_file(elf_file.clone(), fs_resolver, argv, envp, 1)?;
ProgramToLoad::build_from_file(elf_file.clone(), &fs_resolver, argv, envp, 1)?;
renew_vm_and_map(ctx);
@ -137,7 +139,7 @@ fn do_execve(
}
let (new_executable_path, elf_load_info) =
program_to_load.load_to_vm(process.vm(), fs_resolver)?;
program_to_load.load_to_vm(process.vm(), &fs_resolver)?;
// After the program has been successfully loaded, the virtual memory of the current process
// is initialized. Hence, it is necessary to clear the previously recorded robust list.

View File

@ -7,9 +7,9 @@ use crate::{
};
pub fn sys_getcwd(buf: Vaddr, len: usize, ctx: &Context) -> Result<SyscallReturn> {
let current = ctx.posix_thread;
let dirent = current
.fs()
let dirent = ctx
.thread_local
.borrow_fs()
.resolver()
.read()
.lookup(&FsPath::new(AT_FDCWD, "").unwrap())

View File

@ -44,7 +44,8 @@ pub fn sys_linkat(
let old_fs_path = FsPath::new(old_dirfd, old_path.as_ref())?;
let new_fs_path = FsPath::new(new_dirfd, new_path.as_ref())?;
let fs = ctx.posix_thread.fs().resolver().read();
let fs_ref = ctx.thread_local.borrow_fs();
let fs = fs_ref.resolver().read();
let old_dentry = if flags.contains(LinkFlags::AT_SYMLINK_FOLLOW) {
fs.lookup(&old_fs_path)?
} else {

View File

@ -20,22 +20,21 @@ pub fn sys_mkdirat(
let path = ctx.user_space().read_cstring(path_addr, MAX_FILENAME_LEN)?;
debug!("dirfd = {}, path = {:?}, mode = {}", dirfd, path, mode);
let current = ctx.posix_thread;
let fs_ref = ctx.thread_local.borrow_fs();
let (dir_dentry, name) = {
let path = path.to_string_lossy();
if path.is_empty() {
return_errno_with_message!(Errno::ENOENT, "path is empty");
}
let fs_path = FsPath::new(dirfd, path.as_ref())?;
current
.fs()
fs_ref
.resolver()
.read()
.lookup_dir_and_new_basename(&fs_path, true)?
};
let inode_mode = {
let mask_mode = mode & !current.fs().umask().read().get();
let mask_mode = mode & !fs_ref.umask().read().get();
InodeMode::from_bits_truncate(mask_mode)
};
let _ = dir_dentry.new_fs_child(name.trim_end_matches('/'), InodeType::Dir, inode_mode)?;

View File

@ -21,9 +21,9 @@ pub fn sys_mknodat(
ctx: &Context,
) -> Result<SyscallReturn> {
let path = ctx.user_space().read_cstring(path_addr, MAX_FILENAME_LEN)?;
let current = ctx.posix_thread;
let fs_ref = ctx.thread_local.borrow_fs();
let inode_mode = {
let mask_mode = mode & !current.fs().umask().read().get();
let mask_mode = mode & !fs_ref.umask().read().get();
InodeMode::from_bits_truncate(mask_mode)
};
let inode_type = InodeType::from_raw_mode(mode)?;
@ -38,8 +38,7 @@ pub fn sys_mknodat(
return_errno_with_message!(Errno::ENOENT, "path is empty");
}
let fs_path = FsPath::new(dirfd, path.as_ref())?;
current
.fs()
fs_ref
.resolver()
.read()
.lookup_dir_and_new_basename(&fs_path, false)?

View File

@ -39,7 +39,11 @@ pub fn sys_mount(
return_errno_with_message!(Errno::ENOENT, "dirname is empty");
}
let fs_path = FsPath::new(AT_FDCWD, dirname.as_ref())?;
ctx.posix_thread.fs().resolver().read().lookup(&fs_path)?
ctx.thread_local
.borrow_fs()
.resolver()
.read()
.lookup(&fs_path)?
};
if mount_flags.contains(MountFlags::MS_REMOUNT) && mount_flags.contains(MountFlags::MS_BIND) {
@ -92,7 +96,11 @@ fn do_bind_mount(
return_errno_with_message!(Errno::ENOENT, "src_name is empty");
}
let fs_path = FsPath::new(AT_FDCWD, src_name.as_ref())?;
ctx.posix_thread.fs().resolver().read().lookup(&fs_path)?
ctx.thread_local
.borrow_fs()
.resolver()
.read()
.lookup(&fs_path)?
};
if src_dentry.type_() != InodeType::Dir {
@ -115,7 +123,11 @@ fn do_move_mount_old(src_name: CString, dst_dentry: Dentry, ctx: &Context) -> Re
return_errno_with_message!(Errno::ENOENT, "src_name is empty");
}
let fs_path = FsPath::new(AT_FDCWD, src_name.as_ref())?;
ctx.posix_thread.fs().resolver().read().lookup(&fs_path)?
ctx.thread_local
.borrow_fs()
.resolver()
.read()
.lookup(&fs_path)?
};
if !src_dentry.is_root_of_mount() {

View File

@ -24,13 +24,12 @@ pub fn sys_openat(
dirfd, path, flags, mode
);
let current = ctx.posix_thread;
let file_handle = {
let path = path.to_string_lossy();
let fs_path = FsPath::new(dirfd, path.as_ref())?;
let mask_mode = mode & !current.fs().umask().read().get();
let inode_handle = current
.fs()
let fs_ref = ctx.thread_local.borrow_fs();
let mask_mode = mode & !fs_ref.umask().read().get();
let inode_handle = fs_ref
.resolver()
.read()
.open(&fs_path, flags, mask_mode)

View File

@ -30,8 +30,8 @@ pub fn sys_readlinkat(
return_errno_with_message!(Errno::ENOENT, "path is empty");
}
let fs_path = FsPath::new(dirfd, path.as_ref())?;
ctx.posix_thread
.fs()
ctx.thread_local
.borrow_fs()
.resolver()
.read()
.lookup_no_follow(&fs_path)?

View File

@ -26,7 +26,8 @@ pub fn sys_renameat(
old_dirfd, old_path, new_dirfd, new_path
);
let fs = ctx.posix_thread.fs().resolver().read();
let fs_ref = ctx.thread_local.borrow_fs();
let fs = fs_ref.resolver().read();
let (old_dir_dentry, old_name) = {
let old_path = old_path.to_string_lossy();

View File

@ -31,8 +31,8 @@ pub(super) fn sys_rmdirat(
return_errno_with_message!(Errno::EBUSY, "is root directory");
}
let fs_path = FsPath::new(dirfd, path.as_ref())?;
ctx.posix_thread
.fs()
ctx.thread_local
.borrow_fs()
.resolver()
.read()
.lookup_dir_and_base_name(&fs_path)?

View File

@ -132,7 +132,8 @@ pub(super) fn lookup_dentry_for_xattr<'a>(
|path: &CString, ctx: &Context, symlink_no_follow: bool| -> Result<Cow<'_, Dentry>> {
let path = path.to_string_lossy();
let fs_path = FsPath::new(AT_FDCWD, path.as_ref())?;
let fs = ctx.posix_thread.fs().resolver().read();
let fs_ref = ctx.thread_local.borrow_fs();
let fs = fs_ref.resolver().read();
let dentry = if symlink_no_follow {
fs.lookup_no_follow(&fs_path)?
} else {

View File

@ -67,7 +67,8 @@ pub fn sys_fstatat(
let dentry = {
let filename = filename.to_string_lossy();
let fs_path = FsPath::new(dirfd, filename.as_ref())?;
let fs = ctx.posix_thread.fs().resolver().read();
let fs_ref = ctx.thread_local.borrow_fs();
let fs = fs_ref.resolver().read();
if flags.contains(StatFlags::AT_SYMLINK_NOFOLLOW) {
fs.lookup_no_follow(&fs_path)?
} else {

View File

@ -18,7 +18,11 @@ pub fn sys_statfs(path_ptr: Vaddr, statfs_buf_ptr: Vaddr, ctx: &Context) -> Resu
let dentry = {
let path = path.to_string_lossy();
let fs_path = FsPath::try_from(path.as_ref())?;
ctx.posix_thread.fs().resolver().read().lookup(&fs_path)?
ctx.thread_local
.borrow_fs()
.resolver()
.read()
.lookup(&fs_path)?
};
let statfs = Statfs::from(dentry.fs().sb());
user_space.write_val(statfs_buf_ptr, &statfs)?;

View File

@ -49,7 +49,8 @@ pub fn sys_statx(
let dentry = {
let filename = filename.to_string_lossy();
let fs_path = FsPath::new(dirfd, filename.as_ref())?;
let fs = ctx.posix_thread.fs().resolver().read();
let fs_ref = ctx.thread_local.borrow_fs();
let fs = fs_ref.resolver().read();
if flags.contains(StatxFlags::AT_SYMLINK_NOFOLLOW) {
fs.lookup_no_follow(&fs_path)?
} else {

View File

@ -35,8 +35,8 @@ pub fn sys_symlinkat(
return_errno_with_message!(Errno::ENOENT, "linkpath is empty");
}
let fs_path = FsPath::new(dirfd, linkpath.as_ref())?;
ctx.posix_thread
.fs()
ctx.thread_local
.borrow_fs()
.resolver()
.read()
.lookup_dir_and_new_basename(&fs_path, false)?

View File

@ -34,7 +34,11 @@ pub fn sys_truncate(path_ptr: Vaddr, len: isize, ctx: &Context) -> Result<Syscal
return_errno_with_message!(Errno::ENOENT, "path is empty");
}
let fs_path = FsPath::new(AT_FDCWD, path.as_ref())?;
ctx.posix_thread.fs().resolver().read().lookup(&fs_path)?
ctx.thread_local
.borrow_fs()
.resolver()
.read()
.lookup(&fs_path)?
};
dir_dentry.resize(len as usize)?;
Ok(SyscallReturn::Return(0))

View File

@ -5,6 +5,6 @@ use crate::prelude::*;
pub fn sys_umask(mask: u16, ctx: &Context) -> Result<SyscallReturn> {
debug!("mask = 0o{:o}", mask);
let old_mask = ctx.posix_thread.fs().umask().write().set(mask);
let old_mask = ctx.thread_local.borrow_fs().umask().write().set(mask);
Ok(SyscallReturn::Return(old_mask as _))
}

View File

@ -21,13 +21,17 @@ pub fn sys_umount(path_addr: Vaddr, flags: u64, ctx: &Context) -> Result<Syscall
let fs_path = FsPath::new(AT_FDCWD, path.as_ref())?;
let target_dentry = if umount_flags.contains(UmountFlags::UMOUNT_NOFOLLOW) {
ctx.posix_thread
.fs()
ctx.thread_local
.borrow_fs()
.resolver()
.read()
.lookup_no_follow(&fs_path)?
} else {
ctx.posix_thread.fs().resolver().read().lookup(&fs_path)?
ctx.thread_local
.borrow_fs()
.resolver()
.read()
.lookup(&fs_path)?
};
target_dentry.unmount()?;

View File

@ -34,8 +34,8 @@ pub fn sys_unlinkat(
return_errno_with_message!(Errno::EISDIR, "unlink on directory");
}
let fs_path = FsPath::new(dirfd, path.as_ref())?;
ctx.posix_thread
.fs()
ctx.thread_local
.borrow_fs()
.resolver()
.read()
.lookup_dir_and_base_name(&fs_path)?

View File

@ -168,7 +168,8 @@ fn do_utimes(
let dentry = {
// Determine the file system path and the corresponding entry
let fs_path = FsPath::new(dirfd, pathname.as_ref())?;
let fs = ctx.posix_thread.fs().resolver().read();
let fs_ref = ctx.thread_local.borrow_fs();
let fs = fs_ref.resolver().read();
if flags.contains(UtimensFlags::AT_SYMLINK_NOFOLLOW) {
fs.lookup_no_follow(&fs_path)?
} else {