summaryrefslogtreecommitdiff
path: root/ayafs/src/memory/cached_inode.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ayafs/src/memory/cached_inode.rs')
-rw-r--r--ayafs/src/memory/cached_inode.rs178
1 files changed, 178 insertions, 0 deletions
diff --git a/ayafs/src/memory/cached_inode.rs b/ayafs/src/memory/cached_inode.rs
new file mode 100644
index 0000000..2f26dde
--- /dev/null
+++ b/ayafs/src/memory/cached_inode.rs
@@ -0,0 +1,178 @@
+use crate::disk::block::InodeBlock;
+use crate::disk::inode::{Inode, INODE_SIZE};
+use crate::{utils, AyaFS};
+use and_then_some::BoolExt;
+use fuser::FileType;
+use libc::{c_int, EIO, EISDIR, ENOENT, ENOTDIR, ENOTEMPTY};
+
+impl AyaFS {
+ pub(crate) fn create_file(
+ &mut self,
+ permissions: u16,
+ uid: u32,
+ gid: u32,
+ flags: u32,
+ ) -> Option<(usize, &Inode)> {
+ self.inode_bitmap.allocate().map(|inode_index| {
+ self.get_inode_mut(inode_index).map(|inode| {
+ *inode = Inode::file(permissions, uid, gid, utils::time_now(), flags, 0, 0, 0);
+ });
+ (inode_index, self.get_inode(inode_index).unwrap())
+ })
+ }
+
+ pub(crate) fn create_symlink(
+ &mut self,
+ permissions: u16,
+ uid: u32,
+ gid: u32,
+ flags: u32,
+ ) -> Option<(usize, &Inode)> {
+ self.inode_bitmap.allocate().map(|inode_index| {
+ self.get_inode_mut(inode_index).map(|inode| {
+ *inode = Inode::symlink(permissions, uid, gid, utils::time_now(), flags, 0, 0, 0);
+ });
+ (inode_index, self.get_inode(inode_index).unwrap())
+ })
+ }
+
+ /// 根目录的 parent_inode_number 传入 None, 会直接以自己作为 .. 的 inode number
+ pub(crate) fn create_directory(
+ &mut self,
+ permissions: u16,
+ uid: u32,
+ gid: u32,
+ flags: u32,
+ parent_inode_number: Option<usize>,
+ ) -> Option<(usize, &Inode)> {
+ self.inode_bitmap.allocate().map(|inode_index| {
+ // 创建 Inode
+ let mut new_inode =
+ Inode::directory(permissions, uid, gid, utils::time_now(), flags, 0, 0, 0);
+ self.init_direntry_map(inode_index);
+ self.add_direntry(inode_index, &mut new_inode, inode_index, ".", 0x2)
+ .unwrap();
+ self.add_direntry(
+ inode_index,
+ &mut new_inode,
+ parent_inode_number.unwrap_or(inode_index),
+ "..",
+ 0x2,
+ )
+ .unwrap();
+ // 把 inode 放到指定位置
+ self.get_inode_mut(inode_index).map(|inode| {
+ *inode = new_inode;
+ });
+
+ (inode_index, self.get_inode(inode_index).unwrap())
+ })
+ }
+
+ pub(crate) fn remove_file(&mut self, inode_index: usize) -> Result<bool, c_int> {
+ if self.inode_bitmap.query(inode_index) {
+ let (block_index, offset) = self.locate_inode(inode_index);
+ if let Some(cached_block) = self.cached_inodes.get_block::<InodeBlock>(block_index) {
+ let inode = cached_block.block.inodes[offset / INODE_SIZE].clone();
+ match inode.file_type() {
+ FileType::RegularFile => self.deallocate_all_blocks_for(&inode).unwrap(),
+ FileType::Symlink => {
+ if inode.size >= 60 {
+ self.deallocate_all_blocks_for(&inode).unwrap();
+ }
+ }
+ FileType::Directory => return Err(EISDIR),
+ _ => return Err(EIO),
+ }
+ }
+ self.inode_bitmap.deallocate(inode_index);
+ Ok(true)
+ } else {
+ Err(ENOENT)
+ }
+ }
+
+ // 要删除的 inode 一定得是空的
+ pub(crate) fn remove_dir(&mut self, inode_index: usize) -> Result<bool, c_int> {
+ if self.inode_bitmap.query(inode_index) {
+ let (block_index, offset) = self.locate_inode(inode_index);
+ if let Some(cached_block) = self.cached_inodes.get_block::<InodeBlock>(block_index) {
+ let inode = &cached_block.block.inodes[offset / INODE_SIZE].clone();
+ if !inode.is_dir() {
+ // 不是 dir -> ENOTDIR
+ return Err(ENOTDIR);
+ }
+ if inode.size > 2 {
+ // 有 . 和 .. 以外的 entry -> ENOTEMPTY
+ return Err(ENOTEMPTY);
+ }
+ // 销毁 inode 里的所有 block
+ self.deallocate_all_blocks_for(inode).unwrap();
+ }
+ // 销毁 inode
+ self.inode_bitmap.deallocate(inode_index);
+ Ok(true)
+ } else {
+ Err(ENOENT)
+ }
+ }
+
+ pub(crate) fn update_inode(&mut self, inode_index: usize, inode: Inode) -> bool {
+ if self.inode_bitmap.query(inode_index) {
+ let (block_index, offset) = self.locate_inode(inode_index);
+ if let Some(cached_block) = self.cached_inodes.get_block_mut::<InodeBlock>(block_index)
+ {
+ cached_block.block.inodes[offset / INODE_SIZE] = inode;
+ }
+ true
+ } else {
+ false
+ }
+ }
+
+ pub(crate) fn get_inode(&mut self, inode_index: usize) -> Option<&Inode> {
+ self.inode_bitmap.query(inode_index).and_then(|| {
+ let (block_index, offset) = self.locate_inode(inode_index);
+ // debug!("get_inode(inode_index: {}) -> block_index: {}, offset: {}", inode_index, block_index, offset);
+ self.cached_inodes
+ .get_block::<InodeBlock>(block_index)
+ .map(|cached_block| &cached_block.block.inodes[offset / INODE_SIZE])
+ })
+ }
+
+ pub(crate) fn get_inode_mut(&mut self, inode_index: usize) -> Option<&mut Inode> {
+ self.inode_bitmap.query(inode_index).and_then(|| {
+ let (block_index, offset) = self.locate_inode(inode_index);
+ // debug!("get_inode_mut(inode_index: {}) -> block_index: {}, offset: {}", inode_index, block_index, offset);
+ self.cached_inodes
+ .get_block_mut::<InodeBlock>(block_index)
+ .map(|cached_block| {
+ cached_block.dirty = true; // 保守一些, 只要返回了 &mut Inode 这个页一定标记为脏
+ &mut cached_block.block.inodes[offset / INODE_SIZE]
+ })
+ })
+ }
+
+ #[allow(unused)]
+ pub(crate) fn peek_inode(&self, inode_index: usize) -> Option<&Inode> {
+ self.inode_bitmap.query(inode_index).and_then(|| {
+ let (block_index, offset) = self.locate_inode(inode_index);
+ self.cached_inodes
+ .peek_block::<InodeBlock>(block_index)
+ .map(|cached_block| &cached_block.block.inodes[offset / INODE_SIZE])
+ })
+ }
+
+ #[allow(unused)]
+ pub(crate) fn peek_inode_mut(&mut self, inode_index: usize) -> Option<&mut Inode> {
+ self.inode_bitmap.query(inode_index).and_then(|| {
+ let (block_index, offset) = self.locate_inode(inode_index);
+ self.cached_inodes
+ .peek_block_mut::<InodeBlock>(block_index)
+ .map(|cached_block| {
+ cached_block.dirty = true; // 保守一些, 只要返回了 &mut Inode 这个页一定标记为脏
+ &mut cached_block.block.inodes[offset / INODE_SIZE]
+ })
+ })
+ }
+}