瀏覽代碼

feat: extent insert and split

liujingx 11 月之前
父節點
當前提交
6b6fda20ff
共有 4 個文件被更改,包括 379 次插入150 次删除
  1. 161 63
      src/ext4/extent.rs
  2. 2 2
      src/ext4/mod.rs
  3. 214 83
      src/ext4_defs/extent.rs
  4. 2 2
      src/ext4_defs/inode.rs

+ 161 - 63
src/ext4/extent.rs

@@ -4,22 +4,39 @@ use crate::ext4_defs::*;
 use crate::prelude::*;
 use core::cmp::min;
 
+#[derive(Debug)]
+struct ExtentSearchStep {
+    /// The physical block where this extent node is stored.
+    /// For a root node, this field is 0.
+    pblock: PBlockId,
+    /// Index of the found `ExtentIndex` or `Extent` if found, the position where the
+    /// `ExtentIndex` or `Extent` should be inserted if not found.
+    index: core::result::Result<usize, usize>,
+}
+
+impl ExtentSearchStep {
+    /// Create a new extent search step
+    fn new(pblock: PBlockId, index: core::result::Result<usize, usize>) -> Self {
+        Self { pblock, index }
+    }
+}
+
 impl Ext4 {
     /// Find the given logic block id in the extent tree, return the search path
-    fn find_extent(&self, inode_ref: &InodeRef, iblock: LBlockId) -> Vec<ExtentSearchPath> {
-        let mut path: Vec<ExtentSearchPath> = Vec::new();
-        let mut ex_node = inode_ref.inode.extent();
+    fn find_extent(&self, inode_ref: &InodeRef, iblock: LBlockId) -> Vec<ExtentSearchStep> {
+        let mut path: Vec<ExtentSearchStep> = Vec::new();
+        let mut ex_node = inode_ref.inode.extent_node();
         let mut pblock = 0;
         let mut block_data: Block;
 
         // Go until leaf
         while ex_node.header().depth() > 0 {
-            let index = ex_node.extent_index_search(iblock);
+            let index = ex_node.search_extent_index(iblock);
             if index.is_err() {
                 // TODO: no extent index
                 panic!("Unhandled error");
             }
-            path.push(ExtentSearchPath::new_inner(pblock, index));
+            path.push(ExtentSearchStep::new(pblock, index));
             // Get the target extent index
             let ex_idx = ex_node.extent_index_at(index.unwrap());
             // Load the next extent node
@@ -30,11 +47,10 @@ impl Ext4 {
             ex_node = ExtentNode::from_bytes(&block_data.data);
             pblock = next;
         }
-
         // Leaf
-        let index = ex_node.extent_search(iblock);
+        let index = ex_node.search_extent(iblock);
         debug!("Extent search {} res {:?}", iblock, index);
-        path.push(ExtentSearchPath::new_leaf(pblock, index));
+        path.push(ExtentSearchStep::new(pblock, index));
 
         path
     }
@@ -59,7 +75,7 @@ impl Ext4 {
                 ExtentNode::from_bytes(&block_data.data)
             } else {
                 // Root node
-                inode_ref.inode.extent()
+                inode_ref.inode.extent_node()
             };
             let ex = ex_node.extent_at(index);
             Ok(ex.start_pblock() + (iblock - ex.start_lblock()) as PBlockId)
@@ -82,13 +98,11 @@ impl Ext4 {
         // Note: block data must be defined here to keep it alive
         let mut block_data: Block;
         let ex_node = if leaf.pblock != 0 {
-            // Load the extent node
             block_data = self.block_device.read_block(leaf.pblock);
-            // Load the next extent header
             ExtentNodeMut::from_bytes(&mut block_data.data)
         } else {
             // Root node
-            inode_ref.inode.extent_mut()
+            inode_ref.inode.extent_node_mut()
         };
         match leaf.index {
             Ok(index) => {
@@ -102,70 +116,154 @@ impl Ext4 {
                 // Allocate physical block
                 let fblock = self.alloc_block(inode_ref, 0)?;
                 // Create a new extent
-                let new_ext = Ext4Extent::new(iblock, fblock, block_count as u16);
+                let new_ext = Extent::new(iblock, fblock, block_count as u16);
                 // Insert the new extent
-                self.insert_extent(inode_ref, leaf, &new_ext);
+                self.insert_extent(inode_ref, &path, &new_ext)?;
                 Ok(fblock)
             }
         }
     }
 
-    /// Insert a new extent into a leaf node of the extent tree. Return whether
-    /// the node needs to be split.
-    pub(super) fn insert_extent(
-        &self,
+    /// Insert a new extent into the extent tree.
+    fn insert_extent(
+        &mut self,
         inode_ref: &mut InodeRef,
-        leaf: &ExtentSearchPath,
-        new_ext: &Ext4Extent,
-    ) -> bool {
-        // Note: block data must be defined here to keep it alive
-        let mut block_data = Block::default();
-        let mut ex_node = if leaf.pblock != 0 {
-            // Load the extent node
-            block_data = self.block_device.read_block(leaf.pblock);
-            // Load the next extent header
-            ExtentNodeMut::from_bytes(&mut block_data.data)
-        } else {
-            // Root node
-            inode_ref.inode.extent_mut()
-        };
-        // The position where the new extent should be inserted
-        let index = leaf.index.unwrap_err();
-        let targ_ext = ex_node.extent_mut_at(index);
-        let split: bool;
-
-        debug!("Create extent");
-        if targ_ext.is_uninit() {
-            // 1. The position has an uninitialized extent
-            *targ_ext = new_ext.clone();
-
-            let en_count = ex_node.header().entries_count() + 1;
-            ex_node.header_mut().set_entries_count(en_count);
-            split = false;
-        } else {
-            // 2. The position has a valid extent
-            // Insert the extent and move the following extents
-            let mut i = index;
-            while i < ex_node.header().entries_count() as usize {
-                *ex_node.extent_mut_at(i + 1) = *ex_node.extent_at(i);
-                i += 1;
+        path: &Vec<ExtentSearchStep>,
+        new_ext: &Extent,
+    ) -> Result<()> {
+        let leaf = path.last().unwrap();
+        // 1. Check If leaf is root
+        if leaf.pblock == 0 {
+            let mut leaf_node = inode_ref.inode.extent_node_mut();
+            // Insert the extent
+            let res = leaf_node.insert_extent(new_ext, leaf.index.unwrap_err());
+            self.write_inode_without_csum(inode_ref);
+            // Handle split
+            return if let Err(split) = res {
+                self.split_root(inode_ref, &split)
+            } else {
+                Ok(())
+            };
+        }
+        // 2. Leaf is not root, load the leaf node
+        let mut leaf_block = self.block_device.read_block(leaf.pblock);
+        let mut leaf_node = ExtentNodeMut::from_bytes(&mut leaf_block.data);
+        // Insert the extent
+        let res = leaf_node.insert_extent(new_ext, leaf.index.unwrap_err());
+        leaf_block.sync_to_disk(self.block_device.clone());
+        // Handle split
+        if let Err(mut split) = res {
+            // Handle split until root
+            for parent in path.iter().rev().skip(1) {
+                // The split node is at `parent.index.unwrap()`
+                // Call `self.split` to store the split part and update `parent`
+                let res = self.split(inode_ref, parent.pblock, parent.index.unwrap(), &split);
+                // Handle split again
+                if let Err(split_again) = res {
+                    // Insertion to parent also causes split, continue to solve
+                    split = split_again;
+                } else {
+                    return Ok(());
+                }
             }
-            *ex_node.extent_mut_at(index) = new_ext.clone();
+            // Root node needs to be split
+            self.split_root(inode_ref, &split)
+        } else {
+            Ok(())
+        }
+    }
 
-            let en_count = ex_node.header().entries_count() + 1;
-            ex_node.header_mut().set_entries_count(en_count);
-            // Check if the extent node is full
-            split = ex_node.header().entries_count() >= ex_node.header().max_entries_count();
+    /// Split an extent node. Given the block id where the parent node is
+    /// stored, and the child position where `parent_node.extent_at(child_pos)`
+    /// points to the child.
+    ///
+    /// The child node has already been split by calling `insert_extent` or
+    /// `insert_extent_index`, and the split part is stored in `split`.
+    /// This function will create a new leaf node to store the split part.
+    fn split(
+        &mut self,
+        inode_ref: &mut InodeRef,
+        parent_pblock: PBlockId,
+        child_pos: usize,
+        split: &[FakeExtent],
+    ) -> core::result::Result<(), Vec<FakeExtent>> {
+        let right_bid = self.alloc_block(inode_ref, 0).unwrap();
+        let mut right_block = self.block_device.read_block(right_bid);
+        let mut right_node = ExtentNodeMut::from_bytes(&mut right_block.data);
+
+        // Insert the split half to right node
+        right_node.init(0, 0);
+        for (i, extent) in split.iter().enumerate() {
+            *right_node.fake_extent_mut_at(i) = *extent;
         }
+        right_node
+            .header_mut()
+            .set_entries_count(split.len() as u16);
+        // Create an extent index
+        let extent_index =
+            ExtentIndex::new(right_node.extent_index_at(0).start_lblock(), right_bid);
+        right_block.sync_to_disk(self.block_device.clone());
 
-        ex_node.print();
-        // Write back to disk
-        if block_data.block_id != 0 {
-            block_data.sync_to_disk(self.block_device.clone());
-        } else {
+        let res;
+        if parent_pblock == 0 {
+            // Parent is root
+            let mut parent_node = inode_ref.inode.extent_node_mut();
+            res = parent_node.insert_extent_index(&extent_index, child_pos);
             self.write_inode_without_csum(inode_ref);
+        } else {
+            // Parent is not root
+            let mut parent_block = self.block_device.read_block(parent_pblock);
+            let mut parent_node = ExtentNodeMut::from_bytes(&mut parent_block.data);
+            res = parent_node.insert_extent_index(&extent_index, child_pos);
+            parent_block.sync_to_disk(self.block_device.clone());
         }
+        res
+    }
+
+    /// Split the root extent node. This function will create 2 new leaf
+    /// nodes and increase the height of the tree by 1.
+    ///
+    /// The root node has already been split by calling `insert_extent` or
+    /// `insert_extent_index`, and the split part is stored in `split`.
+    /// 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 mut l_block = self.block_device.read_block(l_bid);
+        let mut r_block = self.block_device.read_block(r_bid);
+
+        // Load root, left, right
+        let mut root = inode_ref.inode.extent_node_mut();
+        let mut left = ExtentNodeMut::from_bytes(&mut l_block.data);
+        let mut right = ExtentNodeMut::from_bytes(&mut r_block.data);
+
+        // Copy the left half to left_node
+        left.init(0, 0);
+        for i in 0..root.header().entries_count() as usize {
+            *left.fake_extent_mut_at(i) = *root.fake_extent_at(i);
+        }
+        left.header_mut()
+            .set_entries_count(root.header().entries_count());
+        // Copy the right half to right_node
+        right.init(0, 0);
+        for (i, fake_extent) in split.iter().enumerate() {
+            *right.fake_extent_mut_at(i) = *fake_extent;
+        }
+        right.header_mut().set_entries_count(split.len() as u16);
+
+        // Update the root node
+        let depth = root.header().depth() + 1;
+        root.header_mut().set_depth(depth);
+        root.header_mut().set_entries_count(2);
+        *root.extent_index_mut_at(0) = ExtentIndex::new(root.extent_at(0).start_lblock(), l_bid);
+        *root.extent_index_mut_at(1) = ExtentIndex::new(root.extent_at(1).start_lblock(), r_bid);
+
+        // Sync to disk
+        l_block.sync_to_disk(self.block_device.clone());
+        r_block.sync_to_disk(self.block_device.clone());
+        self.write_inode_without_csum(inode_ref);
 
-        split
+        Ok(())
     }
 }

+ 2 - 2
src/ext4/mod.rs

@@ -56,7 +56,7 @@ impl Ext4 {
     }
 
     /// Write an inode to block device without checksum
-    fn write_inode_without_csum(&self, inode_ref: &mut InodeRef) {
+    fn write_inode_without_csum(&self, inode_ref: &InodeRef) {
         inode_ref.sync_to_disk_without_csum(self.block_device.clone(), &self.super_block)
     }
 
@@ -73,7 +73,7 @@ impl Ext4 {
 
     /// Write a block group descriptor to block device without checksum
     #[allow(unused)]
-    fn write_block_group_without_csum(&self, bg_ref: &mut BlockGroupRef) {
+    fn write_block_group_without_csum(&self, bg_ref: &BlockGroupRef) {
         bg_ref.sync_to_disk_without_csum(self.block_device.clone(), &self.super_block)
     }
 }

+ 214 - 83
src/ext4_defs/extent.rs

@@ -125,6 +125,22 @@ pub struct ExtentIndex {
 }
 
 impl ExtentIndex {
+    /// Create a new extent index with the start logic block number and
+    /// the physical block number of the child node
+    pub fn new(first_block: LBlockId, leaf: PBlockId) -> Self {
+        Self {
+            first_block,
+            leaf_lo: leaf as u32,
+            leaf_hi: (leaf >> 32) as u16,
+            padding: 0,
+        }
+    }
+
+    /// The start logic block number that this extent index covers
+    pub fn start_lblock(&self) -> LBlockId {
+        self.first_block
+    }
+
     /// The physical block number of the extent node that is the next level lower in the tree
     pub fn leaf(&self) -> PBlockId {
         (self.leaf_hi as PBlockId) << 32 | self.leaf_lo as PBlockId
@@ -133,7 +149,7 @@ impl ExtentIndex {
 
 #[derive(Debug, Default, Clone, Copy)]
 #[repr(C)]
-pub struct Ext4Extent {
+pub struct Extent {
     /// First file block number that this extent covers.
     first_block: u32,
 
@@ -152,7 +168,7 @@ pub struct Ext4Extent {
     start_lo: u32,
 }
 
-impl Ext4Extent {
+impl Extent {
     /// Create a new extent with start logic block number, start physical block number, and block count
     pub fn new(start_lblock: LBlockId, start_pblock: PBlockId, block_count: u16) -> Self {
         Self {
@@ -198,22 +214,22 @@ impl Ext4Extent {
         self.block_count = block_count as u16;
     }
 
-    /// Check if the extent is uninitialized
-    pub fn is_uninit(&self) -> bool {
+    /// Check if the extent is unwritten
+    pub fn is_unwritten(&self) -> bool {
         self.block_count > EXT_INIT_MAX_LEN
     }
 
-    /// Mark the extent as uninitialized
-    pub fn mark_uninit(&mut self) {
+    /// Mark the extent as unwritten
+    pub fn mark_unwritten(&mut self) {
         (*self).block_count |= EXT_INIT_MAX_LEN;
     }
 
     /// Check whether the `ex2` extent can be appended to the `ex1` extent
-    pub fn can_append(ex1: &Ext4Extent, ex2: &Ext4Extent) -> bool {
+    pub fn can_append(ex1: &Extent, ex2: &Extent) -> bool {
         if ex1.start_pblock() + ex1.block_count() as u64 != ex2.start_pblock() {
             return false;
         }
-        if ex1.is_uninit()
+        if ex1.is_unwritten()
             && ex1.block_count() + ex2.block_count() > EXT_UNWRITTEN_MAX_LEN as LBlockId
         {
             return false;
@@ -228,6 +244,30 @@ impl Ext4Extent {
     }
 }
 
+/// When only `first_block` field in `Extent` and `ExtentIndex` are used, they can
+/// both be interpreted as the common type `FakeExtent`. This provides convenience
+/// to some tree operations.
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct FakeExtent {
+    /// The `first_block` field in `Extent` and `ExtentIndex`
+    first_block: u32,
+    /// Ignored field, should not be accessed
+    protected: [u8; 8],
+}
+
+impl From<Extent> for FakeExtent {
+    fn from(extent: Extent) -> Self {
+        unsafe { mem::transmute(extent) }
+    }
+}
+
+impl From<ExtentIndex> for FakeExtent {
+    fn from(extent_index: ExtentIndex) -> Self {
+        unsafe { mem::transmute(extent_index) }
+    }
+}
+
 /// Interpret an immutable byte slice as an extent node. Provide methods to
 /// access the extent header and the following extents or extent indices.
 ///
@@ -248,19 +288,14 @@ impl<'a> ExtentNode<'a> {
         unsafe { &*(self.raw_data.as_ptr() as *const ExtentHeader) }
     }
 
-    /// Get a immutable reference to the extent at a given index
-    pub fn extent_at(&self, index: usize) -> &Ext4Extent {
-        unsafe {
-            &*((self.header() as *const ExtentHeader).add(1) as *const Ext4Extent).add(index)
-        }
+    /// Get a immutable reference to the extent at a given position
+    pub fn extent_at(&self, pos: usize) -> &Extent {
+        unsafe { &*((self.header() as *const ExtentHeader).add(1) as *const Extent).add(pos) }
     }
 
-    /// Get a immmutable reference to the extent indexat a given index
-    pub fn extent_index_at(&self, index: usize) -> &ExtentIndex {
-        unsafe {
-            &*((self.header() as *const ExtentHeader).add(1) as *const ExtentIndex)
-                .add(index)
-        }
+    /// Get a immmutable reference to the extent indexat a given position
+    pub fn extent_index_at(&self, pos: usize) -> &ExtentIndex {
+        unsafe { &*((self.header() as *const ExtentHeader).add(1) as *const ExtentIndex).add(pos) }
     }
 
     /// Find the extent that covers the given logical block number.
@@ -268,13 +303,13 @@ impl<'a> ExtentNode<'a> {
     /// Return `Ok(index)` if found, and `eh.extent_at(index)` is the extent that covers
     /// the given logical block number. Return `Err(index)` if not found, and `index` is the
     /// position where the new extent should be inserted.
-    pub fn extent_search(&self, lblock: LBlockId) -> core::result::Result<usize, usize> {
+    pub fn search_extent(&self, lblock: LBlockId) -> core::result::Result<usize, usize> {
         let mut i = 0;
         while i < self.header().entries_count as usize {
             let extent = self.extent_at(i);
             if extent.start_lblock() <= lblock {
                 if extent.start_lblock() + (extent.block_count() as LBlockId) > lblock {
-                    return if extent.is_uninit() { Err(i) } else { Ok(i) };
+                    return if extent.is_unwritten() { Err(i) } else { Ok(i) };
                 }
                 i += 1;
             } else {
@@ -290,7 +325,7 @@ impl<'a> ExtentNode<'a> {
     /// Return `Ok(index)` if found, and `eh.extent_index_at(index)` is the target extent index.
     /// Return `Err(index)` if not found, and `index` is the position where the new extent index
     /// should be inserted.
-    pub fn extent_index_search(&self, lblock: LBlockId) -> core::result::Result<usize, usize> {
+    pub fn search_extent_index(&self, lblock: LBlockId) -> core::result::Result<usize, usize> {
         let mut i = 0;
         self.print();
         while i < self.header().entries_count as usize {
@@ -336,6 +371,13 @@ impl<'a> ExtentNodeMut<'a> {
         Self { raw_data }
     }
 
+    /// Interpret self as immutable extent node
+    pub fn as_immut(&self) -> ExtentNode<'_> {
+        ExtentNode {
+            raw_data: self.raw_data,
+        }
+    }
+
     /// Get a immutable reference to the extent header
     pub fn header(&self) -> &ExtentHeader {
         unsafe { &*(self.raw_data.as_ptr() as *const ExtentHeader) }
@@ -346,84 +388,173 @@ impl<'a> ExtentNodeMut<'a> {
         unsafe { &mut *(self.raw_data.as_mut_ptr() as *mut ExtentHeader) }
     }
 
-    /// Get a immutable reference to the extent at a given index
-    pub fn extent_at(&self, index: usize) -> &'static Ext4Extent {
-        unsafe {
-            &*((self.header() as *const ExtentHeader).add(1) as *const Ext4Extent).add(index)
-        }
+    /// Get a immutable reference to the extent at a given position
+    pub fn extent_at(&self, pos: usize) -> &Extent {
+        unsafe { &*((self.header() as *const ExtentHeader).add(1) as *const Extent).add(pos) }
     }
 
-    /// Get a mutable reference to the extent at a given index
-    pub fn extent_mut_at(&mut self, index: usize) -> &'static mut Ext4Extent {
-        unsafe {
-            &mut *((self.header_mut() as *mut ExtentHeader).add(1) as *mut Ext4Extent)
-                .add(index)
-        }
+    /// Get a mutable reference to the extent at a given position
+    pub fn extent_mut_at(&mut self, pos: usize) -> &mut Extent {
+        unsafe { &mut *((self.header_mut() as *mut ExtentHeader).add(1) as *mut Extent).add(pos) }
     }
 
-    /// Get a immutable reference to the extent index at a given index
-    pub fn extent_index_at(&self, index: usize) -> &'static ExtentIndex {
-        unsafe {
-            &*((self.header() as *const ExtentHeader).add(1) as *const ExtentIndex)
-                .add(index)
-        }
+    /// Get an immutable reference to the extent pos at a given position
+    pub fn extent_index_at(&self, pos: usize) -> &ExtentIndex {
+        unsafe { &*((self.header() as *const ExtentHeader).add(1) as *const ExtentIndex).add(pos) }
     }
 
-    /// Get a mutable reference to the extent index at a given index
-    pub fn extent_index_mut_at(&mut self, index: usize) -> &'static mut ExtentIndex {
+    /// Get a mutable reference to the extent pos at a given position
+    pub fn extent_index_mut_at(&mut self, pos: usize) -> &mut ExtentIndex {
         unsafe {
-            &mut *((self.header_mut() as *mut ExtentHeader).add(1) as *mut ExtentIndex)
-                .add(index)
+            &mut *((self.header_mut() as *mut ExtentHeader).add(1) as *mut ExtentIndex).add(pos)
         }
     }
 
-    pub fn print(&self) {
-        debug!("Extent header {:?}", self.header());
-        let mut i = 0;
-        while i < self.header().entries_count() as usize {
-            let ext = self.extent_at(i);
-            debug!(
-                "extent[{}] start_lblock={}, start_pblock={}, len={}",
-                i,
-                ext.start_lblock(),
-                ext.start_pblock(),
-                ext.block_count()
-            );
-            i += 1;
+    /// Get an immutable reference to the extent or extent index at a given position,
+    /// ignore the detailed type information
+    pub fn fake_extent_at(&self, pos: usize) -> &FakeExtent {
+        unsafe { &*((self.header() as *const ExtentHeader).add(1) as *const FakeExtent).add(pos) }
+    }
+
+    /// Get a mutable reference to the extent or extent index at a given position,
+    /// ignore the detailed type information
+    pub fn fake_extent_mut_at(&mut self, pos: usize) -> &mut FakeExtent {
+        unsafe {
+            &mut *((self.header_mut() as *mut ExtentHeader).add(1) as *mut FakeExtent).add(pos)
         }
     }
-}
 
-#[derive(Debug)]
-pub struct ExtentSearchPath {
-    /// Marks whether the extent search path is for an inner node or a leaf node.
-    pub leaf: bool,
-    /// The physical block where this extent node is stored if it is not a root node.
-    /// For a root node, this field is 0.
-    pub pblock: PBlockId,
-    /// Index of the found `ExtentIndex` or `Extent` if found, the position where the
-    /// `ExtentIndex` or `Extent` should be inserted if not found.
-    pub index: core::result::Result<usize, usize>,
-}
+    /// Initialize the extent node
+    pub fn init(&mut self, depth: u16, generation: u32) {
+        let max_entries_count =
+            (self.raw_data.len() - size_of::<ExtentHeader>()) / size_of::<Extent>();
+        *self.header_mut() = ExtentHeader::new(0, max_entries_count as u16, depth, generation);
+    }
 
-impl ExtentSearchPath {
-    /// Create a new extent search path, which records an inner node
-    /// of the extent tree i.e. an `ExtentIndex`.
-    pub fn new_inner(pblock: PBlockId, index: core::result::Result<usize, usize>) -> Self {
-        Self {
-            pblock,
-            leaf: false,
-            index,
+    /// Insert a new extent into current node.
+    ///
+    /// Return `Ok(())` if the insertion is successful. Return `Err(extents)` if
+    /// the insertion failed and `extents` is a vector of split extents, which
+    /// should be inserted into a new node.
+    ///
+    /// This function requires this extent node to be a leaf node.
+    pub fn insert_extent(
+        &mut self,
+        extent: &Extent,
+        pos: usize,
+    ) -> core::result::Result<(), Vec<FakeExtent>> {
+        if self.extent_at(pos).is_unwritten() {
+            // The position has an uninitialized extent
+            *self.extent_mut_at(pos) = *extent;
+            self.header_mut().entries_count += 1;
+            return Ok(());
         }
+        // The position has a valid extent
+        if self.header().entries_count() < self.header().max_entries_count() {
+            // The extent node is not full
+            // Insert the extent and move the following extents
+            let mut i = pos;
+            while i < self.header().entries_count() as usize {
+                *self.extent_mut_at(i + 1) = *self.extent_at(i);
+                i += 1;
+            }
+            *self.extent_mut_at(pos) = *extent;
+            self.header_mut().entries_count += 1;
+            return Ok(());
+        }
+        // The extent node is full
+        // There may be some unwritten extents, we could find the first
+        // unwritten extent and adjust the extents.
+        let mut unwritten = None;
+        for i in 0..self.header().entries_count() as usize {
+            if self.extent_at(i).is_unwritten() {
+                unwritten = Some(i);
+                break;
+            }
+        }
+        if let Some(unwritten) = unwritten {
+            // There is an uninitialized extent, we could adjust the extents.
+            if unwritten < pos {
+                // Move the extents from `unwritten` to `pos`
+                let mut i = unwritten;
+                while i < pos {
+                    *self.extent_mut_at(i) = *self.extent_at(i + 1);
+                    i += 1;
+                }
+            } else {
+                // Move the extents from `pos` to `unwritten`
+                let mut i = pos;
+                while i < unwritten {
+                    *self.extent_mut_at(i + 1) = *self.extent_at(i);
+                    i += 1;
+                }
+            }
+            *self.extent_mut_at(pos) = *extent;
+            self.header_mut().entries_count += 1;
+            return Ok(());
+        }
+        // The extent node is full and all extents are valid
+        // Split the node, return the extents in the right half
+        let mut split = Vec::new();
+        let mid = self.header().entries_count() as usize / 2;
+        for i in mid..self.header().entries_count() as usize {
+            if i == pos {
+                // The extent to insert
+                split.push((*extent).into());
+            }
+            split.push(*self.fake_extent_at(i));
+        }
+        self.header_mut().entries_count = mid as u16;
+        if pos < mid {
+            // If `pos` is on the left side, insert it
+            self.insert_extent(extent, pos).expect("Must Succeed");
+        }
+        // Return the right half
+        Err(split)
     }
 
-    /// Create a new extent search path, which records a leaf node
-    /// of the extent tree i.e. an `Extent`.
-    pub fn new_leaf(pblock: PBlockId, index: core::result::Result<usize, usize>) -> Self {
-        Self {
-            pblock,
-            leaf: true,
-            index,
+    /// Insert a new extent index into current node.
+    ///
+    /// Return `Ok(())` if the insertion is successful. Return `Err(extent_indexs)` if
+    /// the insertion failed and `extent_indexs` is a vector of split extent indexs,
+    /// which should be inserted into a new node.
+    ///
+    /// This function requires this extent node to be a inner node.
+    pub fn insert_extent_index(
+        &mut self,
+        extent_index: &ExtentIndex,
+        pos: usize,
+    ) -> core::result::Result<(), Vec<FakeExtent>> {
+        if self.header().entries_count() < self.header().max_entries_count() {
+            // The extent node is not full
+            // Insert the extent index and move the following extent indexs
+            let mut i = pos;
+            while i < self.header().entries_count() as usize {
+                *self.extent_index_mut_at(i + 1) = *self.extent_index_at(i);
+                i += 1;
+            }
+            *self.extent_index_mut_at(pos) = *extent_index;
+            self.header_mut().entries_count += 1;
+            return Ok(());
+        }
+        // The extent node is full
+        // Split the node, return the extent indexs in the right half
+        let mut split = Vec::<FakeExtent>::new();
+        let mid = self.header().entries_count() as usize / 2;
+        for i in mid..self.header().entries_count() as usize {
+            if i == pos {
+                // The extent index to insert
+                split.push((*extent_index).into());
+            }
+            split.push(*self.fake_extent_at(i));
+        }
+        self.header_mut().entries_count = mid as u16;
+        if pos < mid {
+            // If `pos` is on the left side, insert it
+            self.insert_extent_index(extent_index, pos)
+                .expect("Must Succeed");
         }
+        // Return the right half
+        Err(split)
     }
 }

+ 2 - 2
src/ext4_defs/inode.rs

@@ -180,14 +180,14 @@ impl Inode {
     /* Extent methods */
 
     /// Get the immutable extent root node
-    pub fn extent(&self) -> ExtentNode {
+    pub fn extent_node(&self) -> ExtentNode {
         ExtentNode::from_bytes(unsafe {
             core::slice::from_raw_parts(self.block.as_ptr() as *const u8, 60)
         })
     }
 
     /// Get the mutable extent root node
-    pub fn extent_mut(&mut self) -> ExtentNodeMut {
+    pub fn extent_node_mut(&mut self) -> ExtentNodeMut {
         ExtentNodeMut::from_bytes(unsafe {
             core::slice::from_raw_parts_mut(self.block.as_mut_ptr() as *mut u8, 60)
         })