From 21a9ce8e53224100f331d9a666bc00c630964724 Mon Sep 17 00:00:00 2001 From: Chuyan Zhang Date: Sun, 3 Dec 2023 00:44:48 -0800 Subject: fix directory entry counting --- ayafs-core/src/filesystem/trait_impl.rs | 21 ++++++++---------- ayafs-core/src/memory/cached_inode.rs | 4 ++++ ayafs-core/src/memory/dir_entry.rs | 38 ++++++++++++++++----------------- ayafs-core/src/utils/permissions.rs | 27 +++++++++++------------ 4 files changed, 45 insertions(+), 45 deletions(-) diff --git a/ayafs-core/src/filesystem/trait_impl.rs b/ayafs-core/src/filesystem/trait_impl.rs index 39dba1a..48afac3 100644 --- a/ayafs-core/src/filesystem/trait_impl.rs +++ b/ayafs-core/src/filesystem/trait_impl.rs @@ -497,7 +497,7 @@ impl Filesystem for AyaFS { let mut parent_inode = parent_inode.clone(); // 不存在 -> No such file or directory - if let Ok((inode_index, entry_index, mut inode)) = + if let Ok((inode_index, _, mut inode)) = self.lookup_name(parent, &parent_inode, name) { let inode_index = inode_index as usize; @@ -533,12 +533,11 @@ impl Filesystem for AyaFS { // 删除 dir entry if let Err(err_code) = - self.remove_direntry(parent, &mut parent_inode, name, entry_index) + self.remove_direntry(parent, &mut parent_inode, name) { reply.error(err_code); return; } - parent_inode.size -= 1; self.update_inode(parent, parent_inode); reply.ok(); } else { @@ -580,7 +579,7 @@ impl Filesystem for AyaFS { let mut parent_inode = parent_inode.clone(); // 不存在 -> No such file or directory - if let Ok((inode_index, entry_index, inode)) = + if let Ok((inode_index, _, inode)) = self.lookup_name(parent, &parent_inode, name) { let inode_index = inode_index as usize; @@ -592,7 +591,9 @@ impl Filesystem for AyaFS { // 一定有 . 和 .. 所以 size == 2 就是空目录 // 目录非空 -> ENOTEMPTY - if inode.size > 2 { + let direntry_map = self.dir_entry_map.get(&inode_index).unwrap(); + if direntry_map.len() > 2 { + trace!("deleting inode {} failed, having {} directory entries", inode_index, direntry_map.len()); reply.error(ENOTEMPTY); return; } @@ -608,13 +609,12 @@ impl Filesystem for AyaFS { // 删除 dir entry if let Err(err_code) = - self.remove_direntry(parent, &mut parent_inode, name, entry_index) + self.remove_direntry(parent, &mut parent_inode, name) { reply.error(err_code); return; } - parent_inode.size -= 1; self.update_inode(parent, parent_inode); reply.ok(); } else { @@ -810,7 +810,7 @@ impl Filesystem for AyaFS { let mut parent_inode = parent_inode.clone(); match self.lookup_name(parent, &parent_inode, name) { - Ok((_inode_index, entry_index, _inode)) => { + Ok((_inode_index, _, _inode)) => { if let Some(new_parent_inode) = self.get_inode(new_parent) { if !check_access( req.uid(), @@ -830,7 +830,7 @@ impl Filesystem for AyaFS { let mut new_parent_inode = new_parent_inode.clone(); match self.lookup_name(new_parent, &new_parent_inode, new_name) { - Ok((_new_inode_index, new_entry_index, _new_inode)) => { + Ok((_new_inode_index, _, _new_inode)) => { // 新文件存在 if flags & RENAME_NOREPLACE != 0 { // 指定 noreplace 之后不允许覆盖文件 @@ -859,7 +859,6 @@ impl Filesystem for AyaFS { parent, &mut parent_inode, name, - entry_index, ) { reply.error(err_code); return; @@ -868,7 +867,6 @@ impl Filesystem for AyaFS { new_parent, &mut new_parent_inode, new_name, - new_entry_index, ) { reply.error(err_code); return; @@ -894,7 +892,6 @@ impl Filesystem for AyaFS { parent, &mut parent_inode, name, - entry_index, ) { reply.error(err_code); return; diff --git a/ayafs-core/src/memory/cached_inode.rs b/ayafs-core/src/memory/cached_inode.rs index 70579c7..c1e1909 100644 --- a/ayafs-core/src/memory/cached_inode.rs +++ b/ayafs-core/src/memory/cached_inode.rs @@ -4,6 +4,7 @@ use crate::{utils, AyaFS}; use and_then_some::BoolExt; use fuser::FileType; use libc::{c_int, EIO, EISDIR, ENOENT, ENOTDIR, ENOTEMPTY}; +use log::debug; impl AyaFS { pub(crate) fn create_file( @@ -103,7 +104,10 @@ impl AyaFS { // 不是 dir -> ENOTDIR return Err(ENOTDIR); } + + let direntry_map = self.dir_entry_map.get(&inode_index).unwrap(); if inode.size > 2 { + debug!("deleting inode {} failed, having {} directory entries", inode_index, direntry_map.len()); // 有 . 和 .. 以外的 entry -> ENOTEMPTY return Err(ENOTEMPTY); } diff --git a/ayafs-core/src/memory/dir_entry.rs b/ayafs-core/src/memory/dir_entry.rs index ee363b2..9a11d2a 100644 --- a/ayafs-core/src/memory/dir_entry.rs +++ b/ayafs-core/src/memory/dir_entry.rs @@ -72,6 +72,7 @@ impl AyaFS { parent_inode: &mut Inode, dir_entry_map: IndexMap, ) -> Result<(), c_int> { + parent_inode.size = dir_entry_map.len() as u64; for (entry_index, (name, dir_entry)) in dir_entry_map.into_iter().enumerate() { let block_index_within_inode = entry_index / 15; let entry_index_within_block = entry_index % 15; @@ -117,32 +118,36 @@ impl AyaFS { new_parent_inode: &mut Inode, new_name: T, ) -> Result<(), c_int> { + let name: &OsStr = name.as_ref(); + let new_name: &OsStr = new_name.as_ref(); self.load_direntry_map(parent_index, parent_inode)?; self.load_direntry_map(new_parent_index, new_parent_inode)?; + if parent_index != new_parent_index { + parent_inode.size -= 1; + new_parent_inode.size += 1; + } + let dir_entry = self .dir_entry_map .get(&parent_index) .ok_or(ENOENT)? - .get(name.as_ref()) + .get(name) .cloned() .ok_or(ENOENT)?; let new_dir_entry = self .dir_entry_map .get(&new_parent_index) .ok_or(ENOENT)? - .get(new_name.as_ref()) + .get(new_name) .cloned() .ok_or(ENOENT)?; - let name: &OsStr = name.as_ref(); - let new_name: &OsStr = new_name.as_ref(); - self.dir_entry_map .get_mut(&parent_index) .map(|dir_entry_map| { if let Occupied(mut entry) = dir_entry_map.entry(name.to_os_string()) { - *entry.get_mut() = new_dir_entry.clone(); + *entry.get_mut() = new_dir_entry; } }) .ok_or(ENOENT)?; @@ -150,7 +155,7 @@ impl AyaFS { .get_mut(&new_parent_index) .map(|new_dir_entry_map| { if let Occupied(mut entry) = new_dir_entry_map.entry(new_name.to_os_string()) { - *entry.get_mut() = dir_entry.clone(); + *entry.get_mut() = dir_entry; } }) .ok_or(ENOENT)?; @@ -164,12 +169,12 @@ impl AyaFS { parent_index: usize, parent_inode: &mut Inode, name: T, - _entry_index: u32, ) -> Result<(), c_int> { self.load_direntry_map(parent_index, parent_inode)?; if let Some(dir_entry_map) = self.dir_entry_map.get_mut(&parent_index) { - trace!(" remove_direntry(ino: {}) using hashmap", parent_index); if dir_entry_map.shift_remove(name.as_ref()).is_some() { + parent_inode.size = dir_entry_map.len() as u64; + // trace!("remove_direntry(parent: {:#x}, name: {:?}), parent inode size is {}, direntry_map size is {}", parent_index, name.as_ref(), parent_inode.size, dir_entry_map.len()); Ok(()) } else { Err(ENOENT) @@ -191,11 +196,9 @@ impl AyaFS { if let Some(dir_entry_map) = self.dir_entry_map.get_mut(&parent_index) { let (entry_index, _) = dir_entry_map.insert_full(child_inode_name.to_os_string(), dir_entry); - trace!( - " add_direntry(ino: {}) using hashmap, entry {}", - parent_index, entry_index - ); - parent_inode.size += 1; + // trace!("parent inode size {} before +1", parent_inode.size); + parent_inode.size = dir_entry_map.len() as u64; + // trace!("add_direntry_2(parent: {:#x}, name: {:?}), parent inode size is {}, direntry_map size is {}", parent_index, child_inode_name, parent_inode.size, dir_entry_map.len()); Ok(entry_index as u32) } else { Err(ENOENT) @@ -227,11 +230,8 @@ impl AyaFS { let (entry_index, _) = dir_entry_map.insert_full(child_inode_name.to_os_string(), dir_entry); - trace!( - " add_direntry(ino: {}) using hashmap, entry {}", - parent_index, entry_index - ); - parent_inode.size += 1; + parent_inode.size = dir_entry_map.len() as u64; + trace!("add_direntry(parent: {:#x}, name: {:?}), parent inode size is {}, direntry_map size is {}", parent_index, child_inode_name, parent_inode.size, dir_entry_map.len()); Ok(entry_index as u32) } else { Err(ENOENT) diff --git a/ayafs-core/src/utils/permissions.rs b/ayafs-core/src/utils/permissions.rs index 53205b5..756ca95 100644 --- a/ayafs-core/src/utils/permissions.rs +++ b/ayafs-core/src/utils/permissions.rs @@ -2,7 +2,7 @@ use crate::disk::inode::InodeMode; use libc::{F_OK, S_ISGID, S_ISUID, S_IXGRP, X_OK}; use std::fs::File; use std::io::BufRead; -use log::debug; +use log::trace; pub(crate) fn get_groups(pid: u32) -> Vec { let file = File::open(format!("/proc/{pid}/task/{pid}/status")) @@ -37,8 +37,16 @@ pub(crate) fn check_access( mode: InodeMode, mut mask: i32, ) -> bool { - let mask_mem = mask; - // true + trace!( + "check_access(incoming_uid: {}, incoming_gid: {}, uid: {}, gid: {}, mode: {:#o}, mask: {:#x})", + incoming_uid, + incoming_gid, + uid, + gid, + mode.0, + mask, + ); + if mask == F_OK { return true; } @@ -51,6 +59,7 @@ pub(crate) fn check_access( mask -= mask & (perm >> 6); mask -= mask & (perm >> 3); mask -= mask & perm; + trace!("check_access -> {}", mask == 0); return mask == 0; } @@ -62,16 +71,6 @@ pub(crate) fn check_access( mask -= mask & perm; } - debug!( - "check_access(incoming_uid: {}, incoming_gid: {}, uid: {}, gid: {}, mode: {:#o}, mask: {:#x}) -> {}", - incoming_uid, - incoming_gid, - uid, - gid, - mode.0, - mask_mem, - mask == 0, - ); - + trace!("check_access -> {}", mask == 0); mask == 0 } -- cgit v1.2.3-70-g09d2