From bb9b9795865c1ed7533b72c24265a6e2c736ec17 Mon Sep 17 00:00:00 2001 From: Wang Siyuan Date: Wed, 24 Dec 2025 08:50:40 +0000 Subject: [PATCH] Support allocating inodes from `PseudoFs` --- kernel/src/fs/epoll/file.rs | 4 +- kernel/src/fs/notify/inotify.rs | 4 +- kernel/src/fs/pipe/anon_pipe.rs | 7 +- kernel/src/fs/procfs/mod.rs | 2 +- kernel/src/fs/pseudofs.rs | 123 ++++++++++++++++++++++---------- kernel/src/fs/ramfs/fs.rs | 2 +- kernel/src/net/socket/mod.rs | 11 ++- kernel/src/process/pid_file.rs | 4 +- kernel/src/syscall/eventfd.rs | 4 +- kernel/src/syscall/signalfd.rs | 4 +- kernel/src/time/timerfd.rs | 4 +- 11 files changed, 107 insertions(+), 62 deletions(-) diff --git a/kernel/src/fs/epoll/file.rs b/kernel/src/fs/epoll/file.rs index ee6cb6d58..34d9e3c30 100644 --- a/kernel/src/fs/epoll/file.rs +++ b/kernel/src/fs/epoll/file.rs @@ -16,7 +16,7 @@ use crate::{ file_handle::FileLike, file_table::{FdFlags, FileDesc, get_file_fast}, path::RESERVED_MOUNT_ID, - pseudofs::anon_inodefs_shared_inode, + pseudofs::AnonInodeFs, utils::{CreationFlags, Inode}, }, prelude::*, @@ -270,7 +270,7 @@ impl FileLike for EpollFile { } fn inode(&self) -> &Arc { - anon_inodefs_shared_inode() + AnonInodeFs::shared_inode() } fn dump_proc_fdinfo(self: Arc, fd_flags: FdFlags) -> Box { diff --git a/kernel/src/fs/notify/inotify.rs b/kernel/src/fs/notify/inotify.rs index 34e4ba42f..c83265295 100644 --- a/kernel/src/fs/notify/inotify.rs +++ b/kernel/src/fs/notify/inotify.rs @@ -22,7 +22,7 @@ use crate::{ file_table::FdFlags, notify::{FsEventSubscriber, FsEvents}, path::{Path, RESERVED_MOUNT_ID}, - pseudofs::anon_inodefs_shared_inode, + pseudofs::AnonInodeFs, utils::{AccessMode, CreationFlags, Inode, InodeExt, StatusFlags}, }, prelude::*, @@ -355,7 +355,7 @@ impl FileLike for InotifyFile { } fn inode(&self) -> &Arc { - anon_inodefs_shared_inode() + AnonInodeFs::shared_inode() } fn dump_proc_fdinfo(self: Arc, fd_flags: FdFlags) -> Box { diff --git a/kernel/src/fs/pipe/anon_pipe.rs b/kernel/src/fs/pipe/anon_pipe.rs index de10d6652..5dee1ade6 100644 --- a/kernel/src/fs/pipe/anon_pipe.rs +++ b/kernel/src/fs/pipe/anon_pipe.rs @@ -15,7 +15,7 @@ use crate::{ file_table::FdFlags, path::RESERVED_MOUNT_ID, pipe::{Pipe, common::PipeHandle}, - pseudofs::{PseudoInode, pipefs_singleton}, + pseudofs::{PipeFs, PseudoInode}, utils::{ AccessMode, CreationFlags, Extension, FileSystem, Inode, InodeIo, InodeMode, InodeType, Metadata, StatusFlags, mkmod, @@ -185,14 +185,11 @@ impl AnonPipeInode { fn new() -> Self { let pipe = Pipe::new(); - let pseudo_inode = PseudoInode::new( - 0, + let pseudo_inode = PipeFs::singleton().alloc_inode( InodeType::NamedPipe, mkmod!(u+rw), Uid::new_root(), Gid::new_root(), - aster_block::BLOCK_SIZE, - Arc::downgrade(pipefs_singleton()), ); Self { pipe, pseudo_inode } diff --git a/kernel/src/fs/procfs/mod.rs b/kernel/src/fs/procfs/mod.rs index ca0f65a20..690ffb14c 100644 --- a/kernel/src/fs/procfs/mod.rs +++ b/kernel/src/fs/procfs/mod.rs @@ -83,7 +83,7 @@ impl ProcFs { } pub(self) fn alloc_id(&self) -> u64 { - self.inode_allocator.fetch_add(1, Ordering::SeqCst) + self.inode_allocator.fetch_add(1, Ordering::Relaxed) } } diff --git a/kernel/src/fs/pseudofs.rs b/kernel/src/fs/pseudofs.rs index e3d8b1248..ac2220a7a 100644 --- a/kernel/src/fs/pseudofs.rs +++ b/kernel/src/fs/pseudofs.rs @@ -1,6 +1,9 @@ // SPDX-License-Identifier: MPL-2.0 -use core::time::Duration; +use core::{ + sync::atomic::{AtomicU64, Ordering}, + time::Duration, +}; use spin::Once; @@ -23,6 +26,7 @@ pub struct PseudoFs { name: &'static str, sb: SuperBlock, root: Arc, + inode_allocator: AtomicU64, fs_event_subscriber_stats: FsEventSubscriberStats, } @@ -56,62 +60,106 @@ impl PseudoFs { name: &'static str, magic: u64, ) -> &'static Arc { + // Reference: fs.call_once(|| { Arc::new_cyclic(|weak_fs: &Weak| Self { name, sb: SuperBlock::new(magic, aster_block::BLOCK_SIZE, NAME_MAX), root: Arc::new(PseudoInode::new( - 0, - InodeType::Unknown, + ROOT_INO, + InodeType::Dir, mkmod!(u+rw), Uid::new_root(), Gid::new_root(), - aster_block::BLOCK_SIZE, weak_fs.clone(), )), + inode_allocator: AtomicU64::new(ROOT_INO + 1), fs_event_subscriber_stats: FsEventSubscriberStats::new(), }) }) } + + pub fn alloc_inode( + self: &Arc, + type_: InodeType, + mode: InodeMode, + uid: Uid, + gid: Gid, + ) -> PseudoInode { + PseudoInode::new(self.alloc_id(), type_, mode, uid, gid, Arc::downgrade(self)) + } + + fn alloc_id(&self) -> u64 { + self.inode_allocator.fetch_add(1, Ordering::Relaxed) + } } -/// Returns the singleton instance of the anonymous pipe file system. -pub fn pipefs_singleton() -> &'static Arc { - static PIPEFS: Once> = Once::new(); - - PseudoFs::singleton(&PIPEFS, "pipefs", PIPEFS_MAGIC) +pub(super) struct PipeFs { + _private: (), } -/// Returns the singleton instance of the socket file system. -pub fn sockfs_singleton() -> &'static Arc { - static SOCKFS: Once> = Once::new(); +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(&SOCKFS, "sockfs", SOCKFS_MAGIC) + PseudoFs::singleton(&PIPEFS, "pipefs", PIPEFS_MAGIC) + } } -/// Returns the singleton instance of the anonymous inode file system. -fn anon_inodefs_singleton() -> &'static Arc { - static ANON_INODEFS: Once> = Once::new(); - - PseudoFs::singleton(&ANON_INODEFS, "anon_inodefs", ANON_INODEFS_MAGIC) +pub struct SockFs { + _private: (), } -/// 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 anon_inodefs_shared_inode() -> &'static Arc { - &anon_inodefs_singleton().root +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) + } +} + +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) + } + + /// 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( + InodeType::Unknown, + mkmod!(u+rw), + Uid::new_root(), + Gid::new_root(), + ); + + Arc::new(shared_inode) + }) + } } pub(super) fn init() { @@ -171,6 +219,8 @@ impl FsType for SockFsType { } } +/// Root Inode ID. +const ROOT_INO: u64 = 1; // Reference: const PIPEFS_MAGIC: u64 = 0x50495045; // Reference: @@ -186,13 +236,12 @@ pub struct PseudoInode { } impl PseudoInode { - pub fn new( + fn new( ino: u64, type_: InodeType, mode: InodeMode, uid: Uid, gid: Gid, - blk_size: usize, fs: Weak, ) -> Self { let now = now(); @@ -200,7 +249,7 @@ impl PseudoInode { dev: 0, ino, size: 0, - blk_size, + blk_size: aster_block::BLOCK_SIZE, blocks: 0, atime: now, mtime: now, diff --git a/kernel/src/fs/ramfs/fs.rs b/kernel/src/fs/ramfs/fs.rs index 355062b84..725ccc2fd 100644 --- a/kernel/src/fs/ramfs/fs.rs +++ b/kernel/src/fs/ramfs/fs.rs @@ -73,7 +73,7 @@ impl RamFs { } fn alloc_id(&self) -> u64 { - self.inode_allocator.fetch_add(1, Ordering::SeqCst) + self.inode_allocator.fetch_add(1, Ordering::Relaxed) } } diff --git a/kernel/src/net/socket/mod.rs b/kernel/src/net/socket/mod.rs index 58ee046ea..cd0f0933d 100644 --- a/kernel/src/net/socket/mod.rs +++ b/kernel/src/net/socket/mod.rs @@ -10,7 +10,7 @@ use crate::{ file_handle::FileLike, file_table::FdFlags, path::RESERVED_MOUNT_ID, - pseudofs::{PseudoInode, sockfs_singleton}, + pseudofs::SockFs, utils::{CreationFlags, Inode, InodeType, StatusFlags, mkmod}, }, prelude::*, @@ -210,13 +210,12 @@ impl FileLike for T { /// Creates a new pseudo inode for a socket. fn new_pseudo_inode() -> Arc { - Arc::new(PseudoInode::new( - 0, + let pseudo_inode = SockFs::singleton().alloc_inode( InodeType::Socket, mkmod!(a+rwx), Uid::new_root(), Gid::new_root(), - aster_block::BLOCK_SIZE, - Arc::downgrade(sockfs_singleton()), - )) + ); + + Arc::new(pseudo_inode) } diff --git a/kernel/src/process/pid_file.rs b/kernel/src/process/pid_file.rs index f97aeb9b0..345ef094b 100644 --- a/kernel/src/process/pid_file.rs +++ b/kernel/src/process/pid_file.rs @@ -11,7 +11,7 @@ use crate::{ file_handle::FileLike, file_table::FdFlags, path::RESERVED_MOUNT_ID, - pseudofs::anon_inodefs_shared_inode, + pseudofs::AnonInodeFs, utils::{CreationFlags, Inode, StatusFlags}, }, prelude::*, @@ -95,7 +95,7 @@ impl FileLike for PidFile { } fn inode(&self) -> &Arc { - anon_inodefs_shared_inode() + AnonInodeFs::shared_inode() } fn dump_proc_fdinfo(self: Arc, fd_flags: FdFlags) -> Box { diff --git a/kernel/src/syscall/eventfd.rs b/kernel/src/syscall/eventfd.rs index 5b1f50bfd..ce8eabbac 100644 --- a/kernel/src/syscall/eventfd.rs +++ b/kernel/src/syscall/eventfd.rs @@ -25,7 +25,7 @@ use crate::{ file_handle::FileLike, file_table::{FdFlags, FileDesc}, path::RESERVED_MOUNT_ID, - pseudofs::anon_inodefs_shared_inode, + pseudofs::AnonInodeFs, utils::{CreationFlags, Inode, StatusFlags}, }, prelude::*, @@ -232,7 +232,7 @@ impl FileLike for EventFile { } fn inode(&self) -> &Arc { - anon_inodefs_shared_inode() + AnonInodeFs::shared_inode() } fn dump_proc_fdinfo(self: Arc, fd_flags: FdFlags) -> Box { diff --git a/kernel/src/syscall/signalfd.rs b/kernel/src/syscall/signalfd.rs index 312d7b0b6..d15c1c943 100644 --- a/kernel/src/syscall/signalfd.rs +++ b/kernel/src/syscall/signalfd.rs @@ -21,7 +21,7 @@ use crate::{ file_handle::FileLike, file_table::{FdFlags, FileDesc, get_file_fast}, path::RESERVED_MOUNT_ID, - pseudofs::anon_inodefs_shared_inode, + pseudofs::AnonInodeFs, utils::{CreationFlags, Inode, StatusFlags}, }, prelude::*, @@ -264,7 +264,7 @@ impl FileLike for SignalFile { } fn inode(&self) -> &Arc { - anon_inodefs_shared_inode() + AnonInodeFs::shared_inode() } fn dump_proc_fdinfo(self: Arc, fd_flags: FdFlags) -> Box { diff --git a/kernel/src/time/timerfd.rs b/kernel/src/time/timerfd.rs index 57f49eb40..4e80bf892 100644 --- a/kernel/src/time/timerfd.rs +++ b/kernel/src/time/timerfd.rs @@ -15,7 +15,7 @@ use crate::{ file_handle::FileLike, file_table::FdFlags, path::RESERVED_MOUNT_ID, - pseudofs::anon_inodefs_shared_inode, + pseudofs::AnonInodeFs, utils::{CreationFlags, Inode, StatusFlags}, }, prelude::*, @@ -252,7 +252,7 @@ impl FileLike for TimerfdFile { } fn inode(&self) -> &Arc { - anon_inodefs_shared_inode() + AnonInodeFs::shared_inode() } fn dump_proc_fdinfo(self: Arc, fd_flags: FdFlags) -> Box {