Browse Source

fix: alloc block

liujingx 1 year ago
parent
commit
d8f0b3d088
6 changed files with 27 additions and 45 deletions
  1. 1 0
      src/constants.rs
  2. 10 10
      src/ext4/alloc.rs
  3. 4 4
      src/ext4/extent.rs
  4. 1 0
      src/ext4_defs/bitmap.rs
  5. 7 22
      src/ext4_defs/extent.rs
  6. 4 9
      src/ext4_defs/inode.rs

+ 1 - 0
src/constants.rs

@@ -40,3 +40,4 @@ pub const EXT4_ROOT_INO: InodeId = 2;
 
 pub const BASE_OFFSET: usize = 1024;
 pub const BLOCK_SIZE: usize = 4096;
+pub const INODE_BLOCK_SIZE: usize = 512;

+ 10 - 10
src/ext4/alloc.rs

@@ -8,10 +8,10 @@ impl Ext4 {
     pub(super) fn alloc_block(
         &mut self,
         inode_ref: &mut InodeRef,
-        goal: PBlockId,
     ) -> Result<PBlockId> {
-        let bgid = (goal / self.super_block.blocks_per_group() as u64) as BlockGroupId;
-        let idx_in_bg = goal % self.super_block.blocks_per_group() as u64;
+        // Calc block group id
+        let inodes_per_group = self.super_block.inodes_per_group();
+        let bgid = ((inode_ref.id - 1) / inodes_per_group) as BlockGroupId;
 
         // Load block group descriptor
         let mut bg = self.read_block_group(bgid);
@@ -23,7 +23,7 @@ impl Ext4 {
 
         // Find the first free block
         let fblock = bitmap
-            .find_and_set_first_clear_bit(idx_in_bg as usize, 8 * BLOCK_SIZE)
+            .find_and_set_first_clear_bit(0, 8 * BLOCK_SIZE)
             .ok_or(Ext4Error::new(ErrCode::ENOSPC))? as PBlockId;
 
         // Set block group checksum
@@ -31,18 +31,18 @@ impl Ext4 {
         self.block_device.write_block(&bitmap_block);
 
         // Update superblock free blocks count
-        let free_blocks = self.super_block.free_blocks_count();
-        self.super_block.set_free_blocks_count(free_blocks); // TODO: why not - 1?
+        let free_blocks = self.super_block.free_blocks_count() - 1;
+        self.super_block.set_free_blocks_count(free_blocks);
         self.super_block.sync_to_disk(self.block_device.clone());
 
         // Update inode blocks (different block size!) count
-        let inode_blocks = inode_ref.inode.blocks_count();
-        inode_ref.inode.set_blocks_count(inode_blocks as u32 + 8); // TODO: why + 8?
+        let inode_blocks = inode_ref.inode.blocks_count() + (BLOCK_SIZE / INODE_BLOCK_SIZE) as u64;
+        inode_ref.inode.set_blocks_count(inode_blocks);
         self.write_inode_with_csum(inode_ref);
 
         // Update block group free blocks count
-        let fb_cnt = bg.desc.get_free_blocks_count();
-        bg.desc.set_free_blocks_count(fb_cnt - 1);
+        let fb_cnt = bg.desc.get_free_blocks_count() - 1;
+        bg.desc.set_free_blocks_count(fb_cnt);
 
         self.write_block_group_with_csum(&mut bg);
 

+ 4 - 4
src/ext4/extent.rs

@@ -114,7 +114,7 @@ impl Ext4 {
                 // Not found, create a new extent
                 let block_count = min(block_count, EXT_MAX_BLOCKS - iblock);
                 // Allocate physical block
-                let fblock = self.alloc_block(inode_ref, 0)?;
+                let fblock = self.alloc_block(inode_ref)?;
                 // Create a new extent
                 let new_ext = Extent::new(iblock, fblock, block_count as u16);
                 // Insert the new extent
@@ -187,7 +187,7 @@ impl Ext4 {
         child_pos: usize,
         split: &[FakeExtent],
     ) -> core::result::Result<(), Vec<FakeExtent>> {
-        let right_bid = self.alloc_block(inode_ref, 0).unwrap();
+        let right_bid = self.alloc_block(inode_ref).unwrap();
         let mut right_block = self.block_device.read_block(right_bid);
         let mut right_node = ExtentNodeMut::from_bytes(&mut right_block.data);
 
@@ -228,8 +228,8 @@ impl Ext4 {
     /// This function will create a new leaf node to store the split part.
     fn split_root(&mut self, inode_ref: &mut InodeRef, split: &[FakeExtent]) -> Result<()> {
         // Create left and right blocks
-        let l_bid = self.alloc_block(inode_ref, 0)?;
-        let r_bid = self.alloc_block(inode_ref, 0)?;
+        let l_bid = self.alloc_block(inode_ref)?;
+        let r_bid = self.alloc_block(inode_ref)?;
         let mut l_block = self.block_device.read_block(l_bid);
         let mut r_block = self.block_device.read_block(r_bid);
 

+ 1 - 0
src/ext4_defs/bitmap.rs

@@ -27,6 +27,7 @@ impl<'a> Bitmap<'a> {
 
     /// Find the first clear bit in the range `[start, end)`
     pub fn first_clear_bit(&self, start: usize, end: usize) -> Option<usize> {
+        let end = core::cmp::min(end, self.0.len() * 8);
         for i in start..end {
             if self.is_bit_clear(i) {
                 return Some(i);

+ 7 - 22
src/ext4_defs/extent.rs

@@ -56,52 +56,37 @@ impl ExtentHeader {
         unsafe { &*(block_data.as_ptr() as *const ExtentHeader) }
     }
 
-    // 获取extent header的魔数
-    pub fn magic(&self) -> u16 {
-        self.magic
-    }
-
-    // 设置extent header的魔数
-    pub fn set_magic(&mut self) {
-        self.magic = EXT4_EXTENT_MAGIC;
-    }
-
-    // 获取extent header的条目数
+    /// 获取extent header的条目数
     pub fn entries_count(&self) -> u16 {
         self.entries_count
     }
 
-    // 设置extent header的条目数
+    /// 设置extent header的条目数
     pub fn set_entries_count(&mut self, count: u16) {
         self.entries_count = count;
     }
 
-    // 获取extent header的最大条目数
+    /// 获取extent header的最大条目数
     pub fn max_entries_count(&self) -> u16 {
         self.max_entries_count
     }
 
-    // 设置extent header的最大条目数
-    pub fn set_max_entries_count(&mut self, max_count: u16) {
-        self.max_entries_count = max_count;
-    }
-
-    // 获取extent header的深度
+    /// 获取extent header的深度
     pub fn depth(&self) -> u16 {
         self.depth
     }
 
-    // 设置extent header的深度
+    /// 设置extent header的深度
     pub fn set_depth(&mut self, depth: u16) {
         self.depth = depth;
     }
 
-    // 获取extent header的生成号
+    /// 获取extent header的生成号
     pub fn generation(&self) -> u32 {
         self.generation
     }
 
-    // 设置extent header的生成号
+    /// 设置extent header的生成号
     pub fn set_generation(&mut self, generation: u32) {
         self.generation = generation;
     }

+ 4 - 9
src/ext4_defs/inode.rs

@@ -11,7 +11,6 @@ use super::crc::*;
 use super::AsBytes;
 use super::BlockDevice;
 use super::BlockGroupRef;
-use super::ExtentHeader;
 use super::Superblock;
 use super::{ExtentNode, ExtentNodeMut};
 use crate::constants::*;
@@ -157,8 +156,9 @@ impl Inode {
         blocks
     }
 
-    pub fn set_blocks_count(&mut self, blocks_count: u32) {
-        self.blocks = blocks_count;
+    pub fn set_blocks_count(&mut self, blocks_count: u64) {
+        self.blocks = (blocks_count & 0xFFFFFFFF) as u32;
+        self.osd2.l_i_blocks_high = (blocks_count >> 32) as u16;
     }
 
     pub fn set_generation(&mut self, generation: u32) {
@@ -198,12 +198,7 @@ impl Inode {
     /// node of the extent tree
     pub fn extent_init(&mut self) {
         self.set_flags(EXT4_INODE_FLAG_EXTENTS);
-        let header = ExtentHeader::new(0, 4, 0, 0);
-        let header_ptr = &header as *const ExtentHeader as *const u8;
-        let array_ptr = &mut self.block as *mut u8;
-        unsafe {
-            core::ptr::copy_nonoverlapping(header_ptr, array_ptr, size_of::<ExtentHeader>());
-        }
+        self.extent_node_mut().init(0, 0);
     }
 }