From 4a2da992a6fd0cf817138f550f4470323b642aed Mon Sep 17 00:00:00 2001 From: Fabing Li Date: Fri, 9 Aug 2024 11:18:50 +0800 Subject: [PATCH] Add Extension implementation on inode for lock storing --- kernel/aster-nix/src/fs/exfat/inode.rs | 9 ++- .../src/fs/ext2/impl_for_vfs/inode.rs | 7 +- kernel/aster-nix/src/fs/ext2/inode.rs | 8 +- kernel/aster-nix/src/fs/ramfs/fs.rs | 16 +++- kernel/aster-nix/src/fs/utils/inode.rs | 78 ++++++++++++++++++- 5 files changed, 112 insertions(+), 6 deletions(-) diff --git a/kernel/aster-nix/src/fs/exfat/inode.rs b/kernel/aster-nix/src/fs/exfat/inode.rs index 7da4fe3ed..b324099f1 100644 --- a/kernel/aster-nix/src/fs/exfat/inode.rs +++ b/kernel/aster-nix/src/fs/exfat/inode.rs @@ -31,7 +31,7 @@ use crate::{ device::Device, exfat::{dentry::ExfatDentryIterator, fat::ExfatChain, fs::ExfatFS}, utils::{ - DirentVisitor, Inode, InodeMode, InodeType, IoctlCmd, Metadata, PageCache, + DirentVisitor, Extension, Inode, InodeMode, InodeType, IoctlCmd, Metadata, PageCache, PageCacheBackend, }, }, @@ -79,6 +79,7 @@ impl FatAttr { #[derive(Debug)] pub struct ExfatInode { inner: RwMutex, + extension: Extension, } #[derive(Debug)] @@ -667,6 +668,7 @@ impl ExfatInode { fs: fs_weak, page_cache: PageCache::with_capacity(size, weak_self.clone() as _).unwrap(), }), + extension: Extension::new(), }); let inner = inode.inner.upread(); @@ -776,6 +778,7 @@ impl ExfatInode { fs: fs_weak, page_cache: PageCache::with_capacity(size, weak_self.clone() as _).unwrap(), }), + extension: Extension::new(), }); if matches!(inode_type, InodeType::Dir) { @@ -1703,4 +1706,8 @@ impl Inode for ExfatInode { fn is_dentry_cacheable(&self) -> bool { true } + + fn extension(&self) -> Option<&Extension> { + Some(&self.extension) + } } diff --git a/kernel/aster-nix/src/fs/ext2/impl_for_vfs/inode.rs b/kernel/aster-nix/src/fs/ext2/impl_for_vfs/inode.rs index 048babd6f..2f0200c76 100644 --- a/kernel/aster-nix/src/fs/ext2/impl_for_vfs/inode.rs +++ b/kernel/aster-nix/src/fs/ext2/impl_for_vfs/inode.rs @@ -11,7 +11,8 @@ use crate::{ device::Device, ext2::{FilePerm, FileType, Inode as Ext2Inode}, utils::{ - DirentVisitor, FallocMode, FileSystem, Inode, InodeMode, InodeType, IoctlCmd, Metadata, + DirentVisitor, Extension, FallocMode, FileSystem, Inode, InodeMode, InodeType, + IoctlCmd, Metadata, }, }, prelude::*, @@ -193,6 +194,10 @@ impl Inode for Ext2Inode { fn fs(&self) -> Arc { self.fs() } + + fn extension(&self) -> Option<&Extension> { + Some(self.extension()) + } } impl From for InodeMode { diff --git a/kernel/aster-nix/src/fs/ext2/inode.rs b/kernel/aster-nix/src/fs/ext2/inode.rs index a39fc1824..269cb9980 100644 --- a/kernel/aster-nix/src/fs/ext2/inode.rs +++ b/kernel/aster-nix/src/fs/ext2/inode.rs @@ -16,7 +16,7 @@ use super::{ prelude::*, utils::now, }; -use crate::fs::utils::FallocMode; +use crate::fs::utils::{Extension, FallocMode}; /// Max length of file name. pub const MAX_FNAME_LEN: usize = 255; @@ -30,6 +30,7 @@ pub struct Inode { block_group_idx: usize, inner: RwMutex, fs: Weak, + extension: Extension, } impl Inode { @@ -44,6 +45,7 @@ impl Inode { block_group_idx, inner: RwMutex::new(Inner::new(desc, weak_self.clone(), fs.clone())), fs, + extension: Extension::new(), }) } @@ -736,6 +738,10 @@ impl Inode { inner.set_ctime(now()); } + pub fn extension(&self) -> &Extension { + &self.extension + } + pub fn fallocate(&self, mode: FallocMode, offset: usize, len: usize) -> Result<()> { if self.file_type() != FileType::File { return_errno_with_message!(Errno::EISDIR, "not regular file"); diff --git a/kernel/aster-nix/src/fs/ramfs/fs.rs b/kernel/aster-nix/src/fs/ramfs/fs.rs index 1c81442f4..39a621871 100644 --- a/kernel/aster-nix/src/fs/ramfs/fs.rs +++ b/kernel/aster-nix/src/fs/ramfs/fs.rs @@ -19,8 +19,8 @@ use crate::{ fs::{ device::Device, utils::{ - CStr256, DirentVisitor, FallocMode, FileSystem, FsFlags, Inode, InodeMode, InodeType, - IoctlCmd, Metadata, PageCache, PageCacheBackend, SuperBlock, + CStr256, DirentVisitor, Extension, FallocMode, FileSystem, FsFlags, Inode, InodeMode, + InodeType, IoctlCmd, Metadata, PageCache, PageCacheBackend, SuperBlock, }, }, prelude::*, @@ -55,6 +55,7 @@ impl RamFS { typ: InodeType::Dir, this: weak_root.clone(), fs: weak_fs.clone(), + extension: Extension::new(), }), inode_allocator: AtomicU64::new(ROOT_INO + 1), }) @@ -99,6 +100,8 @@ struct RamInode { this: Weak, /// Reference to fs fs: Weak, + /// Extensions + extension: Extension, } struct Node { @@ -415,6 +418,7 @@ impl RamInode { typ: InodeType::Dir, this: weak_self.clone(), fs: Arc::downgrade(fs), + extension: Extension::new(), }) } @@ -425,6 +429,7 @@ impl RamInode { typ: InodeType::File, this: weak_self.clone(), fs: Arc::downgrade(fs), + extension: Extension::new(), }) } @@ -435,6 +440,7 @@ impl RamInode { typ: InodeType::SymLink, this: weak_self.clone(), fs: Arc::downgrade(fs), + extension: Extension::new(), }) } @@ -445,6 +451,7 @@ impl RamInode { typ: InodeType::Socket, this: weak_self.clone(), fs: Arc::downgrade(fs), + extension: Extension::new(), }) } @@ -461,6 +468,7 @@ impl RamInode { typ: InodeType::from(device.type_()), this: weak_self.clone(), fs: Arc::downgrade(fs), + extension: Extension::new(), }) } @@ -1154,6 +1162,10 @@ impl Inode for RamInode { } return_errno_with_message!(Errno::EINVAL, "ioctl is not supported"); } + + fn extension(&self) -> Option<&Extension> { + Some(&self.extension) + } } fn write_lock_two_inodes<'a>( diff --git a/kernel/aster-nix/src/fs/utils/inode.rs b/kernel/aster-nix/src/fs/utils/inode.rs index 935b7daac..9e7e40942 100644 --- a/kernel/aster-nix/src/fs/utils/inode.rs +++ b/kernel/aster-nix/src/fs/utils/inode.rs @@ -2,7 +2,7 @@ #![allow(unused_variables)] -use core::time::Duration; +use core::{any::TypeId, time::Duration}; use aster_rights::Full; use core2::io::{Error as IoError, ErrorKind as IoErrorKind, Result as IoResult, Write}; @@ -385,6 +385,11 @@ pub trait Inode: Any + Sync + Send { fn is_dentry_cacheable(&self) -> bool { true } + + /// Get the extension of this inode + fn extension(&self) -> Option<&Extension> { + None + } } impl dyn Inode { @@ -454,3 +459,74 @@ impl Debug for dyn Inode { .finish() } } + +/// An extension is a set of objects that is attached to +/// an inode. +/// +/// Each objects of an extension is of different types. +/// In other words, types are used as the keys to get and +/// set the objects in an extension. +#[derive(Debug)] +pub struct Extension { + data: RwLock>>, +} + +impl Extension { + pub fn new() -> Self { + Self { + data: RwLock::new(BTreeMap::new()), + } + } + + /// Get an object of `Arc`. + pub fn get(&self) -> Option> { + let read_guard = self.data.read(); + read_guard + .get(&TypeId::of::()) + .and_then(|arc_any| Arc::downcast::(arc_any.clone()).ok()) + } + + /// Try to get an object of `Arc`. If no object of the type exists, + /// put the default value for the type, then return it. + pub fn get_or_put_default(&self) -> Arc { + let mut write_guard = self.data.write(); + let type_id = TypeId::of::(); + let arc_any = write_guard.entry(type_id).or_insert_with(|| { + let obj = T::default(); + Arc::new(obj) as Arc + }); + Arc::downcast::(arc_any.clone()).unwrap() + } + + /// Put an object of `Arc`. If there exists one object of the type, + /// then the old one is returned. + pub fn put(&self, obj: Arc) -> Option> { + let mut write_guard = self.data.write(); + write_guard + .insert(TypeId::of::(), obj as Arc) + .and_then(|arc_any| Arc::downcast::(arc_any).ok()) + } + + /// Delete an object of `Arc`. If there exists one object of the type, + /// then the old one is returned. + pub fn del(&self) -> Option> { + let mut write_guard = self.data.write(); + write_guard + .remove(&TypeId::of::()) + .and_then(|arc_any| Arc::downcast::(arc_any).ok()) + } +} + +impl Clone for Extension { + fn clone(&self) -> Self { + Self { + data: RwLock::new(self.data.read().clone()), + } + } +} + +impl Default for Extension { + fn default() -> Self { + Self::new() + } +}