|
@@ -7,7 +7,7 @@ use crate::return_error;
|
|
|
|
|
|
impl Ext4 {
|
|
|
/// Create a new inode, returning the inode and its number
|
|
|
- pub(super) fn create_inode(&mut self, mode: InodeMode) -> Result<InodeRef> {
|
|
|
+ pub(super) fn create_inode(&self, mode: InodeMode) -> Result<InodeRef> {
|
|
|
// Allocate an inode
|
|
|
let is_dir = mode.file_type() == FileType::Directory;
|
|
|
let id = self.alloc_inode(is_dir)?;
|
|
@@ -16,9 +16,6 @@ impl Ext4 {
|
|
|
let mut inode = Inode::default();
|
|
|
inode.set_mode(mode);
|
|
|
inode.extent_init();
|
|
|
- if self.super_block.inode_size() > EXT4_GOOD_OLD_INODE_SIZE {
|
|
|
- inode.set_extra_isize(self.super_block.extra_size());
|
|
|
- }
|
|
|
let mut inode_ref = InodeRef::new(id, inode);
|
|
|
|
|
|
// Sync the inode to disk
|
|
@@ -29,16 +26,14 @@ impl Ext4 {
|
|
|
}
|
|
|
|
|
|
/// Create(initialize) the root inode of the file system
|
|
|
- pub(super) fn create_root_inode(&mut self) -> Result<InodeRef> {
|
|
|
+ pub(super) fn create_root_inode(&self) -> Result<InodeRef> {
|
|
|
let mut inode = Inode::default();
|
|
|
inode.set_mode(InodeMode::from_type_and_perm(
|
|
|
FileType::Directory,
|
|
|
InodeMode::ALL_RWX,
|
|
|
));
|
|
|
inode.extent_init();
|
|
|
- if self.super_block.inode_size() > EXT4_GOOD_OLD_INODE_SIZE {
|
|
|
- inode.set_extra_isize(self.super_block.extra_size());
|
|
|
- }
|
|
|
+
|
|
|
let mut root = InodeRef::new(EXT4_ROOT_INO, inode);
|
|
|
let root_self = root.clone();
|
|
|
|
|
@@ -51,14 +46,14 @@ impl Ext4 {
|
|
|
}
|
|
|
|
|
|
/// Free an allocated inode and all data blocks allocated for it
|
|
|
- pub(super) fn free_inode(&mut self, inode: &mut InodeRef) -> Result<()> {
|
|
|
+ pub(super) fn free_inode(&self, inode: &mut InodeRef) -> Result<()> {
|
|
|
// Free the data blocks allocated for the inode
|
|
|
let pblocks = self.extent_all_data_blocks(&inode);
|
|
|
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);
|
|
|
+ inode.inode.set_block_count(inode.inode.block_count() - 1);
|
|
|
// Clear the block content
|
|
|
self.write_block(&Block::new(pblock, [0; BLOCK_SIZE]));
|
|
|
}
|
|
@@ -80,21 +75,18 @@ impl Ext4 {
|
|
|
}
|
|
|
|
|
|
/// Append a data block for an inode, return a pair of (logical block id, physical block id)
|
|
|
- ///
|
|
|
- /// Only data blocks allocated by `inode_append_block` will be counted in `inode.block_count`.
|
|
|
+ ///
|
|
|
+ /// Only data blocks allocated by `inode_append_block` will be counted in `inode.block_count`.
|
|
|
/// Blocks allocated by calling `alloc_block` directly will not be counted, i.e., blocks
|
|
|
/// allocated for the inode's extent tree.
|
|
|
- ///
|
|
|
+ ///
|
|
|
/// Appending a block does not increase `inode.size`, because `inode.size` records the actual
|
|
|
- /// size of the data content, not the number of blocks allocated for it.
|
|
|
- ///
|
|
|
+ /// size of the data content, not the number of blocks allocated for it.
|
|
|
+ ///
|
|
|
/// If the inode is a file, `inode.size` will be increased when writing to end of the file.
|
|
|
/// If the inode is a directory, `inode.size` will be increased when adding a new entry to the
|
|
|
/// newly created block.
|
|
|
- pub(super) fn inode_append_block(
|
|
|
- &mut self,
|
|
|
- inode: &mut InodeRef,
|
|
|
- ) -> Result<(LBlockId, PBlockId)> {
|
|
|
+ pub(super) fn inode_append_block(&self, inode: &mut InodeRef) -> Result<(LBlockId, PBlockId)> {
|
|
|
// The new logical block id
|
|
|
let iblock = inode.inode.block_count() as LBlockId;
|
|
|
// Check the extent tree to get the physical block id
|
|
@@ -107,16 +99,18 @@ impl Ext4 {
|
|
|
}
|
|
|
|
|
|
/// Allocate a new physical block for an inode, return the physical block number
|
|
|
- pub(super) fn alloc_block(&mut self, inode: &mut InodeRef) -> Result<PBlockId> {
|
|
|
+ pub(super) fn alloc_block(&self, inode: &mut InodeRef) -> Result<PBlockId> {
|
|
|
+ let mut sb = self.read_super_block();
|
|
|
+
|
|
|
// Calc block group id
|
|
|
- let inodes_per_group = self.super_block.inodes_per_group();
|
|
|
+ let inodes_per_group = sb.inodes_per_group();
|
|
|
let bgid = ((inode.id - 1) / inodes_per_group) as BlockGroupId;
|
|
|
|
|
|
// Load block group descriptor
|
|
|
let mut bg = self.read_block_group(bgid);
|
|
|
|
|
|
// Load block bitmap
|
|
|
- let bitmap_block_id = bg.desc.block_bitmap_block(&self.super_block);
|
|
|
+ let bitmap_block_id = bg.desc.block_bitmap_block(&sb);
|
|
|
let mut bitmap_block = self.read_block(bitmap_block_id);
|
|
|
let mut bitmap = Bitmap::new(&mut bitmap_block.data);
|
|
|
|
|
@@ -130,13 +124,13 @@ impl Ext4 {
|
|
|
))? as PBlockId;
|
|
|
|
|
|
// Set block group checksum
|
|
|
- bg.desc.set_block_bitmap_csum(&self.super_block, &bitmap);
|
|
|
+ bg.desc.set_block_bitmap_csum(&sb, &bitmap);
|
|
|
self.write_block(&bitmap_block);
|
|
|
|
|
|
// Update superblock free blocks count
|
|
|
- let free_blocks = self.super_block.free_blocks_count() - 1;
|
|
|
- self.super_block.set_free_blocks_count(free_blocks);
|
|
|
- self.write_super_block();
|
|
|
+ let free_blocks = sb.free_blocks_count() - 1;
|
|
|
+ sb.set_free_blocks_count(free_blocks);
|
|
|
+ self.write_super_block(&sb);
|
|
|
|
|
|
// Update block group free blocks count
|
|
|
let fb_cnt = bg.desc.get_free_blocks_count() - 1;
|
|
@@ -149,20 +143,18 @@ impl Ext4 {
|
|
|
}
|
|
|
|
|
|
/// Deallocate a physical block allocated for an inode
|
|
|
- pub(super) fn dealloc_block(
|
|
|
- &mut self,
|
|
|
- inode: &mut InodeRef,
|
|
|
- pblock: PBlockId,
|
|
|
- ) -> Result<()> {
|
|
|
+ pub(super) fn dealloc_block(&self, inode: &mut InodeRef, pblock: PBlockId) -> Result<()> {
|
|
|
+ let mut sb = self.read_super_block();
|
|
|
+
|
|
|
// Calc block group id
|
|
|
- let inodes_per_group = self.super_block.inodes_per_group();
|
|
|
+ let inodes_per_group = sb.inodes_per_group();
|
|
|
let bgid = ((inode.id - 1) / inodes_per_group) as BlockGroupId;
|
|
|
|
|
|
// Load block group descriptor
|
|
|
let mut bg = self.read_block_group(bgid);
|
|
|
|
|
|
// Load block bitmap
|
|
|
- let bitmap_block_id = bg.desc.block_bitmap_block(&self.super_block);
|
|
|
+ let bitmap_block_id = bg.desc.block_bitmap_block(&sb);
|
|
|
let mut bitmap_block = self.read_block(bitmap_block_id);
|
|
|
let mut bitmap = Bitmap::new(&mut bitmap_block.data);
|
|
|
|
|
@@ -173,13 +165,13 @@ impl Ext4 {
|
|
|
bitmap.clear_bit(pblock as usize);
|
|
|
|
|
|
// Set block group checksum
|
|
|
- bg.desc.set_block_bitmap_csum(&self.super_block, &bitmap);
|
|
|
+ bg.desc.set_block_bitmap_csum(&sb, &bitmap);
|
|
|
self.write_block(&bitmap_block);
|
|
|
|
|
|
// Update superblock free blocks count
|
|
|
- let free_blocks = self.super_block.free_blocks_count() + 1;
|
|
|
- self.super_block.set_free_blocks_count(free_blocks);
|
|
|
- self.write_super_block();
|
|
|
+ let free_blocks = sb.free_blocks_count() + 1;
|
|
|
+ sb.set_free_blocks_count(free_blocks);
|
|
|
+ self.write_super_block(&sb);
|
|
|
|
|
|
// Update block group free blocks count
|
|
|
let fb_cnt = bg.desc.get_free_blocks_count() + 1;
|
|
@@ -192,10 +184,11 @@ impl Ext4 {
|
|
|
}
|
|
|
|
|
|
/// Allocate a new inode, returning the inode number.
|
|
|
- fn alloc_inode(&mut self, is_dir: bool) -> Result<InodeId> {
|
|
|
- let mut bgid = 0;
|
|
|
- let bg_count = self.super_block.block_groups_count();
|
|
|
+ fn alloc_inode(&self, is_dir: bool) -> Result<InodeId> {
|
|
|
+ let mut sb = self.read_super_block();
|
|
|
+ let bg_count = sb.block_groups_count();
|
|
|
|
|
|
+ let mut bgid = 0;
|
|
|
while bgid <= bg_count {
|
|
|
// Load block group descriptor
|
|
|
let mut bg = self.read_block_group(bgid);
|
|
@@ -206,9 +199,9 @@ impl Ext4 {
|
|
|
}
|
|
|
|
|
|
// Load inode bitmap
|
|
|
- let bitmap_block_id = bg.desc.inode_bitmap_block(&self.super_block);
|
|
|
+ let bitmap_block_id = bg.desc.inode_bitmap_block(&sb);
|
|
|
let mut bitmap_block = self.read_block(bitmap_block_id);
|
|
|
- let inode_count = self.super_block.inode_count_in_group(bgid) as usize;
|
|
|
+ let inode_count = sb.inode_count_in_group(bgid) as usize;
|
|
|
let mut bitmap = Bitmap::new(&mut bitmap_block.data[..inode_count / 8]);
|
|
|
|
|
|
// Find a free inode
|
|
@@ -222,36 +215,35 @@ impl Ext4 {
|
|
|
))? as u32;
|
|
|
|
|
|
// Update bitmap in disk
|
|
|
- bg.desc.set_inode_bitmap_csum(&self.super_block, &bitmap);
|
|
|
+ bg.desc.set_inode_bitmap_csum(&sb, &bitmap);
|
|
|
self.write_block(&bitmap_block);
|
|
|
|
|
|
// Modify filesystem counters
|
|
|
let free_inodes = bg.desc.free_inodes_count() - 1;
|
|
|
- bg.desc
|
|
|
- .set_free_inodes_count(&self.super_block, free_inodes);
|
|
|
+ bg.desc.set_free_inodes_count(&sb, free_inodes);
|
|
|
|
|
|
// Increase used directories counter
|
|
|
if is_dir {
|
|
|
- let used_dirs = bg.desc.used_dirs_count(&self.super_block) + 1;
|
|
|
- bg.desc.set_used_dirs_count(&self.super_block, used_dirs);
|
|
|
+ let used_dirs = bg.desc.used_dirs_count(&sb) + 1;
|
|
|
+ bg.desc.set_used_dirs_count(&sb, used_dirs);
|
|
|
}
|
|
|
|
|
|
// Decrease unused inodes count
|
|
|
- let mut unused = bg.desc.itable_unused(&self.super_block);
|
|
|
+ let mut unused = bg.desc.itable_unused(&sb);
|
|
|
let free = inode_count as u32 - unused;
|
|
|
if idx_in_bg >= free {
|
|
|
unused = inode_count as u32 - (idx_in_bg + 1);
|
|
|
- bg.desc.set_itable_unused(&self.super_block, unused);
|
|
|
+ bg.desc.set_itable_unused(&sb, unused);
|
|
|
}
|
|
|
|
|
|
self.write_block_group_with_csum(&mut bg);
|
|
|
|
|
|
// Update superblock
|
|
|
- self.super_block.decrease_free_inodes_count();
|
|
|
- self.write_super_block();
|
|
|
+ sb.decrease_free_inodes_count();
|
|
|
+ self.write_super_block(&sb);
|
|
|
|
|
|
// Compute the absolute i-node number
|
|
|
- let inodes_per_group = self.super_block.inodes_per_group();
|
|
|
+ let inodes_per_group = sb.inodes_per_group();
|
|
|
let inode_id = bgid * inodes_per_group + (idx_in_bg + 1);
|
|
|
|
|
|
return Ok(inode_id);
|
|
@@ -262,9 +254,11 @@ impl Ext4 {
|
|
|
}
|
|
|
|
|
|
/// Free an inode
|
|
|
- fn dealloc_inode(&mut self, inode_ref: &InodeRef) -> Result<()> {
|
|
|
+ fn dealloc_inode(&self, inode_ref: &InodeRef) -> Result<()> {
|
|
|
+ let mut sb = self.read_super_block();
|
|
|
+
|
|
|
// Calc block group id and index in block group
|
|
|
- let inodes_per_group = self.super_block.inodes_per_group();
|
|
|
+ let inodes_per_group = sb.inodes_per_group();
|
|
|
let bgid = ((inode_ref.id - 1) / inodes_per_group) as BlockGroupId;
|
|
|
let idx_in_bg = (inode_ref.id - 1) % inodes_per_group;
|
|
|
|
|
@@ -272,9 +266,9 @@ impl Ext4 {
|
|
|
let mut bg = self.read_block_group(bgid);
|
|
|
|
|
|
// Load inode bitmap
|
|
|
- let bitmap_block_id = bg.desc.inode_bitmap_block(&self.super_block);
|
|
|
+ let bitmap_block_id = bg.desc.inode_bitmap_block(&sb);
|
|
|
let mut bitmap_block = self.read_block(bitmap_block_id);
|
|
|
- let inode_count = self.super_block.inode_count_in_group(bgid) as usize;
|
|
|
+ let inode_count = sb.inode_count_in_group(bgid) as usize;
|
|
|
let mut bitmap = Bitmap::new(&mut bitmap_block.data[..inode_count / 8]);
|
|
|
|
|
|
// Free the inode
|
|
@@ -289,29 +283,28 @@ impl Ext4 {
|
|
|
bitmap.clear_bit(idx_in_bg as usize);
|
|
|
|
|
|
// Update bitmap in disk
|
|
|
- bg.desc.set_inode_bitmap_csum(&self.super_block, &bitmap);
|
|
|
+ bg.desc.set_inode_bitmap_csum(&sb, &bitmap);
|
|
|
self.write_block(&bitmap_block);
|
|
|
|
|
|
// Modify filesystem counters
|
|
|
let free_inodes = bg.desc.free_inodes_count() + 1;
|
|
|
- bg.desc
|
|
|
- .set_free_inodes_count(&self.super_block, free_inodes);
|
|
|
+ bg.desc.set_free_inodes_count(&sb, free_inodes);
|
|
|
|
|
|
// Increase used directories counter
|
|
|
if inode_ref.inode.is_dir() {
|
|
|
- let used_dirs = bg.desc.used_dirs_count(&self.super_block) - 1;
|
|
|
- bg.desc.set_used_dirs_count(&self.super_block, used_dirs);
|
|
|
+ let used_dirs = bg.desc.used_dirs_count(&sb) - 1;
|
|
|
+ bg.desc.set_used_dirs_count(&sb, used_dirs);
|
|
|
}
|
|
|
|
|
|
// Decrease unused inodes count
|
|
|
- let unused = bg.desc.itable_unused(&self.super_block) + 1;
|
|
|
- bg.desc.set_itable_unused(&self.super_block, unused);
|
|
|
+ let unused = bg.desc.itable_unused(&sb) + 1;
|
|
|
+ bg.desc.set_itable_unused(&sb, unused);
|
|
|
|
|
|
self.write_block_group_with_csum(&mut bg);
|
|
|
|
|
|
// Update superblock
|
|
|
- self.super_block.decrease_free_inodes_count();
|
|
|
- self.write_super_block();
|
|
|
+ sb.decrease_free_inodes_count();
|
|
|
+ self.write_super_block(&sb);
|
|
|
|
|
|
Ok(())
|
|
|
}
|