Support generating fdinfo for most of the existing FileLikes

This commit is contained in:
Chen Chengjun 2025-11-19 07:20:25 +00:00 committed by Tate, Hongliang Tian
parent 61a5bb7241
commit 59cd3bd61d
11 changed files with 299 additions and 16 deletions

View File

@ -4,7 +4,10 @@ use alloc::{
collections::vec_deque::VecDeque,
sync::{Arc, Weak},
};
use core::sync::atomic::{AtomicBool, Ordering};
use core::{
fmt::Display,
sync::atomic::{AtomicBool, Ordering},
};
use keyable_arc::{KeyableArc, KeyableWeak};
use ostd::sync::{LocalIrqDisabled, Mutex, MutexGuard, SpinLock, SpinLockGuard};
@ -31,6 +34,15 @@ pub(super) struct Entry {
observer: Arc<Observer>,
}
impl Display for Entry {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let inner = self.inner.lock();
write!(f, "tfd: {:8} ", self.key.fd)?;
write!(f, "events: {:8x} ", inner.event.events.bits())?;
write!(f, "data: {:16x}", inner.event.user_data)
}
}
#[derive(PartialEq, Eq, PartialOrd, Ord)]
pub(super) struct EntryKey {
fd: FileDesc,

View File

@ -1,7 +1,7 @@
// SPDX-License-Identifier: MPL-2.0
use alloc::{collections::btree_set::BTreeSet, sync::Arc};
use core::{borrow::Borrow, time::Duration};
use core::{borrow::Borrow, fmt::Display, time::Duration};
use keyable_arc::KeyableWeak;
use ostd::sync::Mutex;
@ -14,9 +14,10 @@ use crate::{
events::IoEvents,
fs::{
file_handle::FileLike,
file_table::{get_file_fast, FileDesc},
file_table::{get_file_fast, FdFlags, FileDesc},
path::RESERVED_MOUNT_ID,
pseudofs::anon_inodefs_shared_inode,
utils::{Inode, IoctlCmd},
utils::{CreationFlags, Inode, IoctlCmd},
},
prelude::*,
process::{
@ -270,6 +271,38 @@ impl FileLike for EpollFile {
fn inode(&self) -> &Arc<dyn Inode> {
anon_inodefs_shared_inode()
}
fn dump_proc_fdinfo(self: Arc<Self>, fd_flags: FdFlags) -> Box<dyn Display> {
struct FdInfo {
inner: Arc<EpollFile>,
fd_flags: FdFlags,
}
impl Display for FdInfo {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let mut flags = self.inner.status_flags().bits() | self.inner.access_mode() as u32;
if self.fd_flags.contains(FdFlags::CLOEXEC) {
flags |= CreationFlags::O_CLOEXEC.bits();
}
writeln!(f, "pos:\t{}", 0)?;
writeln!(f, "flags:\t0{:o}", flags)?;
// TODO: This should be the mount ID of the pseudo filesystem.
writeln!(f, "mnt_id:\t{}", RESERVED_MOUNT_ID)?;
writeln!(f, "ino:\t{}", self.inner.inode().ino())?;
for entry in self.inner.interest.lock().iter() {
writeln!(f, "{}", entry.0)?;
}
Ok(())
}
}
Box::new(FdInfo {
inner: self,
fd_flags,
})
}
}
struct EntryHolder(Arc<Entry>);

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MPL-2.0
use core::sync::atomic::AtomicU32;
use core::{fmt::Display, sync::atomic::AtomicU32};
use aster_rights::Rights;
use inherit_methods_macro::inherit_methods;
@ -10,10 +10,11 @@ use crate::{
events::IoEvents,
fs::{
file_handle::{FileLike, Mappable},
file_table::FdFlags,
path::Path,
utils::{
AccessMode, DirentVisitor, FallocMode, FlockItem, Inode, InodeType, IoctlCmd,
RangeLockItem, RangeLockType, SeekFrom, StatusFlags,
AccessMode, CreationFlags, DirentVisitor, FallocMode, FlockItem, Inode, InodeType,
IoctlCmd, RangeLockItem, RangeLockType, SeekFrom, StatusFlags,
},
},
prelude::*,
@ -206,6 +207,32 @@ impl FileLike for InodeHandle {
fn inode(&self) -> &Arc<dyn Inode> {
self.0.path.inode()
}
fn dump_proc_fdinfo(self: Arc<Self>, fd_flags: FdFlags) -> Box<dyn Display> {
struct FdInfo {
inner: Arc<InodeHandle>,
fd_flags: FdFlags,
}
impl Display for FdInfo {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let mut flags = self.inner.status_flags().bits() | self.inner.access_mode() as u32;
if self.fd_flags.contains(FdFlags::CLOEXEC) {
flags |= CreationFlags::O_CLOEXEC.bits();
}
writeln!(f, "pos:\t{}", self.inner.offset())?;
writeln!(f, "flags:\t0{:o}", flags)?;
writeln!(f, "mnt_id:\t{}", self.inner.path().mount_node().id())?;
writeln!(f, "ino:\t{}", self.inner.inode().ino())
}
}
Box::new(FdInfo {
inner: self,
fd_flags,
})
}
}
impl Drop for InodeHandle {

View File

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

View File

@ -40,11 +40,17 @@ impl Default for MountPropType {
static ID_ALLOCATOR: Once<SpinLock<IdAlloc>> = Once::new();
/// The reserved mount ID, which represents an invalid mount.
pub static RESERVED_MOUNT_ID: usize = 0;
pub(super) fn init() {
// TODO: Make it configurable.
const MAX_MOUNT_NUM: usize = 10000;
ID_ALLOCATOR.call_once(|| SpinLock::new(IdAlloc::with_capacity(MAX_MOUNT_NUM)));
let mut id_allocator = IdAlloc::with_capacity(MAX_MOUNT_NUM);
let _ = id_allocator.alloc_specific(RESERVED_MOUNT_ID).unwrap(); // Reserve mount ID 0.
ID_ALLOCATOR.call_once(|| SpinLock::new(id_allocator));
}
bitflags! {

View File

@ -1,14 +1,19 @@
// SPDX-License-Identifier: MPL-2.0
use core::sync::atomic::{AtomicU32, Ordering};
use core::{
fmt::Display,
sync::atomic::{AtomicU32, Ordering},
};
use crate::{
events::IoEvents,
fs::{
file_handle::FileLike,
file_table::FdFlags,
path::RESERVED_MOUNT_ID,
pipe::common::{PipeReader, PipeWriter},
pseudofs::{pipefs_singleton, PseudoInode},
utils::{mkmod, AccessMode, Inode, InodeType, StatusFlags},
utils::{mkmod, AccessMode, CreationFlags, Inode, InodeType, StatusFlags},
},
prelude::*,
process::{
@ -76,6 +81,21 @@ impl Pollable for PipeReaderFile {
}
}
struct FdInfo {
flags: u32,
ino: u64,
}
impl Display for FdInfo {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
writeln!(f, "pos:\t{}", 0)?;
writeln!(f, "flags:\t0{:o}", self.flags)?;
// TODO: This should be the mount ID of the pseudo filesystem.
writeln!(f, "mnt_id:\t{}", RESERVED_MOUNT_ID)?;
writeln!(f, "ino:\t{}", self.ino)
}
}
impl FileLike for PipeReaderFile {
fn read(&self, writer: &mut VmWriter) -> Result<usize> {
if !writer.has_avail() {
@ -109,6 +129,18 @@ impl FileLike for PipeReaderFile {
fn inode(&self) -> &Arc<dyn Inode> {
&self.pseudo_inode
}
fn dump_proc_fdinfo(self: Arc<Self>, fd_flags: FdFlags) -> Box<dyn Display> {
let mut flags = self.status_flags().bits() | self.access_mode() as u32;
if fd_flags.contains(FdFlags::CLOEXEC) {
flags |= CreationFlags::O_CLOEXEC.bits();
}
Box::new(FdInfo {
flags,
ino: self.inode().ino(),
})
}
}
impl Drop for PipeReaderFile {
@ -179,6 +211,18 @@ impl FileLike for PipeWriterFile {
fn inode(&self) -> &Arc<dyn Inode> {
&self.pseudo_inode
}
fn dump_proc_fdinfo(self: Arc<Self>, fd_flags: FdFlags) -> Box<dyn Display> {
let mut flags = self.status_flags().bits() | self.access_mode() as u32;
if fd_flags.contains(FdFlags::CLOEXEC) {
flags |= CreationFlags::O_CLOEXEC.bits();
}
Box::new(FdInfo {
flags,
ino: self.inode().ino(),
})
}
}
fn check_status_flags(status_flags: StatusFlags) -> Result<()> {

View File

@ -4,6 +4,7 @@
use alloc::format;
use core::{
fmt::Display,
sync::atomic::{AtomicU32, Ordering},
time::Duration,
};
@ -19,8 +20,9 @@ use crate::{
events::IoEvents,
fs::{
file_handle::{FileLike, Mappable},
file_table::FdFlags,
inode_handle::{do_fallocate_util, do_resize_util, do_seek_util},
path::check_open_util,
path::{check_open_util, RESERVED_MOUNT_ID},
tmpfs::TmpFs,
utils::{
chmod, mkmod, AccessMode, CachePage, CreationFlags, Extension, FallocMode, FileSystem,
@ -469,6 +471,32 @@ impl FileLike for MemfdFile {
fn inode(&self) -> &Arc<dyn Inode> {
&self.memfd_inode
}
fn dump_proc_fdinfo(self: Arc<Self>, fd_flags: FdFlags) -> Box<dyn Display> {
struct FdInfo {
inner: Arc<MemfdFile>,
fd_flags: FdFlags,
}
impl Display for FdInfo {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let mut flags = self.inner.status_flags().bits() | self.inner.access_mode() as u32;
if self.fd_flags.contains(FdFlags::CLOEXEC) {
flags |= CreationFlags::O_CLOEXEC.bits();
}
writeln!(f, "pos:\t{}", *self.inner.offset.lock())?;
writeln!(f, "flags:\t0{:o}", flags)?;
writeln!(f, "mnt_id:\t{}", RESERVED_MOUNT_ID)?;
writeln!(f, "ino:\t{}", self.inner.inode().ino())
}
}
Box::new(FdInfo {
inner: self,
fd_flags,
})
}
}
bitflags! {

View File

@ -1,13 +1,17 @@
// SPDX-License-Identifier: MPL-2.0
use core::fmt::Display;
use options::SocketOption;
use util::{MessageHeader, SendRecvFlags, SockShutdownCmd, SocketAddr};
use crate::{
fs::{
file_handle::FileLike,
file_table::FdFlags,
path::RESERVED_MOUNT_ID,
pseudofs::{sockfs_singleton, PseudoInode},
utils::{mkmod, Inode, InodeType, StatusFlags},
utils::{mkmod, CreationFlags, Inode, InodeType, StatusFlags},
},
prelude::*,
process::{Gid, Uid},
@ -175,6 +179,33 @@ impl<T: Socket + 'static> FileLike for T {
fn inode(&self) -> &Arc<dyn Inode> {
self.pseudo_inode()
}
fn dump_proc_fdinfo(self: Arc<Self>, fd_flags: FdFlags) -> Box<dyn Display> {
struct FdInfo {
flags: u32,
ino: u64,
}
impl Display for FdInfo {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
writeln!(f, "pos:\t{}", 0)?;
writeln!(f, "flags:\t0{:o}", self.flags)?;
// TODO: This should be the mount ID of the pseudo filesystem.
writeln!(f, "mnt_id:\t{}", RESERVED_MOUNT_ID)?;
writeln!(f, "ino:\t{}", self.ino)
}
}
let mut flags = self.status_flags().bits() | self.access_mode() as u32;
if fd_flags.contains(FdFlags::CLOEXEC) {
flags |= CreationFlags::O_CLOEXEC.bits();
}
Box::new(FdInfo {
flags,
ino: self.inode().ino(),
})
}
}
/// Creates a new pseudo inode for a socket.

View File

@ -1,13 +1,18 @@
// SPDX-License-Identifier: MPL-2.0
use core::sync::atomic::{AtomicBool, Ordering};
use core::{
fmt::Display,
sync::atomic::{AtomicBool, Ordering},
};
use crate::{
events::IoEvents,
fs::{
file_handle::FileLike,
file_table::FdFlags,
path::RESERVED_MOUNT_ID,
pseudofs::anon_inodefs_shared_inode,
utils::{Inode, StatusFlags},
utils::{CreationFlags, Inode, StatusFlags},
},
prelude::*,
process::{
@ -92,6 +97,38 @@ impl FileLike for PidFile {
fn inode(&self) -> &Arc<dyn Inode> {
anon_inodefs_shared_inode()
}
fn dump_proc_fdinfo(self: Arc<Self>, fd_flags: FdFlags) -> Box<dyn Display> {
struct FdInfo {
flags: u32,
ino: u64,
pid: u32,
}
impl Display for FdInfo {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
writeln!(f, "pos:\t{}", 0)?;
writeln!(f, "flags:\t0{:o}", self.flags)?;
// TODO: This should be the mount ID of the pseudo filesystem.
writeln!(f, "mnt_id:\t{}", RESERVED_MOUNT_ID)?;
writeln!(f, "ino:\t{}", self.ino)?;
writeln!(f, "Pid:\t{}", self.pid)?;
// TODO: Currently we do not support PID namespaces. Just print the PID once.
writeln!(f, "NSpid:\t{}", self.pid)
}
}
let mut flags = self.status_flags().bits() | self.access_mode() as u32;
if fd_flags.contains(FdFlags::CLOEXEC) {
flags |= CreationFlags::O_CLOEXEC.bits();
}
Box::new(FdInfo {
flags,
ino: self.inode().ino(),
pid: self.process.pid(),
})
}
}
impl Pollable for PidFile {

View File

@ -14,6 +14,8 @@
//! refer to the man 2 eventfd documentation.
//!
use core::fmt::Display;
use ostd::sync::WaitQueue;
use super::SyscallReturn;
@ -22,6 +24,7 @@ use crate::{
fs::{
file_handle::FileLike,
file_table::{FdFlags, FileDesc},
path::RESERVED_MOUNT_ID,
pseudofs::anon_inodefs_shared_inode,
utils::{CreationFlags, Inode, StatusFlags},
},
@ -234,4 +237,32 @@ impl FileLike for EventFile {
fn inode(&self) -> &Arc<dyn Inode> {
anon_inodefs_shared_inode()
}
fn dump_proc_fdinfo(self: Arc<Self>, fd_flags: FdFlags) -> Box<dyn Display> {
struct FdInfo {
inner: Arc<EventFile>,
fd_flags: FdFlags,
}
impl Display for FdInfo {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let mut flags = self.inner.status_flags().bits() | self.inner.access_mode() as u32;
if self.fd_flags.contains(FdFlags::CLOEXEC) {
flags |= CreationFlags::O_CLOEXEC.bits();
}
writeln!(f, "pos:\t{}", 0)?;
writeln!(f, "flags:\t0{:o}", flags)?;
// TODO: This should be the mount ID of the pseudo filesystem.
writeln!(f, "mnt_id:\t{}", RESERVED_MOUNT_ID)?;
writeln!(f, "ino:\t{}", self.inner.inode().ino())?;
writeln!(f, "eventfd-count: {:16x}", *self.inner.counter.lock())
}
}
Box::new(FdInfo {
inner: self,
fd_flags,
})
}
}

View File

@ -6,7 +6,10 @@
//! enabling better integration with event loops.
//! See https://man7.org/linux/man-pages/man2/signalfd.2.html
use core::sync::atomic::{AtomicBool, Ordering};
use core::{
fmt::Display,
sync::atomic::{AtomicBool, Ordering},
};
use bitflags::bitflags;
@ -16,6 +19,7 @@ use crate::{
fs::{
file_handle::FileLike,
file_table::{get_file_fast, FdFlags, FileDesc},
path::RESERVED_MOUNT_ID,
pseudofs::anon_inodefs_shared_inode,
utils::{CreationFlags, Inode, StatusFlags},
},
@ -261,6 +265,36 @@ impl FileLike for SignalFile {
fn inode(&self) -> &Arc<dyn Inode> {
anon_inodefs_shared_inode()
}
fn dump_proc_fdinfo(self: Arc<Self>, fd_flags: FdFlags) -> Box<dyn Display> {
struct FdInfo {
flags: u32,
ino: u64,
sigmask: u64,
}
impl Display for FdInfo {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
writeln!(f, "pos:\t{}", 0)?;
writeln!(f, "flags:\t0{:o}", self.flags)?;
// TODO: This should be the mount ID of the pseudo filesystem.
writeln!(f, "mnt_id:\t{}", RESERVED_MOUNT_ID)?;
writeln!(f, "ino:\t{}", self.ino)?;
writeln!(f, "sigmask:\t{:016x}", self.sigmask)
}
}
let mut flags = self.status_flags().bits() | self.access_mode() as u32;
if fd_flags.contains(FdFlags::CLOEXEC) {
flags |= CreationFlags::O_CLOEXEC.bits();
}
Box::new(FdInfo {
flags,
ino: self.inode().ino(),
sigmask: self.mask().load(Ordering::Relaxed).into(),
})
}
}
#[repr(C)]