feat(ext4): block and inode bitmap allocation/deallocation
This commit is contained in:
121
crates/servers/storage-server/src/fs/ext4/bitmap.rs
Normal file
121
crates/servers/storage-server/src/fs/ext4/bitmap.rs
Normal file
@@ -0,0 +1,121 @@
|
||||
use port_block_device::BlockDevice;
|
||||
use super::io::{read_block, write_block};
|
||||
use super::superblock::Superblock;
|
||||
use super::bgd::BlockGroupDescriptor;
|
||||
|
||||
pub fn alloc_block<B: BlockDevice>(
|
||||
device: &mut B,
|
||||
sb: &mut Superblock,
|
||||
gdt_block: u32,
|
||||
spb: usize,
|
||||
) -> Option<u32> {
|
||||
let bg = 0u32;
|
||||
let mut bgd = BlockGroupDescriptor::read(device, gdt_block, bg, spb)?;
|
||||
if bgd.free_blocks_count == 0 { return None; }
|
||||
|
||||
let mut bitmap = [0u8; 4096];
|
||||
if !read_block(device, bgd.block_bitmap as u64, spb, &mut bitmap) { return None; }
|
||||
|
||||
for byte_idx in 0..sb.blocks_count as usize {
|
||||
let byte = byte_idx / 8;
|
||||
let bit = byte_idx % 8;
|
||||
if byte >= bitmap.len() { break; }
|
||||
if bitmap[byte] & (1 << bit) == 0 {
|
||||
bitmap[byte] |= 1 << bit;
|
||||
if !write_block(device, bgd.block_bitmap as u64, spb, &bitmap) { return None; }
|
||||
bgd.free_blocks_count -= 1;
|
||||
bgd.write_back(device, gdt_block, bg, spb);
|
||||
sb.free_blocks_count -= 1;
|
||||
sb.write_back(device);
|
||||
return Some(byte_idx as u32);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn free_block<B: BlockDevice>(
|
||||
device: &mut B,
|
||||
sb: &mut Superblock,
|
||||
gdt_block: u32,
|
||||
block: u32,
|
||||
spb: usize,
|
||||
) {
|
||||
let bg = 0u32;
|
||||
let mut bgd = match BlockGroupDescriptor::read(device, gdt_block, bg, spb) {
|
||||
Some(b) => b,
|
||||
None => return,
|
||||
};
|
||||
|
||||
let mut bitmap = [0u8; 4096];
|
||||
if !read_block(device, bgd.block_bitmap as u64, spb, &mut bitmap) { return; }
|
||||
|
||||
let byte = block as usize / 8;
|
||||
let bit = block as usize % 8;
|
||||
if byte < bitmap.len() {
|
||||
bitmap[byte] &= !(1 << bit);
|
||||
write_block(device, bgd.block_bitmap as u64, spb, &bitmap);
|
||||
bgd.free_blocks_count += 1;
|
||||
bgd.write_back(device, gdt_block, bg, spb);
|
||||
sb.free_blocks_count += 1;
|
||||
sb.write_back(device);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alloc_inode<B: BlockDevice>(
|
||||
device: &mut B,
|
||||
sb: &mut Superblock,
|
||||
gdt_block: u32,
|
||||
spb: usize,
|
||||
) -> Option<u32> {
|
||||
let bg = 0u32;
|
||||
let mut bgd = BlockGroupDescriptor::read(device, gdt_block, bg, spb)?;
|
||||
if bgd.free_inodes_count == 0 { return None; }
|
||||
|
||||
let mut bitmap = [0u8; 4096];
|
||||
if !read_block(device, bgd.inode_bitmap as u64, spb, &mut bitmap) { return None; }
|
||||
|
||||
for bit_idx in 0..sb.inodes_count as usize {
|
||||
let byte = bit_idx / 8;
|
||||
let bit = bit_idx % 8;
|
||||
if byte >= bitmap.len() { break; }
|
||||
if bitmap[byte] & (1 << bit) == 0 {
|
||||
bitmap[byte] |= 1 << bit;
|
||||
if !write_block(device, bgd.inode_bitmap as u64, spb, &bitmap) { return None; }
|
||||
bgd.free_inodes_count -= 1;
|
||||
bgd.write_back(device, gdt_block, bg, spb);
|
||||
sb.free_inodes_count -= 1;
|
||||
sb.write_back(device);
|
||||
return Some(bit_idx as u32 + 1); // inodes are 1-based
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn free_inode<B: BlockDevice>(
|
||||
device: &mut B,
|
||||
sb: &mut Superblock,
|
||||
gdt_block: u32,
|
||||
inode: u32,
|
||||
spb: usize,
|
||||
) {
|
||||
let bg = 0u32;
|
||||
let mut bgd = match BlockGroupDescriptor::read(device, gdt_block, bg, spb) {
|
||||
Some(b) => b,
|
||||
None => return,
|
||||
};
|
||||
|
||||
let mut bitmap = [0u8; 4096];
|
||||
if !read_block(device, bgd.inode_bitmap as u64, spb, &mut bitmap) { return; }
|
||||
|
||||
let bit_idx = (inode - 1) as usize; // inodes are 1-based
|
||||
let byte = bit_idx / 8;
|
||||
let bit = bit_idx % 8;
|
||||
if byte < bitmap.len() {
|
||||
bitmap[byte] &= !(1 << bit);
|
||||
write_block(device, bgd.inode_bitmap as u64, spb, &bitmap);
|
||||
bgd.free_inodes_count += 1;
|
||||
bgd.write_back(device, gdt_block, bg, spb);
|
||||
sb.free_inodes_count += 1;
|
||||
sb.write_back(device);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
pub mod io;
|
||||
pub mod superblock;
|
||||
pub mod bgd;
|
||||
pub mod bitmap;
|
||||
|
||||
use port_block_device::BlockDevice;
|
||||
use crate::filesystem::{DirEntry, FileHandle, FileName, FileSystem};
|
||||
@@ -173,6 +174,26 @@ impl<B: BlockDevice> Ext4<B> {
|
||||
self.write_inode(inode_num, inode)
|
||||
}
|
||||
|
||||
pub fn alloc_block(&mut self) -> Option<u32> {
|
||||
let spb = self.sb.sectors_per_block();
|
||||
bitmap::alloc_block(&mut self.device, &mut self.sb, self.gdt_block, spb)
|
||||
}
|
||||
|
||||
pub fn free_block(&mut self, block: u32) {
|
||||
let spb = self.sb.sectors_per_block();
|
||||
bitmap::free_block(&mut self.device, &mut self.sb, self.gdt_block, block, spb);
|
||||
}
|
||||
|
||||
pub fn alloc_inode(&mut self) -> Option<u32> {
|
||||
let spb = self.sb.sectors_per_block();
|
||||
bitmap::alloc_inode(&mut self.device, &mut self.sb, self.gdt_block, spb)
|
||||
}
|
||||
|
||||
pub fn free_inode(&mut self, inode: u32) {
|
||||
let spb = self.sb.sectors_per_block();
|
||||
bitmap::free_inode(&mut self.device, &mut self.sb, self.gdt_block, inode, spb);
|
||||
}
|
||||
|
||||
fn read_extents(&self, inode: &Inode) -> Option<Extent> {
|
||||
if !inode.uses_extents() { return None; }
|
||||
let hdr = &inode.block_data;
|
||||
|
||||
Reference in New Issue
Block a user