Apply pseudo `Path` to members of `anon_inodefs`

This commit is contained in:
Wang Siyuan 2025-12-26 11:16:16 +00:00
parent 647b7dfc77
commit 0e291b692e
9 changed files with 64 additions and 38 deletions

View File

@ -15,7 +15,7 @@ use crate::{
fs::{ fs::{
file_handle::FileLike, file_handle::FileLike,
file_table::{FdFlags, FileDesc, get_file_fast}, file_table::{FdFlags, FileDesc, get_file_fast},
path::RESERVED_MOUNT_ID, path::Path,
pseudofs::AnonInodeFs, pseudofs::AnonInodeFs,
utils::{CreationFlags, Inode}, utils::{CreationFlags, Inode},
}, },
@ -47,14 +47,19 @@ pub struct EpollFile {
// Keep this in a separate `Arc` to avoid dropping `EpollFile` in the observer callback, which // Keep this in a separate `Arc` to avoid dropping `EpollFile` in the observer callback, which
// may cause deadlocks. // may cause deadlocks.
ready: Arc<ReadySet>, ready: Arc<ReadySet>,
/// The pseudo path associated with this epoll file.
pseudo_path: Path,
} }
impl EpollFile { impl EpollFile {
/// Creates a new epoll file. /// Creates a new epoll file.
pub fn new() -> Arc<Self> { pub fn new() -> Arc<Self> {
let pseudo_path = AnonInodeFs::new_path(|_| "anon_inode:[eventpoll]".to_string());
Arc::new(Self { Arc::new(Self {
interest: Mutex::new(BTreeSet::new()), interest: Mutex::new(BTreeSet::new()),
ready: Arc::new(ReadySet::new()), ready: Arc::new(ReadySet::new()),
pseudo_path,
}) })
} }
@ -270,7 +275,7 @@ impl FileLike for EpollFile {
} }
fn inode(&self) -> &Arc<dyn Inode> { fn inode(&self) -> &Arc<dyn Inode> {
AnonInodeFs::shared_inode() self.pseudo_path.inode()
} }
fn dump_proc_fdinfo(self: Arc<Self>, fd_flags: FdFlags) -> Box<dyn Display> { fn dump_proc_fdinfo(self: Arc<Self>, fd_flags: FdFlags) -> Box<dyn Display> {
@ -288,9 +293,8 @@ impl FileLike for EpollFile {
writeln!(f, "pos:\t{}", 0)?; writeln!(f, "pos:\t{}", 0)?;
writeln!(f, "flags:\t0{:o}", flags)?; writeln!(f, "flags:\t0{:o}", flags)?;
// TODO: This should be the mount ID of the pseudo filesystem. writeln!(f, "mnt_id:\t{}", AnonInodeFs::mount_node().id())?;
writeln!(f, "mnt_id:\t{}", RESERVED_MOUNT_ID)?; writeln!(f, "ino:\t{}", AnonInodeFs::shared_inode().ino())?;
writeln!(f, "ino:\t{}", self.inner.inode().ino())?;
for entry in self.inner.interest.lock().iter() { for entry in self.inner.interest.lock().iter() {
writeln!(f, "{}", entry.0)?; writeln!(f, "{}", entry.0)?;
} }

View File

@ -21,7 +21,7 @@ use crate::{
file_handle::FileLike, file_handle::FileLike,
file_table::FdFlags, file_table::FdFlags,
notify::{FsEventSubscriber, FsEvents}, notify::{FsEventSubscriber, FsEvents},
path::{Path, RESERVED_MOUNT_ID}, path::Path,
pseudofs::AnonInodeFs, pseudofs::AnonInodeFs,
utils::{AccessMode, CreationFlags, Inode, InodeExt, StatusFlags}, utils::{AccessMode, CreationFlags, Inode, InodeExt, StatusFlags},
}, },
@ -58,6 +58,8 @@ pub struct InotifyFile {
pollee: Pollee, pollee: Pollee,
// A weak reference to this inotify file. // A weak reference to this inotify file.
this: Weak<InotifyFile>, this: Weak<InotifyFile>,
/// The pseudo path associated with this inotify file.
pseudo_path: Path,
} }
impl Drop for InotifyFile { impl Drop for InotifyFile {
@ -93,6 +95,8 @@ const DEFAULT_MAX_QUEUED_EVENTS: usize = 16384;
impl InotifyFile { impl InotifyFile {
/// Creates a new inotify file. /// Creates a new inotify file.
pub fn new(is_nonblocking: bool) -> Result<Arc<Self>> { pub fn new(is_nonblocking: bool) -> Result<Arc<Self>> {
let pseudo_path = AnonInodeFs::new_path(|_| "anon_inode:inotify".to_string());
Ok(Arc::new_cyclic(|weak_self| Self { Ok(Arc::new_cyclic(|weak_self| Self {
// Allocate watch descriptors from 1. // Allocate watch descriptors from 1.
// Reference: <https://elixir.bootlin.com/linux/v6.17/source/fs/notify/inotify/inotify_user.c#L402> // Reference: <https://elixir.bootlin.com/linux/v6.17/source/fs/notify/inotify/inotify_user.c#L402>
@ -104,6 +108,7 @@ impl InotifyFile {
queue_capacity: DEFAULT_MAX_QUEUED_EVENTS, queue_capacity: DEFAULT_MAX_QUEUED_EVENTS,
pollee: Pollee::new(), pollee: Pollee::new(),
this: weak_self.clone(), this: weak_self.clone(),
pseudo_path,
})) }))
} }
@ -355,7 +360,7 @@ impl FileLike for InotifyFile {
} }
fn inode(&self) -> &Arc<dyn Inode> { fn inode(&self) -> &Arc<dyn Inode> {
AnonInodeFs::shared_inode() self.pseudo_path.inode()
} }
fn dump_proc_fdinfo(self: Arc<Self>, fd_flags: FdFlags) -> Box<dyn Display> { fn dump_proc_fdinfo(self: Arc<Self>, fd_flags: FdFlags) -> Box<dyn Display> {
@ -373,9 +378,8 @@ impl FileLike for InotifyFile {
writeln!(f, "pos:\t{}", 0)?; writeln!(f, "pos:\t{}", 0)?;
writeln!(f, "flags:\t0{:o}", flags)?; writeln!(f, "flags:\t0{:o}", flags)?;
// TODO: This should be the mount ID of the pseudo filesystem. writeln!(f, "mnt_id:\t{}", AnonInodeFs::mount_node().id())?;
writeln!(f, "mnt_id:\t{}", RESERVED_MOUNT_ID)?; writeln!(f, "ino:\t{}", AnonInodeFs::shared_inode().ino())?;
writeln!(f, "ino:\t{}", self.inner.inode().ino())?;
for (wd, entry) in self.inner.watch_map.lock().iter() { for (wd, entry) in self.inner.watch_map.lock().iter() {
let Some(inode) = entry.inode.upgrade() else { let Some(inode) = entry.inode.upgrade() else {

View File

@ -5,7 +5,7 @@
use core::time::Duration; use core::time::Duration;
use inherit_methods_macro::inherit_methods; use inherit_methods_macro::inherit_methods;
pub use mount::{Mount, MountPropType, PerMountFlags, RESERVED_MOUNT_ID}; pub use mount::{Mount, MountPropType, PerMountFlags};
pub use mount_namespace::MountNamespace; pub use mount_namespace::MountNamespace;
use crate::{ use crate::{

View File

@ -36,7 +36,7 @@ pub enum MountPropType {
static ID_ALLOCATOR: Once<SpinLock<IdAlloc>> = Once::new(); static ID_ALLOCATOR: Once<SpinLock<IdAlloc>> = Once::new();
/// The reserved mount ID, which represents an invalid mount. /// The reserved mount ID, which represents an invalid mount.
pub static RESERVED_MOUNT_ID: usize = 0; static RESERVED_MOUNT_ID: usize = 0;
pub(super) fn init() { pub(super) fn init() {
// TODO: Make it configurable. // TODO: Make it configurable.

View File

@ -170,6 +170,15 @@ impl AnonInodeFs {
PseudoFs::singleton(&ANON_INODEFS, "anon_inodefs", ANON_INODEFS_MAGIC) 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. /// Returns the pseudo mount node of the anonymous inode file system.
pub fn mount_node() -> &'static Arc<Mount> { pub fn mount_node() -> &'static Arc<Mount> {
static ANON_INODEFS_MOUNT: Once<Arc<Mount>> = Once::new(); static ANON_INODEFS_MOUNT: Once<Arc<Mount>> = Once::new();

View File

@ -10,7 +10,7 @@ use crate::{
fs::{ fs::{
file_handle::FileLike, file_handle::FileLike,
file_table::FdFlags, file_table::FdFlags,
path::RESERVED_MOUNT_ID, path::Path,
pseudofs::AnonInodeFs, pseudofs::AnonInodeFs,
utils::{CreationFlags, Inode, StatusFlags}, utils::{CreationFlags, Inode, StatusFlags},
}, },
@ -24,6 +24,8 @@ use crate::{
pub struct PidFile { pub struct PidFile {
process: Arc<Process>, process: Arc<Process>,
is_nonblocking: AtomicBool, is_nonblocking: AtomicBool,
/// The pseudo path associated with this pid file.
pseudo_path: Path,
} }
impl Debug for PidFile { impl Debug for PidFile {
@ -40,9 +42,12 @@ impl Debug for PidFile {
impl PidFile { impl PidFile {
pub fn new(process: Arc<Process>, is_nonblocking: bool) -> Self { pub fn new(process: Arc<Process>, is_nonblocking: bool) -> Self {
let pseudo_path = AnonInodeFs::new_path(|_| "anon_inode:[pidfd]".to_string());
Self { Self {
process, process,
is_nonblocking: AtomicBool::new(is_nonblocking), is_nonblocking: AtomicBool::new(is_nonblocking),
pseudo_path,
} }
} }
@ -95,13 +100,12 @@ impl FileLike for PidFile {
} }
fn inode(&self) -> &Arc<dyn Inode> { fn inode(&self) -> &Arc<dyn Inode> {
AnonInodeFs::shared_inode() self.pseudo_path.inode()
} }
fn dump_proc_fdinfo(self: Arc<Self>, fd_flags: FdFlags) -> Box<dyn Display> { fn dump_proc_fdinfo(self: Arc<Self>, fd_flags: FdFlags) -> Box<dyn Display> {
struct FdInfo { struct FdInfo {
flags: u32, flags: u32,
ino: u64,
pid: u32, pid: u32,
} }
@ -109,9 +113,8 @@ impl FileLike for PidFile {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
writeln!(f, "pos:\t{}", 0)?; writeln!(f, "pos:\t{}", 0)?;
writeln!(f, "flags:\t0{:o}", self.flags)?; writeln!(f, "flags:\t0{:o}", self.flags)?;
// TODO: This should be the mount ID of the pseudo filesystem. writeln!(f, "mnt_id:\t{}", AnonInodeFs::mount_node().id())?;
writeln!(f, "mnt_id:\t{}", RESERVED_MOUNT_ID)?; writeln!(f, "ino:\t{}", AnonInodeFs::shared_inode().ino())?;
writeln!(f, "ino:\t{}", self.ino)?;
writeln!(f, "Pid:\t{}", self.pid)?; writeln!(f, "Pid:\t{}", self.pid)?;
// TODO: Currently we do not support PID namespaces. Just print the PID once. // TODO: Currently we do not support PID namespaces. Just print the PID once.
writeln!(f, "NSpid:\t{}", self.pid) writeln!(f, "NSpid:\t{}", self.pid)
@ -125,7 +128,6 @@ impl FileLike for PidFile {
Box::new(FdInfo { Box::new(FdInfo {
flags, flags,
ino: self.inode().ino(),
pid: self.process.pid(), pid: self.process.pid(),
}) })
} }

View File

@ -24,7 +24,7 @@ use crate::{
fs::{ fs::{
file_handle::FileLike, file_handle::FileLike,
file_table::{FdFlags, FileDesc}, file_table::{FdFlags, FileDesc},
path::RESERVED_MOUNT_ID, path::Path,
pseudofs::AnonInodeFs, pseudofs::AnonInodeFs,
utils::{CreationFlags, Inode, StatusFlags}, utils::{CreationFlags, Inode, StatusFlags},
}, },
@ -76,6 +76,8 @@ struct EventFile {
pollee: Pollee, pollee: Pollee,
flags: Mutex<Flags>, flags: Mutex<Flags>,
write_wait_queue: WaitQueue, write_wait_queue: WaitQueue,
/// The pseudo path associated with this eventfd file.
pseudo_path: Path,
} }
impl EventFile { impl EventFile {
@ -85,11 +87,13 @@ impl EventFile {
let counter = Mutex::new(init_val); let counter = Mutex::new(init_val);
let pollee = Pollee::new(); let pollee = Pollee::new();
let write_wait_queue = WaitQueue::new(); let write_wait_queue = WaitQueue::new();
let pseudo_path = AnonInodeFs::new_path(|_| "anon_inode:[eventfd]".to_string());
Self { Self {
counter, counter,
pollee, pollee,
flags: Mutex::new(flags), flags: Mutex::new(flags),
write_wait_queue, write_wait_queue,
pseudo_path,
} }
} }
@ -232,7 +236,7 @@ impl FileLike for EventFile {
} }
fn inode(&self) -> &Arc<dyn Inode> { fn inode(&self) -> &Arc<dyn Inode> {
AnonInodeFs::shared_inode() self.pseudo_path.inode()
} }
fn dump_proc_fdinfo(self: Arc<Self>, fd_flags: FdFlags) -> Box<dyn Display> { fn dump_proc_fdinfo(self: Arc<Self>, fd_flags: FdFlags) -> Box<dyn Display> {
@ -250,9 +254,8 @@ impl FileLike for EventFile {
writeln!(f, "pos:\t{}", 0)?; writeln!(f, "pos:\t{}", 0)?;
writeln!(f, "flags:\t0{:o}", flags)?; writeln!(f, "flags:\t0{:o}", flags)?;
// TODO: This should be the mount ID of the pseudo filesystem. writeln!(f, "mnt_id:\t{}", AnonInodeFs::mount_node().id())?;
writeln!(f, "mnt_id:\t{}", RESERVED_MOUNT_ID)?; writeln!(f, "ino:\t{}", AnonInodeFs::shared_inode().ino())?;
writeln!(f, "ino:\t{}", self.inner.inode().ino())?;
writeln!(f, "eventfd-count: {:16x}", *self.inner.counter.lock()) writeln!(f, "eventfd-count: {:16x}", *self.inner.counter.lock())
} }
} }

View File

@ -20,7 +20,7 @@ use crate::{
fs::{ fs::{
file_handle::FileLike, file_handle::FileLike,
file_table::{FdFlags, FileDesc, get_file_fast}, file_table::{FdFlags, FileDesc, get_file_fast},
path::RESERVED_MOUNT_ID, path::Path,
pseudofs::AnonInodeFs, pseudofs::AnonInodeFs,
utils::{CreationFlags, Inode, StatusFlags}, utils::{CreationFlags, Inode, StatusFlags},
}, },
@ -139,14 +139,19 @@ struct SignalFile {
signals_mask: AtomicSigMask, signals_mask: AtomicSigMask,
/// Non-blocking mode flag /// Non-blocking mode flag
non_blocking: AtomicBool, non_blocking: AtomicBool,
/// The pseudo path associated with this signalfd file.
pseudo_path: Path,
} }
impl SignalFile { impl SignalFile {
/// Create a new signalfd instance /// Create a new signalfd instance
fn new(mask: AtomicSigMask, non_blocking: bool) -> Self { fn new(mask: AtomicSigMask, non_blocking: bool) -> Self {
let pseudo_path = AnonInodeFs::new_path(|_| "anon_inode:[signalfd]".to_string());
Self { Self {
signals_mask: mask, signals_mask: mask,
non_blocking: AtomicBool::new(non_blocking), non_blocking: AtomicBool::new(non_blocking),
pseudo_path,
} }
} }
@ -264,13 +269,12 @@ impl FileLike for SignalFile {
} }
fn inode(&self) -> &Arc<dyn Inode> { fn inode(&self) -> &Arc<dyn Inode> {
AnonInodeFs::shared_inode() self.pseudo_path.inode()
} }
fn dump_proc_fdinfo(self: Arc<Self>, fd_flags: FdFlags) -> Box<dyn Display> { fn dump_proc_fdinfo(self: Arc<Self>, fd_flags: FdFlags) -> Box<dyn Display> {
struct FdInfo { struct FdInfo {
flags: u32, flags: u32,
ino: u64,
sigmask: u64, sigmask: u64,
} }
@ -278,9 +282,8 @@ impl FileLike for SignalFile {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
writeln!(f, "pos:\t{}", 0)?; writeln!(f, "pos:\t{}", 0)?;
writeln!(f, "flags:\t0{:o}", self.flags)?; writeln!(f, "flags:\t0{:o}", self.flags)?;
// TODO: This should be the mount ID of the pseudo filesystem. writeln!(f, "mnt_id:\t{}", AnonInodeFs::mount_node().id())?;
writeln!(f, "mnt_id:\t{}", RESERVED_MOUNT_ID)?; writeln!(f, "ino:\t{}", AnonInodeFs::shared_inode().ino())?;
writeln!(f, "ino:\t{}", self.ino)?;
writeln!(f, "sigmask:\t{:016x}", self.sigmask) writeln!(f, "sigmask:\t{:016x}", self.sigmask)
} }
} }
@ -292,7 +295,6 @@ impl FileLike for SignalFile {
Box::new(FdInfo { Box::new(FdInfo {
flags, flags,
ino: self.inode().ino(),
sigmask: self.mask().load(Ordering::Relaxed).into(), sigmask: self.mask().load(Ordering::Relaxed).into(),
}) })
} }

View File

@ -14,7 +14,7 @@ use crate::{
fs::{ fs::{
file_handle::FileLike, file_handle::FileLike,
file_table::FdFlags, file_table::FdFlags,
path::RESERVED_MOUNT_ID, path::Path,
pseudofs::AnonInodeFs, pseudofs::AnonInodeFs,
utils::{CreationFlags, Inode, StatusFlags}, utils::{CreationFlags, Inode, StatusFlags},
}, },
@ -35,6 +35,8 @@ pub struct TimerfdFile {
pollee: Pollee, pollee: Pollee,
flags: AtomicTFDFlags, flags: AtomicTFDFlags,
settime_flags: AtomicTFDSetTimeFlags, settime_flags: AtomicTFDSetTimeFlags,
/// The pseudo path associated with this timerfd file.
pseudo_path: Path,
} }
bitflags! { bitflags! {
@ -115,6 +117,8 @@ impl TimerfdFile {
create_timer(clockid, expired_fn, ctx) create_timer(clockid, expired_fn, ctx)
}?; }?;
let pseudo_path = AnonInodeFs::new_path(|_| "anon_inode:[timerfd]".to_string());
Ok(TimerfdFile { Ok(TimerfdFile {
clockid, clockid,
timer, timer,
@ -122,6 +126,7 @@ impl TimerfdFile {
pollee, pollee,
flags: AtomicTFDFlags::new(flags), flags: AtomicTFDFlags::new(flags),
settime_flags: AtomicTFDSetTimeFlags::default(), settime_flags: AtomicTFDSetTimeFlags::default(),
pseudo_path,
}) })
} }
@ -252,13 +257,12 @@ impl FileLike for TimerfdFile {
} }
fn inode(&self) -> &Arc<dyn Inode> { fn inode(&self) -> &Arc<dyn Inode> {
AnonInodeFs::shared_inode() self.pseudo_path.inode()
} }
fn dump_proc_fdinfo(self: Arc<Self>, fd_flags: FdFlags) -> Box<dyn Display> { fn dump_proc_fdinfo(self: Arc<Self>, fd_flags: FdFlags) -> Box<dyn Display> {
struct FdInfo { struct FdInfo {
flags: u32, flags: u32,
ino: u64,
clockid: i32, clockid: i32,
ticks: u64, ticks: u64,
settime_flags: u32, settime_flags: u32,
@ -270,9 +274,8 @@ impl FileLike for TimerfdFile {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
writeln!(f, "pos:\t{}", 0)?; writeln!(f, "pos:\t{}", 0)?;
writeln!(f, "flags:\t0{:o}", self.flags)?; writeln!(f, "flags:\t0{:o}", self.flags)?;
// TODO: This should be the mount ID of the pseudo filesystem. writeln!(f, "mnt_id:\t{}", AnonInodeFs::mount_node().id())?;
writeln!(f, "mnt_id:\t{}", RESERVED_MOUNT_ID)?; writeln!(f, "ino:\t{}", AnonInodeFs::shared_inode().ino())?;
writeln!(f, "ino:\t{}", self.ino)?;
writeln!(f, "clockid: {}", self.clockid)?; writeln!(f, "clockid: {}", self.clockid)?;
writeln!(f, "ticks: {}", self.ticks)?; writeln!(f, "ticks: {}", self.ticks)?;
writeln!(f, "settime flags: 0{:o}", self.settime_flags)?; writeln!(f, "settime flags: 0{:o}", self.settime_flags)?;
@ -299,7 +302,6 @@ impl FileLike for TimerfdFile {
let timer_guard = self.timer.lock(); let timer_guard = self.timer.lock();
Box::new(FdInfo { Box::new(FdInfo {
flags, flags,
ino: self.inode().ino(),
clockid: self.clockid, clockid: self.clockid,
ticks: self.ticks.load(Ordering::Relaxed), ticks: self.ticks.load(Ordering::Relaxed),
settime_flags: self.settime_flags.load(Ordering::Relaxed).bits(), settime_flags: self.settime_flags.load(Ordering::Relaxed).bits(),