ソースを参照

fix: free inode

liujingx 10 ヶ月 前
コミット
d0c26cacf2
4 ファイル変更31 行追加27 行削除
  1. 0 5
      src/ext4/alloc.rs
  2. 17 10
      src/ext4/dir.rs
  3. 11 9
      src/ext4/link.rs
  4. 3 3
      src/ext4/low_level.rs

+ 0 - 5
src/ext4/alloc.rs

@@ -53,8 +53,6 @@ impl Ext4 {
         for pblock in pblocks {
             // Deallocate the block
             self.dealloc_block(inode, pblock)?;
-            // Update inode block count
-            inode.inode.set_block_count(inode.inode.block_count() - 1);
             // Clear the block content
             self.write_block(&Block::new(pblock, [0; BLOCK_SIZE]));
         }
@@ -69,9 +67,6 @@ impl Ext4 {
         }
         // Deallocate the inode
         self.dealloc_inode(&inode)?;
-        // Clear the inode content
-        inode.inode = unsafe { core::mem::zeroed() };
-        self.write_inode_without_csum(inode);
         Ok(())
     }
 

+ 17 - 10
src/ext4/dir.rs

@@ -2,6 +2,7 @@ use super::Ext4;
 use crate::constants::*;
 use crate::ext4_defs::*;
 use crate::prelude::*;
+use crate::return_error;
 
 impl Ext4 {
     /// Find a directory entry that matches a given name under a parent directory
@@ -21,7 +22,12 @@ impl Ext4 {
             }
             iblock += 1;
         }
-        Err(Ext4Error::new(ErrCode::ENOENT))
+        return_error!(
+            ErrCode::ENOENT,
+            "Directory entry not found: dir {}, name {}",
+            dir.id,
+            name
+        );
     }
 
     /// Add an entry to a directory, memory consistency guaranteed
@@ -33,7 +39,9 @@ impl Ext4 {
     ) -> Result<()> {
         trace!(
             "Dir add entry: dir {}, child {}, name {}",
-            dir.id, child.id, name
+            dir.id,
+            child.id,
+            name
         );
         let total_blocks: u32 = dir.inode.block_count() as u32;
 
@@ -67,9 +75,8 @@ impl Ext4 {
 
     /// Remove a entry from a directory
     pub(super) fn dir_remove_entry(&self, dir: &InodeRef, name: &str) -> Result<()> {
-        trace!("Dir remove entry: dir {}, path {}", dir.id, name);
+        trace!("Dir remove entry: dir {}, name {}", dir.id, name);
         let total_blocks: u32 = dir.inode.block_count() as u32;
-
         // Check each block
         let mut iblock: LBlockId = 0;
         while iblock < total_blocks {
@@ -85,14 +92,17 @@ impl Ext4 {
             // Current block has no enough space
             iblock += 1;
         }
-
         // Not found the target entry
-        Err(Ext4Error::new(ErrCode::ENOENT))
+        return_error!(
+            ErrCode::ENOENT,
+            "Directory entry not found: dir {}, name {}",
+            dir.id,
+            name
+        );
     }
 
     /// Get all entries under a directory
     pub(super) fn dir_get_all_entries(&self, dir: &InodeRef) -> Vec<DirEntry> {
-        trace!("Dir get all entries: dir {} link count {}", dir.id, dir.inode.link_count());
         let total_blocks = dir.inode.block_count() as u32;
         let mut entries: Vec<DirEntry> = Vec::new();
         let mut iblock: LBlockId = 0;
@@ -110,7 +120,6 @@ impl Ext4 {
 
     /// Find a directory entry that matches a given name in a given block
     fn find_entry_in_block(block: &Block, name: &str) -> Option<DirEntry> {
-        trace!("Dir find entry {} in block {}", name, block.id);
         let mut offset = 0;
         while offset < BLOCK_SIZE {
             let de: DirEntry = block.read_offset_as(offset);
@@ -124,7 +133,6 @@ impl Ext4 {
 
     /// Remove a directory entry that matches a given name from a given block
     fn remove_entry_from_block(block: &mut Block, name: &str) -> bool {
-        trace!("Dir remove entry {} from block {}", name, block.id);
         let mut offset = 0;
         while offset < BLOCK_SIZE {
             let mut de: DirEntry = block.read_offset_as(offset);
@@ -141,7 +149,6 @@ impl Ext4 {
 
     /// Get all directory entries from a given block
     fn get_all_entries_from_block(block: &Block, entries: &mut Vec<DirEntry>) {
-        trace!("Dir get all entries from block {}", block.id);
         let mut offset = 0;
         while offset < BLOCK_SIZE {
             let de: DirEntry = block.read_offset_as(offset);

+ 11 - 9
src/ext4/link.rs

@@ -44,20 +44,22 @@ impl Ext4 {
         self.dir_remove_entry(parent, name)?;
 
         let child_link_cnt = child.inode.link_count();
-        if child.inode.is_dir() && child_link_cnt == 2 {
-            // If child is an empty directory
+        if child.inode.is_dir() && child_link_cnt <= 2 {
+            // Child is an empty directory
             // Unlink "child/.."
             parent.inode.set_link_count(parent.inode.link_count() - 1);
             self.write_inode_with_csum(parent);
             // Remove directory
-            return self.free_inode(child);
-        } else if child_link_cnt == 1 {
+            self.free_inode(child)
+        } else if child_link_cnt <= 1 {
+            // Child is a file
             // Remove file
-            return self.free_inode(child);
+            self.free_inode(child)
+        } else {
+            // Not remove
+            child.inode.set_link_count(child_link_cnt - 1);
+            self.write_inode_with_csum(child);
+            Ok(())
         }
-        // Not remove
-        child.inode.set_link_count(child_link_cnt - 1);
-        self.write_inode_with_csum(child);
-        Ok(())
     }
 }

+ 3 - 3
src/ext4/low_level.rs

@@ -26,9 +26,9 @@ impl Ext4 {
     /// `EINVAL` if the inode is invalid (link count == 0).
     pub fn getattr(&self, id: InodeId) -> Result<FileAttr> {
         let inode = self.read_inode(id);
-        // if inode.inode.link_count() == 0 {
-        //     return_error!(ErrCode::EINVAL, "Invalid inode {}", id);
-        // }
+        if inode.inode.link_count() == 0 {
+            return_error!(ErrCode::EINVAL, "Invalid inode {}", id);
+        }
         Ok(FileAttr {
             ino: id,
             size: inode.inode.size(),