Introduce AtomicFileCreationMask

This commit is contained in:
Chen Chengjun 2025-09-22 03:38:07 +00:00 committed by Tate, Hongliang Tian
parent c56089309b
commit 4552fdb830
7 changed files with 56 additions and 25 deletions

View File

@ -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<FsResolver>,
umask: RwLock<FileCreationMask>,
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<FileCreationMask> {
&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)),
}
}
}

View File

@ -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<u16> for FileCreationMask {
type Error = crate::Error;
fn try_from(value: u16) -> Result<Self, Self::Error> {
if value & !Self::MASK != 0 {
Err(Error::with_message(
crate::Errno::EINVAL,
"Invalid FileCreationMask.",
))
} else {
Ok(Self(value))
}
}
}
impl From<FileCreationMask> 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);
});

View File

@ -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};

View File

@ -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)?;

View File

@ -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)?;

View File

@ -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()

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.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 _))
}