asterinas/kernel/src/fs/procfs/mod.rs

165 lines
4.9 KiB
Rust
Raw Normal View History

2024-01-03 03:22:36 +00:00
// SPDX-License-Identifier: MPL-2.0
use core::sync::atomic::{AtomicU64, Ordering};
2023-03-27 05:55:13 +00:00
2024-11-28 05:53:22 +00:00
use filesystems::{FileSystemType, FILESYSTEM_TYPES};
use loadavg::LoadAvgFileOps;
use sys::SysDirOps;
use self::{
2024-11-04 02:30:15 +00:00
cpuinfo::CpuInfoFileOps,
2024-07-21 16:01:55 +00:00
meminfo::MemInfoFileOps,
pid::PidDirOps,
self_::SelfSymOps,
template::{DirOps, ProcDir, ProcDirBuilder, ProcSymBuilder, SymOps},
};
use crate::{
events::Observer,
2024-07-13 09:31:50 +00:00
fs::{
procfs::filesystems::FileSystemsFileOps,
utils::{DirEntryVecExt, FileSystem, FsFlags, Inode, SuperBlock, NAME_MAX},
},
prelude::*,
process::{process_table, process_table::PidEvent, Pid},
};
2023-03-27 05:55:13 +00:00
2024-11-04 02:30:15 +00:00
mod cpuinfo;
2024-07-13 09:31:50 +00:00
mod filesystems;
mod loadavg;
2024-07-21 16:01:55 +00:00
mod meminfo;
2023-03-27 05:55:13 +00:00
mod pid;
mod self_;
mod sys;
2023-03-27 05:55:13 +00:00
mod template;
2024-11-28 05:53:22 +00:00
pub(super) fn init() {
FILESYSTEM_TYPES.call_once(|| {
vec![
FileSystemType::new("proc", true),
FileSystemType::new("ramfs", true),
FileSystemType::new("devpts", true),
FileSystemType::new("ext2", false),
FileSystemType::new("exfat", false),
]
});
}
2023-03-27 05:55:13 +00:00
/// Magic number.
2023-07-03 05:29:02 +00:00
const PROC_MAGIC: u64 = 0x9fa0;
2023-03-27 05:55:13 +00:00
/// Root Inode ID.
const PROC_ROOT_INO: u64 = 1;
2023-03-27 05:55:13 +00:00
/// Block size.
const BLOCK_SIZE: usize = 1024;
pub struct ProcFS {
sb: SuperBlock,
root: Arc<dyn Inode>,
inode_allocator: AtomicU64,
2023-03-27 05:55:13 +00:00
}
impl ProcFS {
pub fn new() -> Arc<Self> {
Arc::new_cyclic(|weak_fs| Self {
sb: SuperBlock::new(PROC_MAGIC, BLOCK_SIZE, NAME_MAX),
root: RootDirOps::new_inode(weak_fs.clone()),
inode_allocator: AtomicU64::new(PROC_ROOT_INO + 1),
})
2023-03-27 05:55:13 +00:00
}
pub(in crate::fs::procfs) fn alloc_id(&self) -> u64 {
2023-09-04 03:04:42 +00:00
self.inode_allocator.fetch_add(1, Ordering::SeqCst)
2023-03-27 05:55:13 +00:00
}
}
impl FileSystem for ProcFS {
fn sync(&self) -> Result<()> {
Ok(())
}
fn root_inode(&self) -> Arc<dyn Inode> {
self.root.clone()
2023-03-27 05:55:13 +00:00
}
fn sb(&self) -> SuperBlock {
self.sb.clone()
2023-03-27 05:55:13 +00:00
}
fn flags(&self) -> FsFlags {
FsFlags::empty()
2023-03-27 05:55:13 +00:00
}
}
/// Represents the inode at `/proc`.
struct RootDirOps;
impl RootDirOps {
pub fn new_inode(fs: Weak<ProcFS>) -> Arc<dyn Inode> {
let root_inode = ProcDirBuilder::new(Self)
.fs(fs)
.ino(PROC_ROOT_INO)
.build()
.unwrap();
2023-03-27 05:55:13 +00:00
let weak_ptr = Arc::downgrade(&root_inode);
process_table::register_observer(weak_ptr);
root_inode
}
}
impl Observer<PidEvent> for ProcDir<RootDirOps> {
fn on_events(&self, events: &PidEvent) {
let PidEvent::Exit(pid) = events;
let mut cached_children = self.cached_children().write();
cached_children.remove_entry_by_name(&pid.to_string());
}
}
impl DirOps for RootDirOps {
fn lookup_child(&self, this_ptr: Weak<dyn Inode>, name: &str) -> Result<Arc<dyn Inode>> {
let child = if name == "self" {
SelfSymOps::new_inode(this_ptr.clone())
} else if name == "sys" {
SysDirOps::new_inode(this_ptr.clone())
2024-07-13 09:31:50 +00:00
} else if name == "filesystems" {
FileSystemsFileOps::new_inode(this_ptr.clone())
2024-07-21 16:01:55 +00:00
} else if name == "meminfo" {
MemInfoFileOps::new_inode(this_ptr.clone())
} else if name == "loadavg" {
LoadAvgFileOps::new_inode(this_ptr.clone())
2024-11-04 02:30:15 +00:00
} else if name == "cpuinfo" {
CpuInfoFileOps::new_inode(this_ptr.clone())
2023-03-27 05:55:13 +00:00
} else if let Ok(pid) = name.parse::<Pid>() {
let process_ref =
2024-05-31 10:21:46 +00:00
process_table::get_process(pid).ok_or_else(|| Error::new(Errno::ENOENT))?;
2023-03-27 05:55:13 +00:00
PidDirOps::new_inode(process_ref, this_ptr.clone())
} else {
return_errno!(Errno::ENOENT);
};
Ok(child)
}
fn populate_children(&self, this_ptr: Weak<dyn Inode>) {
let this = {
let this = this_ptr.upgrade().unwrap();
this.downcast_ref::<ProcDir<RootDirOps>>().unwrap().this()
};
let mut cached_children = this.cached_children().write();
cached_children.put_entry_if_not_found("self", || SelfSymOps::new_inode(this_ptr.clone()));
cached_children.put_entry_if_not_found("sys", || SysDirOps::new_inode(this_ptr.clone()));
2024-07-13 09:31:50 +00:00
cached_children.put_entry_if_not_found("filesystems", || {
FileSystemsFileOps::new_inode(this_ptr.clone())
});
2024-07-21 16:01:55 +00:00
cached_children
.put_entry_if_not_found("meminfo", || MemInfoFileOps::new_inode(this_ptr.clone()));
cached_children
.put_entry_if_not_found("loadavg", || LoadAvgFileOps::new_inode(this_ptr.clone()));
2024-11-04 02:30:15 +00:00
cached_children
.put_entry_if_not_found("cpuinfo", || CpuInfoFileOps::new_inode(this_ptr.clone()));
2024-10-27 06:47:39 +00:00
for process in process_table::process_table_mut().iter() {
2023-03-27 05:55:13 +00:00
let pid = process.pid().to_string();
cached_children.put_entry_if_not_found(&pid, || {
PidDirOps::new_inode(process.clone(), this_ptr.clone())
});
}
}
}