diff --git a/kernel/src/fs/thread_info.rs b/kernel/src/fs/thread_info.rs index 8275cd005..596c3c6d9 100644 --- a/kernel/src/fs/thread_info.rs +++ b/kernel/src/fs/thread_info.rs @@ -1,13 +1,16 @@ // SPDX-License-Identifier: MPL-2.0 -use ostd::sync::{RwLock, RwMutex}; +use core::sync::atomic::Ordering; -use super::{fs_resolver::FsResolver, utils::FileCreationMask}; +use ostd::sync::RwMutex; + +use super::{fs_resolver::FsResolver, utils::AtomicFileCreationMask}; +use crate::fs::utils::FileCreationMask; /// FS information for a POSIX thread. pub struct ThreadFsInfo { resolver: RwMutex, - umask: RwLock, + umask: AtomicFileCreationMask, } impl ThreadFsInfo { @@ -15,7 +18,7 @@ impl ThreadFsInfo { pub fn new(fs_resolver: FsResolver) -> Self { Self { resolver: RwMutex::new(fs_resolver), - umask: RwLock::new(FileCreationMask::default()), + umask: AtomicFileCreationMask::new(FileCreationMask::default()), } } @@ -25,8 +28,13 @@ impl ThreadFsInfo { } /// Returns the associated `FileCreationMask`. - pub fn umask(&self) -> &RwLock { - &self.umask + pub fn umask(&self) -> FileCreationMask { + self.umask.load(Ordering::Acquire) + } + + /// Sets a new `FileCreationMask`, returning the old one. + pub fn swap_umask(&self, new_mask: FileCreationMask) -> FileCreationMask { + self.umask.swap(new_mask, Ordering::AcqRel) } } @@ -34,7 +42,7 @@ impl Clone for ThreadFsInfo { fn clone(&self) -> Self { Self { resolver: RwMutex::new(self.resolver.read().clone()), - umask: RwLock::new(FileCreationMask::new(self.umask.read().get())), + umask: AtomicFileCreationMask::new(self.umask.load(Ordering::Acquire)), } } } diff --git a/kernel/src/fs/utils/file_creation_mask.rs b/kernel/src/fs/utils/file_creation_mask.rs index 42e54bb90..4f4f944bc 100644 --- a/kernel/src/fs/utils/file_creation_mask.rs +++ b/kernel/src/fs/utils/file_creation_mask.rs @@ -1,28 +1,24 @@ // SPDX-License-Identifier: MPL-2.0 +use core::sync::atomic::AtomicU16; + +use atomic_integer_wrapper::define_atomic_version_of_integer_like_type; + +use crate::error::Error; + /// A mask for the file mode of a newly-created file or directory. /// /// This mask is always a subset of `0o777`. pub struct FileCreationMask(u16); impl FileCreationMask { - // Creates a new instance, the initial value is `0o777`. - pub fn new(val: u16) -> Self { - Self(0o777 & val) - } + /// The valid bits of a `FileCreationMask`. + const MASK: u16 = 0o777; /// Get a new value. pub fn get(&self) -> u16 { self.0 } - - /// Set a new value. - pub fn set(&mut self, new_mask: u16) -> u16 { - let new_mask = new_mask & 0o777; - let old_mask = self.0; - self.0 = new_mask; - old_mask - } } impl Default for FileCreationMask { @@ -30,3 +26,30 @@ impl Default for FileCreationMask { Self(0o022) } } + +impl TryFrom for FileCreationMask { + type Error = crate::Error; + + fn try_from(value: u16) -> Result { + if value & !Self::MASK != 0 { + Err(Error::with_message( + crate::Errno::EINVAL, + "Invalid FileCreationMask.", + )) + } else { + Ok(Self(value)) + } + } +} + +impl From for u16 { + fn from(value: FileCreationMask) -> Self { + value.0 + } +} + +define_atomic_version_of_integer_like_type!(FileCreationMask, try_from = true, { + /// An atomic version of `FileCreationMask`. + #[derive(Debug)] + pub struct AtomicFileCreationMask(AtomicU16); +}); diff --git a/kernel/src/fs/utils/mod.rs b/kernel/src/fs/utils/mod.rs index 48bae923a..4cf27eaad 100644 --- a/kernel/src/fs/utils/mod.rs +++ b/kernel/src/fs/utils/mod.rs @@ -8,7 +8,7 @@ pub use dirent_visitor::{DirentCounter, DirentVisitor}; pub use direntry_vec::DirEntryVecExt; pub use endpoint::{Endpoint, EndpointState}; pub use falloc_mode::FallocMode; -pub use file_creation_mask::FileCreationMask; +pub use file_creation_mask::{AtomicFileCreationMask, FileCreationMask}; pub use flock::{FlockItem, FlockList, FlockType}; pub use fs::{FileSystem, FsFlags, SuperBlock}; pub use inode::{Extension, Inode, InodeType, Metadata, MknodType, Permission}; diff --git a/kernel/src/syscall/mkdir.rs b/kernel/src/syscall/mkdir.rs index 8c8684af4..00a237a06 100644 --- a/kernel/src/syscall/mkdir.rs +++ b/kernel/src/syscall/mkdir.rs @@ -34,7 +34,7 @@ pub fn sys_mkdirat( }; let inode_mode = { - let mask_mode = mode & !fs_ref.umask().read().get(); + let mask_mode = mode & !fs_ref.umask().get(); InodeMode::from_bits_truncate(mask_mode) }; let _ = dir_path.new_fs_child(name.trim_end_matches('/'), InodeType::Dir, inode_mode)?; diff --git a/kernel/src/syscall/mknod.rs b/kernel/src/syscall/mknod.rs index 0d7e62342..67abbff64 100644 --- a/kernel/src/syscall/mknod.rs +++ b/kernel/src/syscall/mknod.rs @@ -23,7 +23,7 @@ pub fn sys_mknodat( let path_name = ctx.user_space().read_cstring(path_addr, MAX_FILENAME_LEN)?; let fs_ref = ctx.thread_local.borrow_fs(); let inode_mode = { - let mask_mode = mode & !fs_ref.umask().read().get(); + let mask_mode = mode & !fs_ref.umask().get(); InodeMode::from_bits_truncate(mask_mode) }; let inode_type = InodeType::from_raw_mode(mode)?; diff --git a/kernel/src/syscall/open.rs b/kernel/src/syscall/open.rs index 80e6742c6..13fd3bd0c 100644 --- a/kernel/src/syscall/open.rs +++ b/kernel/src/syscall/open.rs @@ -32,7 +32,7 @@ pub fn sys_openat( let path = path.to_string_lossy(); let fs_path = FsPath::new(dirfd, path.as_ref())?; let fs_ref = ctx.thread_local.borrow_fs(); - let mask_mode = mode & !fs_ref.umask().read().get(); + let mask_mode = mode & !fs_ref.umask().get(); let inode_handle = fs_ref .resolver() .read() diff --git a/kernel/src/syscall/umask.rs b/kernel/src/syscall/umask.rs index 399cbfa24..978f6f217 100644 --- a/kernel/src/syscall/umask.rs +++ b/kernel/src/syscall/umask.rs @@ -5,6 +5,6 @@ use crate::prelude::*; pub fn sys_umask(mask: u16, ctx: &Context) -> Result { debug!("mask = 0o{:o}", mask); - let old_mask = ctx.thread_local.borrow_fs().umask().write().set(mask); - Ok(SyscallReturn::Return(old_mask as _)) + let old_mask = ctx.thread_local.borrow_fs().swap_umask(mask.try_into()?); + Ok(SyscallReturn::Return(old_mask.get() as _)) }