From 6307446edeb1dd495aea17469e47c04641746bc2 Mon Sep 17 00:00:00 2001 From: Wildan M Date: Mon, 9 Mar 2026 15:57:38 +0700 Subject: [PATCH] Solve borrow rules to LockedFdTbl --- src/context/context.rs | 2 +- src/context/file.rs | 4 +- src/event.rs | 4 +- src/scheme/proc.rs | 10 ++- src/scheme/sys/iostat.rs | 3 +- src/scheme/user.rs | 42 ++++++----- src/syscall/fs.rs | 158 ++++++++++++++++++++++----------------- src/syscall/process.rs | 8 +- 8 files changed, 132 insertions(+), 99 deletions(-) diff --git a/src/context/context.rs b/src/context/context.rs index 8146d977bf..94378851b0 100644 --- a/src/context/context.rs +++ b/src/context/context.rs @@ -865,7 +865,7 @@ impl FdTbl { &self, scheme_id: SchemeId, scheme_number: usize, - token: &mut LockToken, + token: &mut LockToken, ) -> Result { self.iter() .flatten() diff --git a/src/context/file.rs b/src/context/file.rs index 2d99e54934..2d3790f147 100644 --- a/src/context/file.rs +++ b/src/context/file.rs @@ -3,13 +3,13 @@ use crate::{ event, scheme::{self, SchemeId}, - sync::{CleanLockToken, RwLock, L5}, + sync::{CleanLockToken, RwLock, L6}, syscall::error::Result, }; use alloc::sync::Arc; use syscall::{schemev2::NewFdFlags, RwFlags, O_APPEND, O_NONBLOCK}; -pub type LockedFileDescription = RwLock; +pub type LockedFileDescription = RwLock; /// A file description #[derive(Clone, Copy, Debug)] diff --git a/src/event.rs b/src/event.rs index 14e71d68ae..b1db2cff5f 100644 --- a/src/event.rs +++ b/src/event.rs @@ -47,8 +47,8 @@ impl EventQueue { for event in events { let file = { let context_ref = context::current(); - let context = context_ref.read(token.token()); - + let mut context = context_ref.read(token.token()); + let (context, mut token) = context.token_split(); let files = context.files.read(token.token()); match files.get(event.id).ok_or(Error::new(EBADF))? { Some(file) => file.clone(), diff --git a/src/scheme/proc.rs b/src/scheme/proc.rs index b6030c072d..082e052e1e 100644 --- a/src/scheme/proc.rs +++ b/src/scheme/proc.rs @@ -834,11 +834,13 @@ impl KernelScheme for ProcScheme { } } fn extract_scheme_number(fd: usize, token: &mut CleanLockToken) -> Result<(KernelSchemes, usize)> { - let file_descriptor = context::current() - .read(token.token()) - .get_file(FileHandle::from(fd), token) - .ok_or(Error::new(EBADF))?; let (scheme_id, number) = { + let current_lock = context::current(); + let mut current = current_lock.read(token.token()); + let (context, mut token) = current.token_split(); + let file_descriptor = context + .get_file(FileHandle::from(fd), &mut token) + .ok_or(Error::new(EBADF))?; let desc = file_descriptor.description.read(token.token()); (desc.scheme, desc.number) }; diff --git a/src/scheme/sys/iostat.rs b/src/scheme/sys/iostat.rs index 455f280cc1..931ebce7ba 100644 --- a/src/scheme/sys/iostat.rs +++ b/src/scheme/sys/iostat.rs @@ -25,7 +25,8 @@ fn inner(fpath_user: UserSliceRw, token: &mut CleanLockToken) -> Result> let mut contexts = context::contexts(token.token()); let (contexts, mut token) = contexts.token_split(); for context_ref in contexts.iter().filter_map(|r| r.upgrade()) { - let context = context_ref.read(token.token()); + let mut current = context_ref.read(token.token()); + let (context, mut token) = current.token_split(); rows.push(( context.pid, context.name, diff --git a/src/scheme/user.rs b/src/scheme/user.rs index 4edac5a4f6..ef0804686c 100644 --- a/src/scheme/user.rs +++ b/src/scheme/user.rs @@ -752,11 +752,14 @@ impl UserInner { ParsedCqe::ResponseWithFd { tag, fd } => self.respond( tag, Response::Fd({ - context::current() - .read(token.token()) - .remove_file(FileHandle::from(fd), token) - .ok_or(Error::new(EINVAL))? - .description + { + let current_lock = context::current(); + let mut current = current_lock.read(token.token()); + let (context, mut token) = current.token_split(); + context.remove_file(FileHandle::from(fd), &mut token) + } + .ok_or(Error::new(EINVAL))? + .description }), token, )?, @@ -787,23 +790,28 @@ impl UserInner { // FIXME: Description can leak if there is no additional file table space. if flags.contains(FobtainFdFlags::MANUAL_FD) { - context::current().read(token.token()).insert_file( + let current_lock = context::current(); + let mut current = current_lock.read(token.token()); + let (context, mut token) = current.token_split(); + context.insert_file( FileHandle::from(dst_fd_or_ptr), FileDescriptor { description, cloexec: true, }, - token, + &mut token, ); } else { - let fd = context::current() - .read(token.token()) + let current_lock = context::current(); + let mut current = current_lock.read(token.token()); + let (context, mut token) = current.token_split(); + let fd = context .add_file( FileDescriptor { description, cloexec: true, }, - token, + &mut token, ) .ok_or(Error::new(EMFILE))?; UserSlice::wo(dst_fd_or_ptr, size_of::())?.write_usize(fd.get())?; @@ -1013,14 +1021,12 @@ impl UserInner { } let (pid, desc) = { - let context_lock = context::current(); - let mut context = context_lock.read(token.token()); - let (context, mut lock_token) = context.token_split(); - let desc = context.files.read(token.token()).find_by_scheme( - self.scheme_id, - file, - &mut lock_token, - )?; + let current_lock = context::current(); + let mut current = current_lock.read(token.token()); + let (context, mut token) = current.token_split(); + let mut files = context.files.read(token.token()); + let (files, mut token) = files.token_split(); + let desc = files.find_by_scheme(self.scheme_id, file, &mut token)?; (context.pid, desc.description) }; diff --git a/src/syscall/fs.rs b/src/syscall/fs.rs index 79a5352128..1be232fda3 100644 --- a/src/syscall/fs.rs +++ b/src/syscall/fs.rs @@ -37,10 +37,10 @@ pub fn file_op_generic_ext( ) -> Result, ) -> Result { let (file, desc) = { - let file = context::current() - .read(token.token()) - .get_file(fd, token) - .ok_or(Error::new(EBADF))?; + let current_lock = context::current(); + let mut current = current_lock.read(token.token()); + let (context, mut token) = current.token_split(); + let file = context.get_file(fd, &mut token).ok_or(Error::new(EBADF))?; let desc = *file.description.read(token.token()); (file, desc) }; @@ -73,12 +73,11 @@ pub fn openat( ) -> Result { let path_buf = copy_path_to_buf(raw_path, PATH_MAX)?; - let pipe = context::current() - .read(token.token()) - .get_file(fh, token) - .ok_or(Error::new(EBADF))?; - let (scheme_id, number) = { + let current_lock = context::current(); + let mut current = current_lock.read(token.token()); + let (context, mut token) = current.token_split(); + let pipe = context.get_file(fh, &mut token).ok_or(Error::new(EBADF))?; let desc = pipe.description.read(token.token()); (desc.scheme, desc.number) }; @@ -114,14 +113,16 @@ pub fn openat( } }; - context::current() - .read(token.token()) + let current_lock = context::current(); + let mut current = current_lock.read(token.token()); + let (context, mut token) = current.token_split(); + context .add_file( FileDescriptor { description: new_description, cloexec: flags as usize & O_CLOEXEC == O_CLOEXEC, }, - token, + &mut token, ) .ok_or(Error::new(EMFILE)) } @@ -135,12 +136,12 @@ pub fn unlinkat( token: &mut CleanLockToken, ) -> Result<()> { let path_buf = copy_path_to_buf(raw_path, PATH_MAX)?; - let pipe = context::current() - .read(token.token()) - .get_file(fh, token) - .ok_or(Error::new(EBADF))?; let (number, scheme_id) = { + let current_lock = context::current(); + let mut current = current_lock.read(token.token()); + let (context, mut token) = current.token_split(); + let pipe = context.get_file(fh, &mut token).ok_or(Error::new(EBADF))?; let desc = pipe.description.read(token.token()); (desc.number, desc.scheme) }; @@ -162,9 +163,12 @@ pub fn unlinkat( /// Close syscall pub fn close(fd: FileHandle, token: &mut CleanLockToken) -> Result<()> { let file = { - let context_lock = context::current(); - let context = context_lock.read(token.token()); - context.remove_file(fd, token).ok_or(Error::new(EBADF))? + let current_lock = context::current(); + let mut current = current_lock.read(token.token()); + let (context, mut token) = current.token_split(); + context + .remove_file(fd, &mut token) + .ok_or(Error::new(EBADF))? }; file.close(token) @@ -177,11 +181,12 @@ fn duplicate_file( token: &mut CleanLockToken, ) -> Result { let (caller_ctx, file) = { - let context_lock = context::current(); - let context = context_lock.read(token.token()); + let current_lock = context::current(); + let mut current = current_lock.read(token.token()); + let (context, mut token) = current.token_split(); ( context.caller_ctx(), - context.get_file(fd, token).ok_or(Error::new(EBADF))?, + context.get_file(fd, &mut token).ok_or(Error::new(EBADF))?, ) }; @@ -220,10 +225,11 @@ fn duplicate_file( /// Duplicate file descriptor pub fn dup(fd: FileHandle, buf: UserSliceRo, token: &mut CleanLockToken) -> Result { let new_file = duplicate_file(fd, buf, false, token)?; - - context::current() - .read(token.token()) - .add_file(new_file, token) + let current_lock = context::current(); + let mut current = current_lock.read(token.token()); + let (context, mut token) = current.token_split(); + context + .add_file(new_file, &mut token) .ok_or(Error::new(EMFILE)) } @@ -240,11 +246,11 @@ pub fn dup2( let _ = close(new_fd, token); let new_file = duplicate_file(fd, buf, false, token)?; - let context_ref = context::current(); - let context = context_ref.read(token.token()); - + let current_lock = context::current(); + let mut current = current_lock.read(token.token()); + let (context, mut token) = current.token_split(); context - .insert_file(new_fd, new_file, token) + .insert_file(new_fd, new_file, &mut token) .ok_or(Error::new(EMFILE)) } } @@ -280,13 +286,14 @@ fn call_normal( metadata: &[u64], token: &mut CleanLockToken, ) -> Result { - let file = (match ( - context::current().read(token.token()), - flags.contains(CallFlags::CONSUME), - ) { - (ctxt, true) => ctxt.remove_file(fd, token), - (ctxt, false) => ctxt.get_file(fd, token), - }) + let file = { + let current_lock = context::current(); + let mut current = current_lock.read(token.token()); + match (current.token_split(), flags.contains(CallFlags::CONSUME)) { + ((ctxt, mut token), true) => ctxt.remove_file(fd, &mut token), + ((ctxt, mut token), false) => ctxt.get_file(fd, &mut token), + } + } .ok_or(Error::new(EBADF))?; let (scheme_id, number) = { @@ -337,22 +344,25 @@ fn fdwrite_inner( let (scheme, number) = { let current_lock = context::current(); let mut current = current_lock.read(token.token()); - let (current, mut lock_token) = current.token_split(); - let file_descriptor = current.get_file(socket, token).ok_or(Error::new(EBADF))?; - let desc = &file_descriptor.description.read(lock_token.token()); + let (context, mut token) = current.token_split(); + let file_descriptor = context + .get_file(socket, &mut token) + .ok_or(Error::new(EBADF))?; + let desc = &file_descriptor.description.read(token.token()); (desc.scheme, desc.number) }; let scheme = scheme::get_scheme(token.token(), scheme)?; let current_lock = context::current(); - let current = current_lock.read(token.token()); + let mut current = current_lock.read(token.token()); + let (context, mut token) = current.token_split(); ( scheme, number, if flags.contains(CallFlags::FD_CLONE) { - current.bulk_get_files(&target_fds, token) + context.bulk_get_files(&target_fds, &mut token) } else { - current.bulk_remove_files(&target_fds, token) + context.bulk_remove_files(&target_fds, &mut token) }? .into_iter() .map(|f| f.description) @@ -389,9 +399,9 @@ fn call_fdread( let (scheme, number) = { let current_lock = context::current(); let mut current = current_lock.read(token.token()); - let (current, mut lock_token) = current.token_split(); - let file_descriptor = current.get_file(fd, token).ok_or(Error::new(EBADF))?; - let desc = file_descriptor.description.read(lock_token.token()); + let (context, mut token) = current.token_split(); + let file_descriptor = context.get_file(fd, &mut token).ok_or(Error::new(EBADF))?; + let desc = file_descriptor.description.read(token.token()); (desc.scheme, desc.number) }; let scheme = scheme::get_scheme(token.token(), scheme)?; @@ -422,10 +432,13 @@ pub fn sendfd( /// File descriptor controls pub fn fcntl(fd: FileHandle, cmd: usize, arg: usize, token: &mut CleanLockToken) -> Result { - let file = context::current() - .read(token.token()) - .get_file(fd, token) - .ok_or(Error::new(EBADF))?; + let file = { + let current_lock = context::current(); + let mut current = current_lock.read(token.token()); + let (context, mut token) = current.token_split(); + context.get_file(fd, &mut token) + } + .ok_or(Error::new(EBADF))?; let (scheme_id, number, flags) = { let desc = file.description.write(token.token()); @@ -436,11 +449,11 @@ pub fn fcntl(fd: FileHandle, cmd: usize, arg: usize, token: &mut CleanLockToken) // Not in match because 'files' cannot be locked let new_file = duplicate_file(fd, UserSlice::empty(), cmd == F_DUPFD_CLOEXEC, token)?; - let context_lock = context::current(); - let context = context_lock.read(token.token()); - + let current_lock = context::current(); + let mut current = current_lock.read(token.token()); + let (context, mut token) = current.token_split(); return context - .add_file_min(new_file, arg, token) + .add_file_min(new_file, arg, &mut token) .ok_or(Error::new(EMFILE)) .map(FileHandle::into); } @@ -454,11 +467,12 @@ pub fn fcntl(fd: FileHandle, cmd: usize, arg: usize, token: &mut CleanLockToken) // Perform kernel operation if scheme agrees { - let context_lock = context::current(); - let mut context = context_lock.read(token.token()); - let (context, mut lock_token) = context.token_split(); + let current_lock = context::current(); + let mut current = current_lock.read(token.token()); + let (context, mut token) = current.token_split(); let mut files = context.files.write(token.token()); + let (files, mut token) = files.token_split(); match *files.get_mut(fd.get()).ok_or(Error::new(EBADF))? { Some(ref mut file) => match cmd { F_GETFD => { @@ -475,7 +489,7 @@ pub fn fcntl(fd: FileHandle, cmd: usize, arg: usize, token: &mut CleanLockToken) F_GETFL => Ok(flags as usize), F_SETFL => { let new_flags = (flags & O_ACCMODE as u32) | (arg as u32 & !O_ACCMODE as u32); - file.description.write(lock_token.token()).flags = new_flags; + file.description.write(token.token()).flags = new_flags; Ok(0) } _ => Err(Error::new(EINVAL)), @@ -486,11 +500,15 @@ pub fn fcntl(fd: FileHandle, cmd: usize, arg: usize, token: &mut CleanLockToken) } pub fn flink(fd: FileHandle, raw_path: UserSliceRo, token: &mut CleanLockToken) -> Result<()> { - let caller_ctx = context::current().read(token.token()).caller_ctx(); - let file = context::current() - .read(token.token()) - .get_file(fd, token) - .ok_or(Error::new(EBADF))?; + let (caller_ctx, file) = { + let current_lock = context::current(); + let mut current = current_lock.read(token.token()); + let (context, mut token) = current.token_split(); + ( + context.caller_ctx(), + context.get_file(fd, &mut token).ok_or(Error::new(EBADF))?, + ) + }; /* let mut path_buf = BorrowedHtBuf::head()?; @@ -518,11 +536,15 @@ pub fn flink(fd: FileHandle, raw_path: UserSliceRo, token: &mut CleanLockToken) } pub fn frename(fd: FileHandle, raw_path: UserSliceRo, token: &mut CleanLockToken) -> Result<()> { - let caller_ctx = context::current().read(token.token()).caller_ctx(); - let file = context::current() - .read(token.token()) - .get_file(fd, token) - .ok_or(Error::new(EBADF))?; + let (caller_ctx, file) = { + let current_lock = context::current(); + let mut current = current_lock.read(token.token()); + let (context, mut token) = current.token_split(); + ( + context.caller_ctx(), + context.get_file(fd, &mut token).ok_or(Error::new(EBADF))?, + ) + }; /* let mut path_buf = BorrowedHtBuf::head()?; diff --git a/src/syscall/process.rs b/src/syscall/process.rs index 4ce1ee0984..fa907da17d 100644 --- a/src/syscall/process.rs +++ b/src/syscall/process.rs @@ -253,8 +253,10 @@ unsafe fn bootstrap_mem(bootstrap: &crate::Bootstrap) -> &'static [u8] { } fn insert_fd(scheme: SchemeId, number: usize, cloexec: bool, token: &mut CleanLockToken) -> usize { - context::current() - .write(token.token()) + let current_lock = context::current(); + let mut current = current_lock.read(token.token()); + let (context, mut token) = current.token_split(); + context .add_file_min( FileDescriptor { description: Arc::new(RwLock::new(FileDescription { @@ -267,7 +269,7 @@ fn insert_fd(scheme: SchemeId, number: usize, cloexec: bool, token: &mut CleanLo cloexec, }, syscall::flag::UPPER_FDTBL_TAG + scheme.get(), - token, + &mut token, ) .expect("failed to insert fd to current context") .get()