From 9c99e782ed04e1232148ad6660ced289b78259be Mon Sep 17 00:00:00 2001 From: Jianfeng Jiang Date: Mon, 9 Feb 2026 06:41:07 +0000 Subject: [PATCH] Split pseudofs.rs into several modules --- kernel/src/fs/pseudofs/anon_inode_fs.rs | 74 ++++++ .../src/fs/{pseudofs.rs => pseudofs/mod.rs} | 241 +----------------- kernel/src/fs/pseudofs/pidfdfs.rs | 61 +++++ kernel/src/fs/pseudofs/pipefs.rs | 71 ++++++ kernel/src/fs/pseudofs/sockfs.rs | 78 ++++++ 5 files changed, 297 insertions(+), 228 deletions(-) create mode 100644 kernel/src/fs/pseudofs/anon_inode_fs.rs rename kernel/src/fs/{pseudofs.rs => pseudofs/mod.rs} (50%) create mode 100644 kernel/src/fs/pseudofs/pidfdfs.rs create mode 100644 kernel/src/fs/pseudofs/pipefs.rs create mode 100644 kernel/src/fs/pseudofs/sockfs.rs diff --git a/kernel/src/fs/pseudofs/anon_inode_fs.rs b/kernel/src/fs/pseudofs/anon_inode_fs.rs new file mode 100644 index 000000000..df911ebdf --- /dev/null +++ b/kernel/src/fs/pseudofs/anon_inode_fs.rs @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: MPL-2.0 + +use spin::Once; + +use crate::{ + fs::{ + path::{Mount, Path}, + pseudofs::{PseudoFs, PseudoInodeType}, + utils::{Inode, mkmod}, + }, + prelude::*, + process::{Gid, Uid}, +}; + +pub struct AnonInodeFs { + _private: (), +} + +impl AnonInodeFs { + /// Returns the singleton instance of the anonymous inode file system. + fn singleton() -> &'static Arc { + static ANON_INODEFS: Once> = Once::new(); + + PseudoFs::singleton(&ANON_INODEFS, "anon_inodefs", ANON_INODEFS_MAGIC) + } + + /// Creates a pseudo `Path` for the shared inode. + pub fn new_path(name_fn: fn(&dyn Inode) -> String) -> Path { + Path::new_pseudo( + Self::mount_node().clone(), + Self::shared_inode().clone(), + name_fn, + ) + } + + /// Returns the pseudo mount node of the anonymous inode file system. + pub fn mount_node() -> &'static Arc { + static ANON_INODEFS_MOUNT: Once> = Once::new(); + + ANON_INODEFS_MOUNT.call_once(|| Mount::new_pseudo(Self::singleton().clone())) + } + + /// Returns the shared inode of the anonymous inode file system singleton. + // + // Some members of anon_inodefs (such as epollfd, eventfd, timerfd, etc.) share + // the same inode. The sharing is not only within the same category (e.g., two + // epollfds share the same inode) but also across different categories (e.g., + // an epollfd and a timerfd share the same inode). Even across namespaces, this + // inode is still shared. Although this Linux behavior is a bit odd, we keep it + // for compatibility. + // + // A small subset of members in anon_inodefs (i.e., userfaultfd, io_uring, and + // kvm_guest_memfd) have their own dedicated inodes. We need to support creating + // independent inodes within anon_inodefs for them in the future. + // + // Reference: + pub fn shared_inode() -> &'static Arc { + static SHARED_INODE: Once> = Once::new(); + + SHARED_INODE.call_once(|| { + let shared_inode = Self::singleton().alloc_inode( + PseudoInodeType::AnonInode, + mkmod!(u+rw), + Uid::new_root(), + Gid::new_root(), + ); + + Arc::new(shared_inode) + }) + } +} + +// Reference: +const ANON_INODEFS_MAGIC: u64 = 0x09041934; diff --git a/kernel/src/fs/pseudofs.rs b/kernel/src/fs/pseudofs/mod.rs similarity index 50% rename from kernel/src/fs/pseudofs.rs rename to kernel/src/fs/pseudofs/mod.rs index d34ef12ce..046f57ecb 100644 --- a/kernel/src/fs/pseudofs.rs +++ b/kernel/src/fs/pseudofs/mod.rs @@ -1,23 +1,25 @@ // SPDX-License-Identifier: MPL-2.0 -use alloc::format; use core::{ sync::atomic::{AtomicU64, Ordering}, time::Duration, }; +pub use anon_inode_fs::AnonInodeFs; +pub use pidfdfs::PidfdFs; +pub(super) use pipefs::PipeFs; +use pipefs::PipeFsType; +pub use sockfs::SockFs; +use sockfs::SockFsType; use spin::Once; use super::utils::{Extension, InodeIo, StatusFlags}; use crate::{ fs::{ inode_handle::FileIo, - path::{Mount, Path}, - pipe::AnonPipeInode, - registry::{FsProperties, FsType}, utils::{ - AccessMode, FileSystem, FsEventSubscriberStats, FsFlags, Inode, InodeMode, InodeType, - Metadata, NAME_MAX, SuperBlock, mkmod, + AccessMode, FileSystem, FsEventSubscriberStats, Inode, InodeMode, InodeType, Metadata, + NAME_MAX, SuperBlock, mkmod, }, }, prelude::*, @@ -25,6 +27,11 @@ use crate::{ time::clocks::RealTimeCoarseClock, }; +mod anon_inode_fs; +mod pidfdfs; +mod pipefs; +mod sockfs; + /// A pseudo file system that manages pseudo inodes, such as pipe inodes and socket inodes. pub struct PseudoFs { name: &'static str, @@ -98,170 +105,6 @@ impl PseudoFs { } } -pub(super) struct PipeFs { - _private: (), -} - -impl PipeFs { - /// Returns the singleton instance of the anonymous pipe file system. - pub(super) fn singleton() -> &'static Arc { - static PIPEFS: Once> = Once::new(); - - PseudoFs::singleton(&PIPEFS, "pipefs", PIPEFS_MAGIC) - } - - /// Creates a pseudo `Path` for an anonymous pipe. - pub(super) fn new_path(pipe_inode: Arc) -> Path { - Path::new_pseudo(Self::mount_node().clone(), pipe_inode, |inode| { - format!("pipe:[{}]", inode.ino()) - }) - } - - /// Returns the pseudo mount node of the pipe file system. - fn mount_node() -> &'static Arc { - static PIPEFS_MOUNT: Once> = Once::new(); - - PIPEFS_MOUNT.call_once(|| Mount::new_pseudo(Self::singleton().clone())) - } -} - -pub struct SockFs { - _private: (), -} - -impl SockFs { - /// Returns the singleton instance of the socket file system. - pub fn singleton() -> &'static Arc { - static SOCKFS: Once> = Once::new(); - - PseudoFs::singleton(&SOCKFS, "sockfs", SOCKFS_MAGIC) - } - - /// Creates a pseudo `Path` for a socket. - pub fn new_path() -> Path { - let socket_inode = Arc::new(Self::singleton().alloc_inode( - PseudoInodeType::Socket, - mkmod!(a+rwx), - Uid::new_root(), - Gid::new_root(), - )); - - Path::new_pseudo(Self::mount_node().clone(), socket_inode, |inode| { - format!("socket:[{}]", inode.ino()) - }) - } - - /// Returns the pseudo mount node of the socket file system. - pub fn mount_node() -> &'static Arc { - static SOCKFS_MOUNT: Once> = Once::new(); - - SOCKFS_MOUNT.call_once(|| Mount::new_pseudo(Self::singleton().clone())) - } -} - -pub struct AnonInodeFs { - _private: (), -} - -impl AnonInodeFs { - /// Returns the singleton instance of the anonymous inode file system. - fn singleton() -> &'static Arc { - static ANON_INODEFS: Once> = Once::new(); - - PseudoFs::singleton(&ANON_INODEFS, "anon_inodefs", ANON_INODEFS_MAGIC) - } - - /// Creates a pseudo `Path` for the shared inode. - pub fn new_path(name_fn: fn(&dyn Inode) -> String) -> Path { - Path::new_pseudo( - Self::mount_node().clone(), - Self::shared_inode().clone(), - name_fn, - ) - } - - /// Returns the pseudo mount node of the anonymous inode file system. - pub fn mount_node() -> &'static Arc { - static ANON_INODEFS_MOUNT: Once> = Once::new(); - - ANON_INODEFS_MOUNT.call_once(|| Mount::new_pseudo(Self::singleton().clone())) - } - - /// Returns the shared inode of the anonymous inode file system singleton. - // - // Some members of anon_inodefs (such as epollfd, eventfd, timerfd, etc.) share - // the same inode. The sharing is not only within the same category (e.g., two - // epollfds share the same inode) but also across different categories (e.g., - // an epollfd and a timerfd share the same inode). Even across namespaces, this - // inode is still shared. Although this Linux behavior is a bit odd, we keep it - // for compatibility. - // - // A small subset of members in anon_inodefs (i.e., userfaultfd, io_uring, and - // kvm_guest_memfd) have their own dedicated inodes. We need to support creating - // independent inodes within anon_inodefs for them in the future. - // - // Reference: - pub fn shared_inode() -> &'static Arc { - static SHARED_INODE: Once> = Once::new(); - - SHARED_INODE.call_once(|| { - let shared_inode = Self::singleton().alloc_inode( - PseudoInodeType::AnonInode, - mkmod!(u+rw), - Uid::new_root(), - Gid::new_root(), - ); - - Arc::new(shared_inode) - }) - } -} - -pub struct PidfdFs { - _private: (), -} - -impl PidfdFs { - /// Returns the singleton instance of the pidfd file system. - pub fn singleton() -> &'static Arc { - static PIDFDFS: Once> = Once::new(); - - PseudoFs::singleton(&PIDFDFS, "pidfdfs", PIDFDFS_MAGIC) - } - - /// Creates a pseudo `Path` for a pidfd. - pub fn new_path(name_fn: fn(&dyn Inode) -> String) -> Path { - Path::new_pseudo( - Self::mount_node().clone(), - Self::shared_inode().clone(), - name_fn, - ) - } - - /// Returns the pseudo mount node of the pidfd file system. - pub fn mount_node() -> &'static Arc { - static PIDFDFS_MOUNT: Once> = Once::new(); - - PIDFDFS_MOUNT.call_once(|| Mount::new_pseudo(Self::singleton().clone())) - } - - /// Returns the shared inode of the pidfd file system. - pub fn shared_inode() -> &'static Arc { - static SHARED_INODE: Once> = Once::new(); - - SHARED_INODE.call_once(|| { - let pidfd_inode = Self::singleton().alloc_inode( - PseudoInodeType::Pidfd, - mkmod!(u+rwx), - Uid::new_root(), - Gid::new_root(), - ); - - Arc::new(pidfd_inode) - }) - } -} - pub(super) fn init() { super::registry::register(&PipeFsType).unwrap(); super::registry::register(&SockFsType).unwrap(); @@ -269,66 +112,8 @@ pub(super) fn init() { // Reference: } -pub(super) struct PipeFsType; - -impl FsType for PipeFsType { - fn name(&self) -> &'static str { - "pipefs" - } - - fn properties(&self) -> FsProperties { - FsProperties::empty() - } - - fn create( - &self, - _flags: FsFlags, - _args: Option, - _disk: Option>, - ) -> Result> { - return_errno_with_message!(Errno::EINVAL, "pipefs cannot be mounted"); - } - - fn sysnode(&self) -> Option> { - None - } -} - -pub(super) struct SockFsType; - -impl FsType for SockFsType { - fn name(&self) -> &'static str { - "sockfs" - } - - fn properties(&self) -> FsProperties { - FsProperties::empty() - } - - fn create( - &self, - _flags: FsFlags, - _args: Option, - _disk: Option>, - ) -> Result> { - return_errno_with_message!(Errno::EINVAL, "sockfs cannot be mounted"); - } - - fn sysnode(&self) -> Option> { - None - } -} - /// Root Inode ID. const ROOT_INO: u64 = 1; -// Reference: -const PIPEFS_MAGIC: u64 = 0x50495045; -// Reference: -const SOCKFS_MAGIC: u64 = 0x534F434B; -// Reference: -const ANON_INODEFS_MAGIC: u64 = 0x09041934; -// Reference: -const PIDFDFS_MAGIC: u64 = 0x50494446; #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum PseudoInodeType { diff --git a/kernel/src/fs/pseudofs/pidfdfs.rs b/kernel/src/fs/pseudofs/pidfdfs.rs new file mode 100644 index 000000000..638b89fa8 --- /dev/null +++ b/kernel/src/fs/pseudofs/pidfdfs.rs @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: MPL-2.0 + +use spin::Once; + +use crate::{ + fs::{ + path::{Mount, Path}, + pseudofs::{PseudoFs, PseudoInodeType}, + utils::{Inode, mkmod}, + }, + prelude::*, + process::{Gid, Uid}, +}; + +pub struct PidfdFs { + _private: (), +} + +impl PidfdFs { + /// Returns the singleton instance of the pidfd file system. + pub fn singleton() -> &'static Arc { + static PIDFDFS: Once> = Once::new(); + + PseudoFs::singleton(&PIDFDFS, "pidfdfs", PIDFDFS_MAGIC) + } + + /// Creates a pseudo `Path` for a pidfd. + pub fn new_path(name_fn: fn(&dyn Inode) -> String) -> Path { + Path::new_pseudo( + Self::mount_node().clone(), + Self::shared_inode().clone(), + name_fn, + ) + } + + /// Returns the pseudo mount node of the pidfd file system. + pub fn mount_node() -> &'static Arc { + static PIDFDFS_MOUNT: Once> = Once::new(); + + PIDFDFS_MOUNT.call_once(|| Mount::new_pseudo(Self::singleton().clone())) + } + + /// Returns the shared inode of the pidfd file system. + pub fn shared_inode() -> &'static Arc { + static SHARED_INODE: Once> = Once::new(); + + SHARED_INODE.call_once(|| { + let pidfd_inode = Self::singleton().alloc_inode( + PseudoInodeType::Pidfd, + mkmod!(u+rwx), + Uid::new_root(), + Gid::new_root(), + ); + + Arc::new(pidfd_inode) + }) + } +} + +// Reference: +const PIDFDFS_MAGIC: u64 = 0x50494446; diff --git a/kernel/src/fs/pseudofs/pipefs.rs b/kernel/src/fs/pseudofs/pipefs.rs new file mode 100644 index 000000000..15477c1c4 --- /dev/null +++ b/kernel/src/fs/pseudofs/pipefs.rs @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: MPL-2.0 + +use alloc::format; + +use spin::Once; + +use crate::{ + fs::{ + path::{Mount, Path}, + pipe::AnonPipeInode, + pseudofs::PseudoFs, + registry::{FsProperties, FsType}, + utils::{FileSystem, FsFlags}, + }, + prelude::*, +}; + +pub(in crate::fs) struct PipeFs { + _private: (), +} + +impl PipeFs { + /// Returns the singleton instance of the anonymous pipe file system. + pub(in crate::fs) fn singleton() -> &'static Arc { + static PIPEFS: Once> = Once::new(); + + PseudoFs::singleton(&PIPEFS, "pipefs", PIPEFS_MAGIC) + } + + /// Creates a pseudo `Path` for an anonymous pipe. + pub(in crate::fs) fn new_path(pipe_inode: Arc) -> Path { + Path::new_pseudo(Self::mount_node().clone(), pipe_inode, |inode| { + format!("pipe:[{}]", inode.ino()) + }) + } + + /// Returns the pseudo mount node of the pipe file system. + fn mount_node() -> &'static Arc { + static PIPEFS_MOUNT: Once> = Once::new(); + + PIPEFS_MOUNT.call_once(|| Mount::new_pseudo(Self::singleton().clone())) + } +} + +pub(super) struct PipeFsType; + +impl FsType for PipeFsType { + fn name(&self) -> &'static str { + "pipefs" + } + + fn properties(&self) -> FsProperties { + FsProperties::empty() + } + + fn create( + &self, + _flags: FsFlags, + _args: Option, + _disk: Option>, + ) -> Result> { + return_errno_with_message!(Errno::EINVAL, "pipefs cannot be mounted"); + } + + fn sysnode(&self) -> Option> { + None + } +} + +// Reference: +const PIPEFS_MAGIC: u64 = 0x50495045; diff --git a/kernel/src/fs/pseudofs/sockfs.rs b/kernel/src/fs/pseudofs/sockfs.rs new file mode 100644 index 000000000..5933eea96 --- /dev/null +++ b/kernel/src/fs/pseudofs/sockfs.rs @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: MPL-2.0 + +use alloc::format; + +use spin::Once; + +use crate::{ + fs::{ + path::{Mount, Path}, + pseudofs::{PseudoFs, PseudoInodeType}, + registry::{FsProperties, FsType}, + utils::{FileSystem, FsFlags, mkmod}, + }, + prelude::*, + process::{Gid, Uid}, +}; + +pub struct SockFs { + _private: (), +} + +impl SockFs { + /// Returns the singleton instance of the socket file system. + pub fn singleton() -> &'static Arc { + static SOCKFS: Once> = Once::new(); + + PseudoFs::singleton(&SOCKFS, "sockfs", SOCKFS_MAGIC) + } + + /// Creates a pseudo `Path` for a socket. + pub fn new_path() -> Path { + let socket_inode = Arc::new(Self::singleton().alloc_inode( + PseudoInodeType::Socket, + mkmod!(a+rwx), + Uid::new_root(), + Gid::new_root(), + )); + + Path::new_pseudo(Self::mount_node().clone(), socket_inode, |inode| { + format!("socket:[{}]", inode.ino()) + }) + } + + /// Returns the pseudo mount node of the socket file system. + pub fn mount_node() -> &'static Arc { + static SOCKFS_MOUNT: Once> = Once::new(); + + SOCKFS_MOUNT.call_once(|| Mount::new_pseudo(Self::singleton().clone())) + } +} + +pub(super) struct SockFsType; + +impl FsType for SockFsType { + fn name(&self) -> &'static str { + "sockfs" + } + + fn properties(&self) -> FsProperties { + FsProperties::empty() + } + + fn create( + &self, + _flags: FsFlags, + _args: Option, + _disk: Option>, + ) -> Result> { + return_errno_with_message!(Errno::EINVAL, "sockfs cannot be mounted"); + } + + fn sysnode(&self) -> Option> { + None + } +} + +// Reference: +const SOCKFS_MAGIC: u64 = 0x534F434B;