Refine ProcFs by improving the use of locks

This commit is contained in:
LI Qing 2024-05-24 10:32:30 +08:00 committed by Tate, Hongliang Tian
parent 6ff8497101
commit 494c88e993
7 changed files with 95 additions and 79 deletions

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MPL-2.0
use core::sync::atomic::{AtomicUsize, Ordering};
use core::sync::atomic::{AtomicU64, Ordering};
use self::{
pid::PidDirOps,
@ -21,33 +21,26 @@ mod template;
/// Magic number.
const PROC_MAGIC: u64 = 0x9fa0;
/// Root Inode ID.
const PROC_ROOT_INO: usize = 1;
const PROC_ROOT_INO: u64 = 1;
/// Block size.
const BLOCK_SIZE: usize = 1024;
pub struct ProcFS {
sb: RwLock<SuperBlock>,
root: RwLock<Option<Arc<dyn Inode>>>,
inode_allocator: AtomicUsize,
sb: SuperBlock,
root: Arc<dyn Inode>,
inode_allocator: AtomicU64,
}
impl ProcFS {
pub fn new() -> Arc<Self> {
let procfs = {
let sb = SuperBlock::new(PROC_MAGIC, BLOCK_SIZE, NAME_MAX);
Arc::new(Self {
sb: RwLock::new(sb),
root: RwLock::new(None),
inode_allocator: AtomicUsize::new(PROC_ROOT_INO),
})
};
let root = RootDirOps::new_inode(&procfs);
*procfs.root.write() = Some(root);
procfs
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),
})
}
pub(in crate::fs::procfs) fn alloc_id(&self) -> usize {
pub(in crate::fs::procfs) fn alloc_id(&self) -> u64 {
self.inode_allocator.fetch_add(1, Ordering::SeqCst)
}
}
@ -58,11 +51,11 @@ impl FileSystem for ProcFS {
}
fn root_inode(&self) -> Arc<dyn Inode> {
self.root.read().as_ref().unwrap().clone()
self.root.clone()
}
fn sb(&self) -> SuperBlock {
self.sb.read().clone()
self.sb.clone()
}
fn flags(&self) -> FsFlags {
@ -74,8 +67,12 @@ impl FileSystem for ProcFS {
struct RootDirOps;
impl RootDirOps {
pub fn new_inode(fs: &Arc<ProcFS>) -> Arc<dyn Inode> {
let root_inode = ProcDirBuilder::new(Self).fs(fs.clone()).build().unwrap();
pub fn new_inode(fs: Weak<ProcFS>) -> Arc<dyn Inode> {
let root_inode = ProcDirBuilder::new(Self)
.fs(fs)
.ino(PROC_ROOT_INO)
.build()
.unwrap();
let weak_ptr = Arc::downgrade(&root_inode);
process_table::register_observer(weak_ptr);
root_inode

View File

@ -32,7 +32,7 @@ impl<O: DirOps> ProcDirBuilder<O> {
self.optional_builder(|ob| ob.parent(parent))
}
pub fn fs(self, fs: Arc<dyn FileSystem>) -> Self {
pub fn fs(self, fs: Weak<dyn FileSystem>) -> Self {
self.optional_builder(|ob| ob.fs(fs))
}
@ -40,9 +40,13 @@ impl<O: DirOps> ProcDirBuilder<O> {
self.optional_builder(|ob| ob.volatile())
}
pub fn ino(self, ino: u64) -> Self {
self.optional_builder(|ob| ob.ino(ino))
}
pub fn build(mut self) -> Result<Arc<ProcDir<O>>> {
let (fs, parent, is_volatile) = self.optional_builder.take().unwrap().build()?;
Ok(ProcDir::new(self.dir, fs, parent, is_volatile))
let (fs, parent, ino, is_volatile) = self.optional_builder.take().unwrap().build()?;
Ok(ProcDir::new(self.dir, fs, parent, ino, is_volatile))
}
fn optional_builder<F>(mut self, f: F) -> Self
@ -80,7 +84,7 @@ impl<O: FileOps> ProcFileBuilder<O> {
}
pub fn build(mut self) -> Result<Arc<ProcFile<O>>> {
let (fs, _, is_volatile) = self.optional_builder.take().unwrap().build()?;
let (fs, _, _, is_volatile) = self.optional_builder.take().unwrap().build()?;
Ok(ProcFile::new(self.file, fs, is_volatile))
}
@ -119,7 +123,7 @@ impl<O: SymOps> ProcSymBuilder<O> {
}
pub fn build(mut self) -> Result<Arc<ProcSym<O>>> {
let (fs, _, is_volatile) = self.optional_builder.take().unwrap().build()?;
let (fs, _, _, is_volatile) = self.optional_builder.take().unwrap().build()?;
Ok(ProcSym::new(self.sym, fs, is_volatile))
}
@ -136,7 +140,8 @@ impl<O: SymOps> ProcSymBuilder<O> {
#[derive(Default)]
struct OptionalBuilder {
parent: Option<Weak<dyn Inode>>,
fs: Option<Arc<dyn FileSystem>>,
fs: Option<Weak<dyn FileSystem>>,
ino: Option<u64>,
is_volatile: bool,
}
@ -146,24 +151,36 @@ impl OptionalBuilder {
self
}
pub fn fs(mut self, fs: Arc<dyn FileSystem>) -> Self {
pub fn fs(mut self, fs: Weak<dyn FileSystem>) -> Self {
self.fs = Some(fs);
self
}
pub fn ino(mut self, ino: u64) -> Self {
self.ino = Some(ino);
self
}
pub fn volatile(mut self) -> Self {
self.is_volatile = true;
self
}
#[allow(clippy::type_complexity)]
pub fn build(self) -> Result<(Arc<dyn FileSystem>, Option<Weak<dyn Inode>>, bool)> {
pub fn build(
self,
) -> Result<(
Weak<dyn FileSystem>,
Option<Weak<dyn Inode>>,
Option<u64>,
bool,
)> {
if self.parent.is_none() && self.fs.is_none() {
return_errno_with_message!(Errno::EINVAL, "must have parent or fs");
}
let fs = self
.fs
.unwrap_or_else(|| self.parent.as_ref().unwrap().upgrade().unwrap().fs());
let fs = self.fs.unwrap_or_else(|| {
Arc::downgrade(&self.parent.as_ref().unwrap().upgrade().unwrap().fs())
});
// The volatile property is inherited from parent.
let is_volatile = {
@ -176,6 +193,6 @@ impl OptionalBuilder {
is_volatile
};
Ok((fs, self.parent, is_volatile))
Ok((fs, self.parent, self.ino, is_volatile))
}
}

View File

@ -21,31 +21,37 @@ pub struct ProcDir<D: DirOps> {
inner: D,
this: Weak<ProcDir<D>>,
parent: Option<Weak<dyn Inode>>,
cached_children: RwLock<SlotVec<(String, Arc<dyn Inode>)>>,
cached_children: RwMutex<SlotVec<(String, Arc<dyn Inode>)>>,
common: Common,
}
impl<D: DirOps> ProcDir<D> {
pub fn new(
dir: D,
fs: Arc<dyn FileSystem>,
fs: Weak<dyn FileSystem>,
parent: Option<Weak<dyn Inode>>,
ino: Option<u64>,
is_volatile: bool,
) -> Arc<Self> {
let common = {
let procfs = fs.downcast_ref::<ProcFS>().unwrap();
let ino = ino.unwrap_or_else(|| {
let arc_fs = fs.upgrade().unwrap();
let procfs = arc_fs.downcast_ref::<ProcFS>().unwrap();
procfs.alloc_id()
});
let metadata = Metadata::new_dir(
procfs.alloc_id(),
ino as _,
InodeMode::from_bits_truncate(0o555),
&fs.sb(),
super::BLOCK_SIZE,
);
Common::new(metadata, Arc::downgrade(&fs), is_volatile)
Common::new(metadata, fs, is_volatile)
};
Arc::new_cyclic(|weak_self| Self {
inner: dir,
this: weak_self.clone(),
parent,
cached_children: RwLock::new(SlotVec::new()),
cached_children: RwMutex::new(SlotVec::new()),
common,
})
}
@ -58,7 +64,7 @@ impl<D: DirOps> ProcDir<D> {
self.parent.as_ref().and_then(|p| p.upgrade())
}
pub fn cached_children(&self) -> &RwLock<SlotVec<(String, Arc<dyn Inode>)>> {
pub fn cached_children(&self) -> &RwMutex<SlotVec<(String, Arc<dyn Inode>)>> {
&self.cached_children
}
}
@ -108,20 +114,15 @@ impl<D: DirOps + 'static> Inode for ProcDir<D> {
let this_inode = self.this();
visitor.visit(
".",
this_inode.common.metadata().ino as u64,
this_inode.common.metadata().type_,
this_inode.common.ino(),
this_inode.common.type_(),
*offset,
)?;
*offset += 1;
}
if *offset == 1 {
let parent_inode = self.parent().unwrap_or(self.this());
visitor.visit(
"..",
parent_inode.metadata().ino as u64,
parent_inode.metadata().type_,
*offset,
)?;
visitor.visit("..", parent_inode.ino(), parent_inode.type_(), *offset)?;
*offset += 1;
}
@ -134,12 +135,7 @@ impl<D: DirOps + 'static> Inode for ProcDir<D> {
.map(|(idx, (name, child))| (idx + 2, (name, child)))
.skip_while(|(idx, _)| idx < &start_offset)
{
visitor.visit(
name.as_ref(),
child.metadata().ino as u64,
child.metadata().type_,
idx,
)?;
visitor.visit(name.as_ref(), child.ino(), child.type_(), idx)?;
*offset = idx + 1;
}
Ok(())

View File

@ -17,15 +17,16 @@ pub struct ProcFile<F: FileOps> {
}
impl<F: FileOps> ProcFile<F> {
pub fn new(file: F, fs: Arc<dyn FileSystem>, is_volatile: bool) -> Arc<Self> {
pub fn new(file: F, fs: Weak<dyn FileSystem>, is_volatile: bool) -> Arc<Self> {
let common = {
let procfs = fs.downcast_ref::<ProcFS>().unwrap();
let arc_fs = fs.upgrade().unwrap();
let procfs = arc_fs.downcast_ref::<ProcFS>().unwrap();
let metadata = Metadata::new_file(
procfs.alloc_id(),
procfs.alloc_id() as _,
InodeMode::from_bits_truncate(0o444),
&fs.sb(),
super::BLOCK_SIZE,
);
Common::new(metadata, Arc::downgrade(&fs), is_volatile)
Common::new(metadata, fs, is_volatile)
};
Arc::new(Self {
inner: file,

View File

@ -8,9 +8,9 @@ pub use self::{
file::FileOps,
sym::SymOps,
};
use super::ProcFS;
use super::{ProcFS, BLOCK_SIZE};
use crate::{
fs::utils::{FileSystem, InodeMode, Metadata},
fs::utils::{FileSystem, InodeMode, InodeType, Metadata},
prelude::*,
process::{Gid, Uid},
};
@ -47,6 +47,10 @@ impl Common {
self.metadata.read().ino as _
}
pub fn type_(&self) -> InodeType {
self.metadata.read().type_
}
pub fn size(&self) -> usize {
self.metadata.read().size
}

View File

@ -17,15 +17,16 @@ pub struct ProcSym<S: SymOps> {
}
impl<S: SymOps> ProcSym<S> {
pub fn new(sym: S, fs: Arc<dyn FileSystem>, is_volatile: bool) -> Arc<Self> {
pub fn new(sym: S, fs: Weak<dyn FileSystem>, is_volatile: bool) -> Arc<Self> {
let common = {
let procfs = fs.downcast_ref::<ProcFS>().unwrap();
let arc_fs = fs.upgrade().unwrap();
let procfs = arc_fs.downcast_ref::<ProcFS>().unwrap();
let metadata = Metadata::new_symlink(
procfs.alloc_id(),
procfs.alloc_id() as _,
InodeMode::from_bits_truncate(0o777),
&fs.sb(),
super::BLOCK_SIZE,
);
Common::new(metadata, Arc::downgrade(&fs), is_volatile)
Common::new(metadata, fs, is_volatile)
};
Arc::new(Self { inner: sym, common })
}

View File

@ -7,7 +7,7 @@ use core::time::Duration;
use aster_rights::Full;
use core2::io::{Error as IoError, ErrorKind as IoErrorKind, Result as IoResult, Write};
use super::{DirentVisitor, FileSystem, IoctlCmd, SuperBlock};
use super::{DirentVisitor, FileSystem, IoctlCmd};
use crate::{
events::IoEvents,
fs::device::{Device, DeviceType},
@ -136,12 +136,12 @@ pub struct Metadata {
}
impl Metadata {
pub fn new_dir(ino: usize, mode: InodeMode, sb: &SuperBlock) -> Self {
pub fn new_dir(ino: usize, mode: InodeMode, blk_size: usize) -> Self {
Self {
dev: 0,
ino,
size: 2,
blk_size: sb.bsize,
blk_size,
blocks: 1,
atime: Default::default(),
mtime: Default::default(),
@ -155,12 +155,12 @@ impl Metadata {
}
}
pub fn new_file(ino: usize, mode: InodeMode, sb: &SuperBlock) -> Self {
pub fn new_file(ino: usize, mode: InodeMode, blk_size: usize) -> Self {
Self {
dev: 0,
ino,
size: 0,
blk_size: sb.bsize,
blk_size,
blocks: 0,
atime: Default::default(),
mtime: Default::default(),
@ -174,12 +174,12 @@ impl Metadata {
}
}
pub fn new_symlink(ino: usize, mode: InodeMode, sb: &SuperBlock) -> Self {
pub fn new_symlink(ino: usize, mode: InodeMode, blk_size: usize) -> Self {
Self {
dev: 0,
ino,
size: 0,
blk_size: sb.bsize,
blk_size,
blocks: 0,
atime: Default::default(),
mtime: Default::default(),
@ -192,12 +192,12 @@ impl Metadata {
rdev: 0,
}
}
pub fn new_device(ino: usize, mode: InodeMode, sb: &SuperBlock, device: &dyn Device) -> Self {
pub fn new_device(ino: usize, mode: InodeMode, blk_size: usize, device: &dyn Device) -> Self {
Self {
dev: 0,
ino,
size: 0,
blk_size: sb.bsize,
blk_size,
blocks: 0,
atime: Default::default(),
mtime: Default::default(),
@ -211,12 +211,12 @@ impl Metadata {
}
}
pub fn new_socket(ino: usize, mode: InodeMode, sb: &SuperBlock) -> Metadata {
pub fn new_socket(ino: usize, mode: InodeMode, blk_size: usize) -> Metadata {
Self {
dev: 0,
ino,
size: 0,
blk_size: sb.bsize,
blk_size,
blocks: 0,
atime: Default::default(),
mtime: Default::default(),