Refine ProcFs by improving the use of locks
This commit is contained in:
parent
6ff8497101
commit
494c88e993
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 })
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
Loading…
Reference in New Issue