Browse Source

feat: use Result error handler

liujingx 1 year ago
parent
commit
99c6b769d1
8 changed files with 126 additions and 120 deletions
  1. 3 3
      ext4_test/src/main.rs
  2. 24 25
      src/ext4/alloc.rs
  3. 44 53
      src/ext4/dir.rs
  4. 13 9
      src/ext4/extent.rs
  5. 12 13
      src/ext4/file.rs
  6. 5 6
      src/ext4/link.rs
  7. 3 3
      src/ext4/mod.rs
  8. 22 8
      src/ext4_defs/dir_entry.rs

+ 3 - 3
ext4_test/src/main.rs

@@ -21,7 +21,7 @@ impl BlockFile {
 
 impl BlockDevice for BlockFile {
     fn read_offset(&self, offset: usize) -> Vec<u8> {
-        info!("Reading block at offset {}", offset);
+        // info!("Reading block at offset {}", offset);
         let mut file = &self.0;
         let mut buffer = vec![0u8; BLOCK_SIZE];
         let _r = file.seek(SeekFrom::Start(offset as u64));
@@ -30,7 +30,7 @@ impl BlockDevice for BlockFile {
     }
 
     fn write_offset(&self, offset: usize, data: &[u8]) {
-        info!("Writing block at offset {}", offset);
+        // info!("Writing block at offset {}", offset);
         let mut file = &self.0;
         let _r = file.seek(SeekFrom::Start(offset as u64));
         let _r = file.write_all(data);
@@ -76,7 +76,7 @@ fn open_test(ext4: &mut Ext4) {
         .expect("open failed");
     ext4.ext4_open("1/2/3/4/5", "r", true).expect("open failed");
     ext4.ext4_open("1/2/3/4/5", "a", true).expect("open failed");
-    ext4.ext4_open("4", "w+", true).expect("open failed");
+    ext4.ext4_open("2/4", "w+", true).expect("open failed");
 }
 
 fn main() {

+ 24 - 25
src/ext4/alloc.rs

@@ -5,7 +5,11 @@ use crate::prelude::*;
 
 impl Ext4 {
     /// Allocate a new data block for an inode, return the physical block number
-    pub(super) fn alloc_block(&mut self, inode_ref: &mut Ext4InodeRef, goal: PBlockId) -> PBlockId {
+    pub(super) fn alloc_block(
+        &mut self,
+        inode_ref: &mut Ext4InodeRef,
+        goal: PBlockId,
+    ) -> Result<PBlockId> {
         let bgid = goal / self.super_block.blocks_per_group() as u64;
         let idx_in_bg = goal % self.super_block.blocks_per_group() as u64;
 
@@ -18,10 +22,9 @@ impl Ext4 {
         let raw_bitmap = &mut self.block_device.read_offset(block_bmap_offset);
         let mut bitmap = Bitmap::new(raw_bitmap);
         // Find and first free block
-        let fblock = bitmap.find_and_set_first_clear_bit(idx_in_bg as usize, 8 * BLOCK_SIZE);
-        if fblock.is_none() {
-            return 0;
-        }
+        let fblock = bitmap
+            .find_and_set_first_clear_bit(idx_in_bg as usize, 8 * BLOCK_SIZE)
+            .ok_or(Ext4Error::new(ErrCode::ENOSPC))? as PBlockId;
 
         // Set block group checksum
         bg.set_block_bitmap_csum(&self.super_block, &bitmap);
@@ -44,29 +47,28 @@ impl Ext4 {
 
         bg.sync_to_disk_with_csum(self.block_device.clone(), bgid as usize, &self.super_block);
 
-        info!("Alloc block {}", fblock.unwrap());
-
-        fblock.unwrap() as PBlockId
+        info!("Alloc block {}", fblock);
+        Ok(fblock)
     }
 
     /// Append a data block for an inode, return a pair of (logical block id, physical block id)
     pub(super) fn inode_append_block(
         &mut self,
         inode_ref: &mut Ext4InodeRef,
-    ) -> (LBlockId, PBlockId) {
+    ) -> Result<(LBlockId, PBlockId)> {
         let inode_size = inode_ref.inode.size();
         // The new logical block id
         let iblock = ((inode_size + BLOCK_SIZE as u64 - 1) / BLOCK_SIZE as u64) as u32;
         // Check the extent tree to get the physical block id
-        let fblock = self.extent_get_pblock_create(inode_ref, iblock, 1);
+        let fblock = self.extent_get_pblock_create(inode_ref, iblock, 1)?;
         // Update the inode
         inode_ref.inode.set_size(inode_size + BLOCK_SIZE as u64);
         self.write_back_inode_with_csum(inode_ref);
-        (iblock, fblock)
+        Ok((iblock, fblock))
     }
 
     /// Allocate(initialize) the root inode of the file system
-    pub(super) fn alloc_root_inode(&mut self) -> Ext4InodeRef {
+    pub(super) fn alloc_root_inode(&mut self) -> Result<Ext4InodeRef> {
         let mut inode = Ext4Inode::default();
         inode.set_mode(0o777 | EXT4_INODE_MODE_DIRECTORY);
         inode.extent_init();
@@ -75,22 +77,21 @@ impl Ext4 {
         }
         let mut root = Ext4InodeRef::new(EXT4_ROOT_INO, inode);
         let root_self = root.clone();
-        
+
         // Add `.` and `..` entries
-        self.dir_add_entry(&mut root, &root_self, ".");
-        self.dir_add_entry(&mut root, &root_self, "..");
+        self.dir_add_entry(&mut root, &root_self, ".")?;
+        self.dir_add_entry(&mut root, &root_self, "..")?;
         root.inode.links_count += 2;
 
         self.write_back_inode_with_csum(&mut root);
-
-        root
+        Ok(root)
     }
 
     /// Allocate a new inode in the file system, returning the inode and its number
-    pub(super) fn alloc_inode(&mut self, filetype: FileType) -> Ext4InodeRef {
+    pub(super) fn alloc_inode(&mut self, filetype: FileType) -> Result<Ext4InodeRef> {
         // Allocate an inode
         let is_dir = filetype == FileType::Directory;
-        let id = self.do_alloc_inode(is_dir);
+        let id = self.do_alloc_inode(is_dir)?;
 
         // Initialize the inode
         let mut inode = Ext4Inode::default();
@@ -112,12 +113,11 @@ impl Ext4 {
         self.write_back_inode_with_csum(&mut inode_ref);
 
         info!("Alloc inode {}", inode_ref.inode_id);
-
-        inode_ref
+        Ok(inode_ref)
     }
 
     /// Allocate a new inode in the filesystem, returning its number.
-    fn do_alloc_inode(&mut self, is_dir: bool) -> u32 {
+    fn do_alloc_inode(&mut self, is_dir: bool) -> Result<u32> {
         let mut bgid = 0;
         let bg_count = self.super_block.block_groups_count();
 
@@ -182,11 +182,10 @@ impl Ext4 {
             // Compute the absolute i-node number
             let inodes_per_group = self.super_block.inodes_per_group();
             let inode_num = bgid * inodes_per_group + (idx_in_bg + 1);
-            log::info!("alloc inode {}", inode_num);
 
-            return inode_num;
+            return Ok(inode_num);
         }
         log::info!("no free inode");
-        0
+        Err(Ext4Error::new(ErrCode::ENOSPC))
     }
 }

+ 44 - 53
src/ext4/dir.rs

@@ -13,7 +13,7 @@ impl Ext4 {
 
         while iblock < total_blocks {
             // Get the fs block id
-            let fblock = self.extent_get_pblock(parent, iblock);
+            let fblock = self.extent_get_pblock(parent, iblock)?;
             // Load block from disk
             let block_data = self.block_device.read_offset(fblock as usize * BLOCK_SIZE);
             // Find the entry in block
@@ -32,8 +32,7 @@ impl Ext4 {
     fn find_entry_in_block(block_data: &[u8], name: &str) -> Result<Ext4DirEntry> {
         let mut offset = 0;
         while offset < block_data.len() {
-            let de = Ext4DirEntry::try_from(&block_data[offset..]).unwrap();
-            debug!("de {:?}", de.rec_len());
+            let de = Ext4DirEntry::from_bytes(&block_data[offset..]);
             offset += de.rec_len() as usize;
             // Unused dir entry
             if de.unused() {
@@ -53,7 +52,7 @@ impl Ext4 {
         parent: &mut Ext4InodeRef,
         child: &Ext4InodeRef,
         path: &str,
-    ) -> usize {
+    ) -> Result<()> {
         info!(
             "Adding entry: parent {}, child {}, path {}",
             parent.inode_id, child.inode_id, path
@@ -65,7 +64,7 @@ impl Ext4 {
         let mut iblock: LBlockId = 0;
         while iblock < total_blocks {
             // Get the parent physical block id, create if not exist
-            let fblock = self.extent_get_pblock_create(parent, iblock, 1);
+            let fblock = self.extent_get_pblock_create(parent, iblock, 1)?;
             // Load the parent block from disk
             let mut data = self.block_device.read_offset(fblock as usize * BLOCK_SIZE);
             let mut ext4_block = Ext4Block {
@@ -76,17 +75,14 @@ impl Ext4 {
             };
             debug!("Insert dirent to old block {}", fblock);
             // Try inserting the entry to parent block
-            let r = self.insert_entry_to_old_block(&mut ext4_block, child, path);
-            if r == EOK {
-                return EOK;
-            }
+            self.insert_entry_to_old_block(&mut ext4_block, child, path)?;
             // Current block has no enough space
             iblock += 1;
         }
 
         // No free block found - needed to allocate a new data block
         // Append a new data block
-        let (iblock, fblock) = self.inode_append_block(parent);
+        let (iblock, fblock) = self.inode_append_block(parent)?;
         // Load new block
         let block_device = self.block_device.clone();
         let mut data = block_device.read_offset(fblock as usize * BLOCK_SIZE);
@@ -98,36 +94,41 @@ impl Ext4 {
         };
         debug!("Insert dirent to new block {}", fblock);
         // Write the entry to block
-        self.insert_entry_to_new_block(&mut new_block, child, path);
-
-        EOK
+        self.insert_entry_to_new_block(&mut new_block, child, path)
     }
 
     /// Insert a directory entry of a child inode into a new parent block.
     /// A new block must have enough space
-    fn insert_entry_to_new_block(&self, dst_blk: &mut Ext4Block, child: &Ext4InodeRef, name: &str) {
+    fn insert_entry_to_new_block(
+        &self,
+        dst_blk: &mut Ext4Block,
+        child: &Ext4InodeRef,
+        name: &str,
+    ) -> Result<()> {
         // Set the entry
-        let mut new_entry = Ext4DirEntry::default();
         let rec_len = BLOCK_SIZE - size_of::<Ext4DirEntryTail>();
-        Self::set_dir_entry(&mut new_entry, rec_len as u16, &child, name);
+        let new_entry = Ext4DirEntry::new(
+            child.inode_id,
+            rec_len as u16,
+            name,
+            inode_mode2file_type(child.inode.mode()),
+        );
 
-        // Write to block
+        // Write entry to block
         new_entry.copy_to_byte_slice(&mut dst_blk.block_data, 0);
 
         // Set tail
         let mut tail = Ext4DirEntryTail::default();
         tail.rec_len = size_of::<Ext4DirEntryTail>() as u16;
         tail.reserved_ft = 0xDE;
-        tail.reserved_zero1 = 0;
-        tail.reserved_zero2 = 0;
         tail.set_csum(&self.super_block, &new_entry, &dst_blk.block_data[..]);
-
-        // Copy to block
+        // Copy tail to block
         let tail_offset = BLOCK_SIZE - size_of::<Ext4DirEntryTail>();
         tail.copy_to_byte_slice(&mut dst_blk.block_data, tail_offset);
 
-        // Sync to disk
+        // Sync block to disk
         dst_blk.sync_to_disk(self.block_device.clone());
+        Ok(())
     }
 
     /// Try insert a directory entry of child inode into a parent block.
@@ -137,62 +138,52 @@ impl Ext4 {
         dst_blk: &mut Ext4Block,
         child: &Ext4InodeRef,
         name: &str,
-    ) -> usize {
+    ) -> Result<()> {
         let required_size = Ext4DirEntry::required_size(name.len());
         let mut offset = 0;
 
         while offset < dst_blk.block_data.len() {
-            let mut de = Ext4DirEntry::try_from(&dst_blk.block_data[offset..]).unwrap();
-            if de.unused() {
-                continue;
-            }
-            // Split valid dir entry
-            let rec_len = de.rec_len();
+            let mut de = Ext4DirEntry::from_bytes(&dst_blk.block_data[offset..]);
+            let rec_len = de.rec_len() as usize;
 
-            // The actual size that `de` uses
+            // Try splitting dir entry
+            // The size that `de` actually uses
             let used_size = de.used_size();
             // The rest size
-            let free_size = rec_len as usize - used_size;
+            let free_size = rec_len - used_size;
+
             // Compare size
             if free_size < required_size {
                 // No enough space, try next dir ent
-                offset = offset + rec_len as usize;
+                offset = offset + rec_len;
                 continue;
             }
             // Has enough space
-            // Set the entry
-            de.set_rec_len(free_size as u16);
-            let mut new_entry = Ext4DirEntry::default();
-            Self::set_dir_entry(&mut new_entry, free_size as u16, &child, name);
-
-            // Write dir entries to blk_data
+            // Update the old entry
+            de.set_rec_len(used_size as u16);
             de.copy_to_byte_slice(&mut dst_blk.block_data, offset);
+            // Insert the new entry
+            let new_entry = Ext4DirEntry::new(
+                child.inode_id,
+                free_size as u16,
+                name,
+                inode_mode2file_type(child.inode.mode()),
+            );
             new_entry.copy_to_byte_slice(&mut dst_blk.block_data, offset + used_size);
 
             // Set tail csum
-            let mut tail = Ext4DirEntryTail::from(&mut dst_blk.block_data, BLOCK_SIZE).unwrap();
+            let mut tail =
+                Ext4DirEntryTail::from_bytes(&mut dst_blk.block_data, BLOCK_SIZE).unwrap();
             tail.set_csum(&self.super_block, &de, &dst_blk.block_data[offset..]);
-            let parent_de = Ext4DirEntry::try_from(&dst_blk.block_data[..]).unwrap();
-            tail.set_csum(&self.super_block, &parent_de, &dst_blk.block_data[..]);
-
             // Write tail to blk_data
             let tail_offset = BLOCK_SIZE - size_of::<Ext4DirEntryTail>();
             tail.copy_to_byte_slice(&mut dst_blk.block_data, tail_offset);
 
             // Sync to disk
             dst_blk.sync_to_disk(self.block_device.clone());
-
-            return EOK;
+            return Ok(());
         }
-        ENOSPC
-    }
-
-    /// Set the directory entry for an inode
-    fn set_dir_entry(en: &mut Ext4DirEntry, rec_len: u16, child: &Ext4InodeRef, name: &str) {
-        en.set_inode(child.inode_id);
-        en.set_rec_len(rec_len);
-        en.set_entry_type(child.inode.mode());
-        en.set_name(name);
+        Err(Ext4Error::new(ErrCode::ENOSPC))
     }
 
     /// Create a new directory. `path` is the absolute path of the new directory.

+ 13 - 9
src/ext4/extent.rs

@@ -41,7 +41,11 @@ impl Ext4 {
 
     /// Given a logic block id, find the corresponding fs block id.
     /// Return 0 if not found.
-    pub(super) fn extent_get_pblock(&self, inode_ref: &Ext4InodeRef, iblock: LBlockId) -> PBlockId {
+    pub(super) fn extent_get_pblock(
+        &self,
+        inode_ref: &Ext4InodeRef,
+        iblock: LBlockId,
+    ) -> Result<PBlockId> {
         let path = self.find_extent(inode_ref, iblock);
         // Leaf is the last element of the path
         let leaf = path.last().unwrap();
@@ -60,9 +64,9 @@ impl Ext4 {
                 inode_ref.inode.extent()
             };
             let ex = ex_node.extent_at(index);
-            ex.start_pblock() + (iblock - ex.start_lblock()) as PBlockId
+            Ok(ex.start_pblock() + (iblock - ex.start_lblock()) as PBlockId)
         } else {
-            0
+            Err(Ext4Error::new(ErrCode::ENOENT))
         }
     }
 
@@ -73,7 +77,7 @@ impl Ext4 {
         inode_ref: &mut Ext4InodeRef,
         iblock: LBlockId,
         block_count: u32,
-    ) -> PBlockId {
+    ) -> Result<PBlockId> {
         let path = self.find_extent(inode_ref, iblock);
         // Leaf is the last element of the path
         let leaf = path.last().unwrap();
@@ -94,18 +98,18 @@ impl Ext4 {
             Ok(index) => {
                 // Found, return the corresponding fs block id
                 let ex = ex_node.extent_at(index);
-                ex.start_pblock() + (iblock - ex.start_lblock()) as PBlockId
+                Ok(ex.start_pblock() + (iblock - ex.start_lblock()) as PBlockId)
             }
             Err(_) => {
                 // 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, 0)?;
                 // Create a new extent
                 let new_ext = Ext4Extent::new(iblock, fblock, block_count as u16);
                 // Insert the new extent
                 self.insert_extent(inode_ref, leaf, &new_ext);
-                fblock
+                Ok(fblock)
             }
         }
     }
@@ -140,7 +144,7 @@ impl Ext4 {
         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;
@@ -153,7 +157,7 @@ impl Ext4 {
                 i += 1;
             }
             *ex_node.extent_mut_at(index) = new_ext.clone();
-            
+
             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

+ 12 - 13
src/ext4/file.rs

@@ -21,7 +21,7 @@ impl Ext4 {
         // Search from the given parent inode
         let mut parent = parent_inode.clone();
         let search_path = Self::split_path(path);
-        
+
         info!("generic open: {}", path);
         for (i, path) in search_path.iter().enumerate() {
             let res = self.dir_find_entry(&parent, path);
@@ -43,13 +43,10 @@ impl Ext4 {
                         self.alloc_inode(ftype)
                     } else {
                         self.alloc_inode(FileType::Directory)
-                    };
+                    }?;
                     // Link the new inode
-                    let r = self.ext4_link(&mut parent, &mut child, path);
-                    if r != EOK {
-                        // Fail. Free new inode
-                        return_errno_with_message!(ErrCode::ELINKFIAL, "link fail");
-                    }
+                    self.ext4_link(&mut parent, &mut child, path)
+                        .map_err(|_| Ext4Error::with_message(ErrCode::ELINKFIAL, "link fail"))?;
                     // Write back parent and child
                     self.write_back_inode_with_csum(&mut parent);
                     self.write_back_inode_with_csum(&mut child);
@@ -120,7 +117,7 @@ impl Ext4 {
         // Read first block
         if misaligned > 0 {
             let first_block_read_len = min(BLOCK_SIZE - misaligned, size_to_read);
-            let fblock = self.extent_get_pblock(&mut inode_ref, start_iblock);
+            let fblock = self.extent_get_pblock(&mut inode_ref, start_iblock)?;
             if fblock != 0 {
                 let block_offset = fblock as usize * BLOCK_SIZE + misaligned;
                 let block_data = self.block_device.read_offset(block_offset);
@@ -138,7 +135,7 @@ impl Ext4 {
         // Continue with full block reads
         while cursor < size_to_read {
             let read_length = min(BLOCK_SIZE, size_to_read - cursor);
-            let fblock = self.extent_get_pblock(&mut inode_ref, iblock);
+            let fblock = self.extent_get_pblock(&mut inode_ref, iblock)?;
             if fblock != 0 {
                 let block_data = self.block_device.read_offset(fblock as usize * BLOCK_SIZE);
                 // Copy data from block to the user buffer
@@ -155,7 +152,7 @@ impl Ext4 {
         Ok(cursor)
     }
 
-    pub fn ext4_file_write(&mut self, file: &mut Ext4File, data: &[u8]) {
+    pub fn ext4_file_write(&mut self, file: &mut Ext4File, data: &[u8]) -> Result<()> {
         let size = data.len();
         let mut inode_ref = self.get_inode_ref(file.inode);
         // Sync ext file
@@ -169,7 +166,7 @@ impl Ext4 {
         // Append enough block for writing
         let append_block_count = end_iblock + 1 - block_count as LBlockId;
         for _ in 0..append_block_count {
-            self.inode_append_block(&mut inode_ref);
+            self.inode_append_block(&mut inode_ref)?;
         }
 
         // Write data
@@ -177,9 +174,10 @@ impl Ext4 {
         let mut iblock = start_iblock;
         while cursor < size {
             let write_len = min(BLOCK_SIZE, size - cursor);
-            let fblock = self.extent_get_pblock(&mut inode_ref, iblock);
+            let fblock = self.extent_get_pblock(&mut inode_ref, iblock)?;
             if fblock != 0 {
-                self.block_device.write_offset(cursor, &data[cursor..cursor + write_len]);
+                self.block_device
+                    .write_offset(cursor, &data[cursor..cursor + write_len]);
             } else {
                 panic!("Write to unallocated block");
             }
@@ -187,6 +185,7 @@ impl Ext4 {
             file.fpos += write_len;
             iblock += 1;
         }
+        Ok(())
     }
 
     pub fn ext4_file_remove(&self, _path: &str) -> Result<usize> {

+ 5 - 6
src/ext4/link.rs

@@ -1,5 +1,5 @@
 use super::Ext4;
-use crate::constants::*;
+use crate::prelude::*;
 use crate::ext4_defs::*;
 
 impl Ext4 {
@@ -8,7 +8,7 @@ impl Ext4 {
         parent: &mut Ext4InodeRef,
         child: &mut Ext4InodeRef,
         name: &str,
-    ) -> usize {
+    ) -> Result<()> {
         // Add entry to parent directory
         let _r = self.dir_add_entry(parent, child, name);
         child.inode.links_count += 1;
@@ -16,12 +16,11 @@ impl Ext4 {
         if child.inode.is_dir(&self.super_block) {
             // add '.' and '..' entries
             let child_self = child.clone();
-            self.dir_add_entry(child, &child_self, ".");
+            self.dir_add_entry(child, &child_self, ".")?;
             child.inode.links_count += 1;
-            self.dir_add_entry(child, parent, "..");
+            self.dir_add_entry(child, parent, "..")?;
             parent.inode.links_count += 1;
         }
-
-        EOK
+        Ok(())
     }
 }

+ 3 - 3
src/ext4/mod.rs

@@ -21,7 +21,7 @@ impl Ext4 {
     ///
     /// | Super Block | Group Descriptor | Reserved GDT Blocks |
     /// | Block Bitmap | Inode Bitmap | Inode Table | Data Blocks |
-    pub fn load(block_device: Arc<dyn BlockDevice>) -> Self {
+    pub fn load(block_device: Arc<dyn BlockDevice>) -> Result<Self> {
         // Load the superblock
         // TODO: if the main superblock is corrupted, should we load the backup?
         let raw_data = block_device.read_offset(BASE_OFFSET);
@@ -35,8 +35,8 @@ impl Ext4 {
             mount_point,
         };
         // Create root directory
-        ext4.alloc_root_inode();
-        ext4
+        ext4.alloc_root_inode()?;
+        Ok(ext4)
     }
 
     /// Read an inode from block device, return an`Ext4InodeRef` that combines

+ 22 - 8
src/ext4_defs/dir_entry.rs

@@ -58,15 +58,28 @@ impl Default for Ext4DirEntry {
     }
 }
 
-impl<T> TryFrom<&[T]> for Ext4DirEntry {
-    type Error = u64;
-    fn try_from(data: &[T]) -> core::result::Result<Self, u64> {
-        let data = data;
-        Ok(unsafe { core::ptr::read(data.as_ptr() as *const _) })
+impl Ext4DirEntry {
+    /// Create a new directory entry
+    pub fn new(inode: u32, rec_len: u16, name: &str, dirent_type: FileType) -> Self {
+        let mut name_bytes = [0u8; 255];
+        let name_len = name.as_bytes().len();
+        name_bytes[..name_len].copy_from_slice(name.as_bytes());
+        Self {
+            inode,
+            rec_len,
+            name_len: name_len as u8,
+            inner: Ext4DirEnInner {
+                inode_type: dirent_type,
+            },
+            name: name_bytes,
+        }
+    }
+
+    /// Load a directory entry from bytes
+    pub fn from_bytes(bytes: &[u8]) -> Self {
+        unsafe { core::ptr::read(bytes.as_ptr() as *const _) }
     }
-}
 
-impl Ext4DirEntry {
     pub fn name(&self) -> core::result::Result<String, FromUtf8Error> {
         let name_len = self.name_len as usize;
         let name = &self.name[..name_len];
@@ -82,6 +95,7 @@ impl Ext4DirEntry {
         self.name[..name.len()].copy_from_slice(name.as_bytes());
     }
 
+    /// Distance to the next directory entry
     pub fn rec_len(&self) -> u16 {
         self.rec_len
     }
@@ -167,7 +181,7 @@ pub struct Ext4DirEntryTail {
 }
 
 impl Ext4DirEntryTail {
-    pub fn from(data: &mut [u8], blocksize: usize) -> Option<Self> {
+    pub fn from_bytes(data: &mut [u8], blocksize: usize) -> Option<Self> {
         unsafe {
             let ptr = data as *mut [u8] as *mut u8;
             let t = *(ptr.add(blocksize - core::mem::size_of::<Ext4DirEntryTail>())