From f43331b8835a7775c21f495a72c6df057a679f3e Mon Sep 17 00:00:00 2001 From: Raghumani Mehta Date: Fri, 26 Dec 2025 02:07:24 +0530 Subject: [PATCH 01/11] the code compiles but the logic is a bit off, will continue tomorrow --- src/main.rs | 74 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 69 insertions(+), 5 deletions(-) diff --git a/src/main.rs b/src/main.rs index c260761..5abf001 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,14 +2,15 @@ use bitvec::prelude::*; use fuser::{FileType, Filesystem, MountOption}; use log::{debug, error, info, log_enabled, Level}; use std::env; +use std::time::{SystemTime, UNIX_EPOCH}; struct NullFS; impl Filesystem for NullFS {} // This is the total capacity of the backing storage for the file system // this includes the space used for the superblock, free object bitmaps, and file data and metadata -const FS_SIZE_BYTES: u64 = 1u64 * (0b1 << 30) as u64; // 1 GB, toy size -const BLK_SIZE_BYTES: u64 = 4096u64; +const FS_SIZE_BYTES: u64 = 1u64 << 30; // 1 GB +const BLK_SIZE_BYTES: u64 = 4096; const NUM_DATA_BLKS: u32 = (FS_SIZE_BYTES / BLK_SIZE_BYTES) as u32; const FREE_BLK_BMAP_SIZE_BYTES: usize = ((NUM_DATA_BLKS + 7) / 8) as usize; @@ -17,6 +18,7 @@ const FREE_BLK_BMAP_SIZE_BYTES: usize = ((NUM_DATA_BLKS + 7) / 8) as usize; const MAX_NUM_INODES: u32 = 10; // toy size const FREE_INODE_BMAP_SIZE_BYTES: usize = ((MAX_NUM_INODES + 7) / 8) as usize; const NUM_INO_DIRECT_PTR: usize = 12; +const INVALID_PTR: u32 = 0; // free inode bitmap can begin right after this struct and inode table can follow immediately after struct SuperBlock { @@ -75,6 +77,30 @@ struct Inode { tri_indirect_blk: u32, } +fn secs_from_unix_epoch() -> i64 { + SystemTime::now() + .duration_since(UNIX_EPOCH) + .map(|d| d.as_secs() as i64) + .unwrap_or(0) +} + +impl Inode { + fn new(ino_id: u64, kind: FileType, perm: u16) -> Self { + Self { + ino_id, + size: 0, + blocks: 0, + mtime_secs: secs_from_unix_epoch(), + kind, + perm, + direct_blks: [INVALID_PTR; NUM_INO_DIRECT_PTR], + indirect_blk: INVALID_PTR, + dbl_indirect_blk: INVALID_PTR, + tri_indirect_blk: INVALID_PTR, + } + } +} + #[derive(Default)] struct FreeInodeBitmap { map: BitArray<[u8; FREE_INODE_BMAP_SIZE_BYTES], Lsb0>, @@ -91,13 +117,51 @@ struct FSState { superblk: SuperBlock, free_blks: FreeBlockBitmap, inode_bitmap: FreeInodeBitmap, - inodes: Vec, + inodes: [Option; MAX_NUM_INODES as usize], blks: Vec, } +#[derive(Debug)] +enum InodeError { + NoFreeInodesOnAlloc, + InodeNotFound, + InvalidInoId +} + impl FSState { - fn alloc_inode(&mut self) -> Option { - None + fn alloc_inode(&mut self, kind: FileType, perm: u16) -> Result { + let ino_idx: usize = match self.inode_bitmap.find_first_free() { + Some(idx) => idx, + None => { + error!("alloc_inode failed: no free inodes"); + return Err(InodeError::NoFreeInodesOnAlloc); + } + }; + + // mark inode allocated in bitmap + self.inode_bitmap.map.set(ino_idx, true); + + // The true index is 0, but we use 0 as an invalid ptr so always + // increment when storing ptrs + let ino_id: u64 = (ino_idx + 1) as u64; + self.inodes[ino_idx] = Some(Inode::new(ino_id, kind, perm)); + + Ok(ino_id) + } + + fn fnid_inode_by_id(&self, ino_id: u64) -> Result<&Inode, InodeError> { + if ino_id <= 0 { + return Err(InodeError::InvalidInoId); + } + let ino_idx = (ino_id - 1) as usize; + if ino_idx >= (MAX_NUM_INODES as usize) { + return Err(InodeError::InodeNotFound); + } + + match self.inodes[ino_idx].as_ref() { + Some(inode) => Ok(inode), + None => Err(InodeError::InodeNotFound), + } } } From 39902d5fd24624a35e9f2aee6b541d95d0337032 Mon Sep 17 00:00:00 2001 From: Raghumani Mehta Date: Sun, 28 Dec 2025 21:06:49 +0530 Subject: [PATCH 02/11] added todos --- src/main.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 5abf001..a5b4a9f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -36,8 +36,8 @@ impl Default for SuperBlock { Self { ino_count: MAX_NUM_INODES, blk_count: NUM_DATA_BLKS, - free_blk_count: NUM_DATA_BLKS - 3u32, // first three blocks are reserved for FS metadata - free_ino_count: MAX_NUM_INODES - 1, // first inode is reserved for the root + free_blk_count: NUM_DATA_BLKS, // first three blocks are reserved for FS metadata + free_ino_count: MAX_NUM_INODES, // first inode is reserved for the root super_blk_no: 0, mtime: 0, wtime: 0, @@ -138,6 +138,9 @@ impl FSState { } }; + // TODO: add root inode logic + // TODO: Block first two blocks. + // TODO: Reserved ones // mark inode allocated in bitmap self.inode_bitmap.map.set(ino_idx, true); From fcf4fefe85d704cf570c8aa1332c7ad0cad879d6 Mon Sep 17 00:00:00 2001 From: Raghumani Mehta Date: Mon, 29 Dec 2025 00:18:19 +0530 Subject: [PATCH 03/11] added set_alloc and get_free functions for FreeObjectBitmap --- src/main.rs | 91 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 68 insertions(+), 23 deletions(-) diff --git a/src/main.rs b/src/main.rs index 77957d0..47a7297 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,7 +11,7 @@ impl Filesystem for NullFS {} // this includes the space used for the FSMetadata, free object bitmaps, and file data and metadata const FS_SIZE_BYTES: u64 = 1u64 * (0b1 << 30) as u64; // 1 GB const BLK_SIZE_BYTES: u64 = 4096u64; -// some blocks reserved for FSMetadata, free inode and data block bitmaps, and inode table +// 0 -> FSMetadata, 1->InodeBitmap, 2 -> Freeblock bitmap const RESERVED_DATA_BLKS: u32 = 3; const NUM_DATA_BLKS: u32 = (FS_SIZE_BYTES / BLK_SIZE_BYTES) as u32; const FREE_BLK_BMAP_SIZE_BYTES: usize = ((NUM_DATA_BLKS + 7) / 8) as usize; @@ -53,11 +53,57 @@ struct Block { data: [u8; BLK_SIZE_BYTES as usize], } +#[derive(Debug)] +enum BitMapError { + RestrictedEntry, + AlreadyAlloced, + AlreadyFree +} + + trait FreeObjectBitmap { - fn map(&self) -> &BitArray<[u8; N], Lsb0>; + const RESERVED: usize; + const MAX: usize; + + fn map(&mut self) -> &mut BitArray<[u8; N], Lsb0>; + + fn find_first_free(&mut self) -> Option { + match self.map().first_zero() { + Some(idx) => { + if idx < Self::RESERVED { + None + } else { + Some(idx) + } + } + None => None, + } + } - fn find_first_free(&self) -> Option { - self.map().first_zero() + fn set_alloc(&mut self, idx: usize) -> Result<(), BitMapError> { + if idx < Self::RESERVED || idx > Self::MAX { + return Err(BitMapError::RestrictedEntry) + } + if self.map()[idx] == true { + error!("The index is already alloced, no change") + return Err(BitMapError::AlreadyAlloced) + } else { + self.map().set(idx, true); + Ok(()) + } + } + + fn set_free(&mut self, idx: usize) -> Result<(), BitMapError> { + if idx < Self::RESERVED || idx > Self::MAX { + return Err(BitMapError::RestrictedEntry) + } + if self.map()[idx] == false { + error!("The index is already free, no change") + return Err(BitMapError::AlreadyFree) + } else { + self.map().set(idx, false); + Ok(()) + } } } @@ -74,8 +120,10 @@ impl Default for FreeBlockBitmap { } impl FreeObjectBitmap for FreeBlockBitmap { - fn map(&self) -> &BitArray<[u8; FREE_BLK_BMAP_SIZE_BYTES], Lsb0> { - &self.map + const RESERVED: usize = RESERVED_DATA_BLKS as usize; + const MAX: usize = NUM_DATA_BLKS as usize; + fn map(&mut self) -> &mut BitArray<[u8; FREE_BLK_BMAP_SIZE_BYTES], Lsb0> { + &mut self.map } } @@ -117,7 +165,6 @@ impl Inode { } } -#[derive(Default)] struct FreeInodeBitmap { map: BitArray<[u8; FREE_INODE_BMAP_SIZE_BYTES], Lsb0>, } @@ -131,17 +178,19 @@ impl Default for FreeInodeBitmap { } impl FreeObjectBitmap for FreeInodeBitmap { - fn map(&self) -> &BitArray<[u8; FREE_INODE_BMAP_SIZE_BYTES], Lsb0> { - &self.map + const RESERVED: usize = RESERVED_INODES as usize; + const MAX: usize = MAX_NUM_INODES as usize; + fn map(&mut self) -> &mut BitArray<[u8; FREE_INODE_BMAP_SIZE_BYTES], Lsb0> { + &mut self.map } } struct FSState { - superblk: SuperBlock, - free_blks: FreeBlockBitmap, + metadata: FSMetadata, inode_bitmap: FreeInodeBitmap, inodes: [Option; MAX_NUM_INODES as usize], - blks: Vec, + free_blk_bitmap: FreeBlockBitmap, + blks: [Option; NUM_DATA_BLKS as usize], } #[derive(Debug)] @@ -188,27 +237,23 @@ impl FSState { Some(inode) => Ok(inode), None => Err(InodeError::InodeNotFound), } - metadata: FSMetadata, - free_inode_bitmap: FreeInodeBitmap, - inodes: [Option; MAX_NUM_INODES as usize], - free_blk_bitmap: FreeBlockBitmap, - blks: [Option; NUM_DATA_BLKS as usize], -} + } +} // we have to implement Default ourselves here // because the Default trait is not implemented for static arrays // above a certain size impl Default for FSState { fn default() -> Self { - let mut metadata = FSMetadata::default(); - let free_inode_bitmap = FreeInodeBitmap::default(); - let mut inodes = [None; MAX_NUM_INODES as usize]; + let metadata = FSMetadata::default(); + let inode_bitmap = FreeInodeBitmap::default(); + let inodes = [None; MAX_NUM_INODES as usize]; let free_blk_bitmap = FreeBlockBitmap::default(); - let mut blks = [None; NUM_DATA_BLKS as usize]; + let blks = [None; NUM_DATA_BLKS as usize]; Self { metadata, - free_inode_bitmap, + inode_bitmap, inodes, free_blk_bitmap, blks, From 3525f7f504d758d0e1bc0b890ebbf85c324d8677 Mon Sep 17 00:00:00 2001 From: Raghumani Mehta Date: Mon, 29 Dec 2025 10:31:39 +0530 Subject: [PATCH 04/11] freeObjectBitmap basic interaction functions --- src/main.rs | 177 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 126 insertions(+), 51 deletions(-) diff --git a/src/main.rs b/src/main.rs index 47a7297..a42ab2c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -68,16 +68,12 @@ trait FreeObjectBitmap { fn map(&mut self) -> &mut BitArray<[u8; N], Lsb0>; fn find_first_free(&mut self) -> Option { - match self.map().first_zero() { - Some(idx) => { - if idx < Self::RESERVED { - None - } else { - Some(idx) - } + for idx in Self::RESERVED..Self::MAX { + if !self.map()[idx] { + return Some(idx); } - None => None, } + None } fn set_alloc(&mut self, idx: usize) -> Result<(), BitMapError> { @@ -85,8 +81,8 @@ trait FreeObjectBitmap { return Err(BitMapError::RestrictedEntry) } if self.map()[idx] == true { - error!("The index is already alloced, no change") - return Err(BitMapError::AlreadyAlloced) + error!("The index is already alloced, no change"); + return Err(BitMapError::AlreadyAlloced); } else { self.map().set(idx, true); Ok(()) @@ -98,8 +94,8 @@ trait FreeObjectBitmap { return Err(BitMapError::RestrictedEntry) } if self.map()[idx] == false { - error!("The index is already free, no change") - return Err(BitMapError::AlreadyFree) + error!("The index is already free, no change"); + return Err(BitMapError::AlreadyFree); } else { self.map().set(idx, false); Ok(()) @@ -200,45 +196,7 @@ enum InodeError { InvalidInoId } -impl FSState { - fn alloc_inode(&mut self, kind: FileType, perm: u16) -> Result { - let ino_idx: usize = match self.inode_bitmap.find_first_free() { - Some(idx) => idx, - None => { - error!("alloc_inode failed: no free inodes"); - return Err(InodeError::NoFreeInodesOnAlloc); - } - }; - - // TODO: add root inode logic - // TODO: Block first two blocks. - // TODO: Reserved ones - // mark inode allocated in bitmap - self.inode_bitmap.map.set(ino_idx, true); - - // The true index is 0, but we use 0 as an invalid ptr so always - // increment when storing ptrs - let ino_id: u64 = (ino_idx + 1) as u64; - self.inodes[ino_idx] = Some(Inode::new(ino_id, kind, perm)); - - Ok(ino_id) - } - - fn fnid_inode_by_id(&self, ino_id: u64) -> Result<&Inode, InodeError> { - if ino_id <= 0 { - return Err(InodeError::InvalidInoId); - } - let ino_idx = (ino_id - 1) as usize; - if ino_idx >= (MAX_NUM_INODES as usize) { - return Err(InodeError::InodeNotFound); - } - - match self.inodes[ino_idx].as_ref() { - Some(inode) => Ok(inode), - None => Err(InodeError::InodeNotFound), - } - } -} +impl FSState {} // we have to implement Default ourselves here // because the Default trait is not implemented for static arrays @@ -266,3 +224,120 @@ fn main() { let mountpoint = env::args_os().nth(1).unwrap(); fuser::mount2(NullFS, mountpoint, &[MountOption::AutoUnmount]).unwrap(); } + +#[cfg(test)] +mod tests { + use super::*; + + // Test find_first_free + #[test] + fn test_find_first_free_returns_first_unreserved_index() { + let mut bitmap = FreeInodeBitmap::default(); + assert_eq!(bitmap.find_first_free(), Some(RESERVED_INODES as usize)); + } + + #[test] + fn test_find_first_free_skips_allocated_indices() { + let mut bitmap = FreeInodeBitmap::default(); + bitmap.map.set(2, true); + assert_eq!(bitmap.find_first_free(), Some(3)); + } + + #[test] + fn test_find_first_free_returns_none_when_full() { + let mut bitmap = FreeInodeBitmap::default(); + bitmap.map.fill(true); + assert_eq!(bitmap.find_first_free(), None); + } + + // Test set_alloc + #[test] + fn test_set_alloc_succeeds_for_valid_free_index() { + let mut bitmap = FreeInodeBitmap::default(); + let idx = RESERVED_INODES as usize; + assert!(bitmap.set_alloc(idx).is_ok()); + assert_eq!(bitmap.map[idx], true); + } + + #[test] + fn test_set_alloc_fails_for_reserved_index() { + let mut bitmap = FreeInodeBitmap::default(); + let result = bitmap.set_alloc(0); + assert!(matches!(result, Err(BitMapError::RestrictedEntry))); + } + + #[test] + fn test_set_alloc_fails_for_index_beyond_max() { + let mut bitmap = FreeInodeBitmap::default(); + let result = bitmap.set_alloc(MAX_NUM_INODES as usize + 1); + assert!(matches!(result, Err(BitMapError::RestrictedEntry))); + } + + #[test] + fn test_set_alloc_fails_for_already_allocated_index() { + let mut bitmap = FreeInodeBitmap::default(); + let idx = RESERVED_INODES as usize; + bitmap.map.set(idx, true); + let result = bitmap.set_alloc(idx); + assert!(matches!(result, Err(BitMapError::AlreadyAlloced))); + } + + // Test set_free + #[test] + fn test_set_free_succeeds_for_valid_allocated_index() { + let mut bitmap = FreeInodeBitmap::default(); + let idx = RESERVED_INODES as usize; + bitmap.map.set(idx, true); // First allocate it + assert!(bitmap.set_free(idx).is_ok()); + assert_eq!(bitmap.map[idx], false); + } + + #[test] + fn test_set_free_fails_for_reserved_index() { + let mut bitmap = FreeInodeBitmap::default(); + let result = bitmap.set_free(0); + assert!(matches!(result, Err(BitMapError::RestrictedEntry))); + assert_eq!(bitmap.map[0], true) + } + + #[test] + fn test_set_free_fails_for_index_beyond_max() { + let mut bitmap = FreeInodeBitmap::default(); + let result = bitmap.set_free(MAX_NUM_INODES as usize + 1); + assert!(matches!(result, Err(BitMapError::RestrictedEntry))); + + } + + #[test] + fn test_set_free_fails_for_already_free_index() { + let mut bitmap = FreeInodeBitmap::default(); + let idx = RESERVED_INODES as usize; + let mut result = bitmap.set_alloc((RESERVED_INODES as usize) + 1); + assert!(result.is_ok()); + let mut clone = FreeInodeBitmap::default(); + clone.set_alloc((RESERVED_INODES as usize) + 1) + let result = bitmap.set_free(idx); + assert!(matches!(result, Err(BitMapError::AlreadyFree))); + } + + // Test with FreeBlockBitmap to ensure trait works for both implementations + #[test] + fn test_free_block_bitmap_find_first_free() { + let mut bitmap = FreeBlockBitmap::default(); + assert_eq!(bitmap.find_first_free(), Some(RESERVED_DATA_BLKS as usize)); + } + + #[test] + fn test_free_block_bitmap_set_alloc_and_free() { + let mut bitmap = FreeBlockBitmap::default(); + let idx = RESERVED_DATA_BLKS as usize; + + // Allocate + assert!(bitmap.set_alloc(idx).is_ok()); + assert_eq!(bitmap.map[idx], true); + + // Free + assert!(bitmap.set_free(idx).is_ok()); + assert_eq!(bitmap.map[idx], false); + } +} From 75290571904ba559f3f39c99621541cd66d70ea5 Mon Sep 17 00:00:00 2001 From: Raghumani Mehta Date: Mon, 29 Dec 2025 10:41:20 +0530 Subject: [PATCH 05/11] fixed test --- src/main.rs | 44 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/src/main.rs b/src/main.rs index a42ab2c..b38d979 100644 --- a/src/main.rs +++ b/src/main.rs @@ -196,7 +196,45 @@ enum InodeError { InvalidInoId } -impl FSState {} +impl FSState { + fn alloc_inode(&mut self, kind: FileType, perm: u16) -> Result { + let ino_idx: usize = match self.inode_bitmap.find_first_free() { + Some(idx) => idx, + None => { + error!("alloc_inode failed: no free inodes"); + return Err(InodeError::NoFreeInodesOnAlloc); + } + }; + + // TODO: add root inode logic + // TODO: Block first two blocks. + // TODO: Reserved ones + // mark inode allocated in bitmap + self.inode_bitmap.map.set(ino_idx, true); + + // The true index is 0, but we use 0 as an invalid ptr so always + // increment when storing ptrs + let ino_id: u64 = (ino_idx + 1) as u64; + self.inodes[ino_idx] = Some(Inode::new(ino_id, kind, perm)); + + Ok(ino_id) + } + + fn fnid_inode_by_id(&self, ino_id: u64) -> Result<&Inode, InodeError> { + if ino_id <= 0 { + return Err(InodeError::InvalidInoId); + } + let ino_idx = (ino_id - 1) as usize; + if ino_idx >= (MAX_NUM_INODES as usize) { + return Err(InodeError::InodeNotFound); + } + + match self.inodes[ino_idx].as_ref() { + Some(inode) => Ok(inode), + None => Err(InodeError::InodeNotFound), + } + } +} // we have to implement Default ourselves here // because the Default trait is not implemented for static arrays @@ -312,10 +350,6 @@ mod tests { fn test_set_free_fails_for_already_free_index() { let mut bitmap = FreeInodeBitmap::default(); let idx = RESERVED_INODES as usize; - let mut result = bitmap.set_alloc((RESERVED_INODES as usize) + 1); - assert!(result.is_ok()); - let mut clone = FreeInodeBitmap::default(); - clone.set_alloc((RESERVED_INODES as usize) + 1) let result = bitmap.set_free(idx); assert!(matches!(result, Err(BitMapError::AlreadyFree))); } From 2f03ec50edbd962b908bc81e6575eb0f9c730689 Mon Sep 17 00:00:00 2001 From: Raghumani Mehta Date: Mon, 29 Dec 2025 10:41:56 +0530 Subject: [PATCH 06/11] removed broken code --- src/main.rs | 38 +------------------------------------- 1 file changed, 1 insertion(+), 37 deletions(-) diff --git a/src/main.rs b/src/main.rs index b38d979..17a552d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -197,43 +197,7 @@ enum InodeError { } impl FSState { - fn alloc_inode(&mut self, kind: FileType, perm: u16) -> Result { - let ino_idx: usize = match self.inode_bitmap.find_first_free() { - Some(idx) => idx, - None => { - error!("alloc_inode failed: no free inodes"); - return Err(InodeError::NoFreeInodesOnAlloc); - } - }; - - // TODO: add root inode logic - // TODO: Block first two blocks. - // TODO: Reserved ones - // mark inode allocated in bitmap - self.inode_bitmap.map.set(ino_idx, true); - - // The true index is 0, but we use 0 as an invalid ptr so always - // increment when storing ptrs - let ino_id: u64 = (ino_idx + 1) as u64; - self.inodes[ino_idx] = Some(Inode::new(ino_id, kind, perm)); - - Ok(ino_id) - } - - fn fnid_inode_by_id(&self, ino_id: u64) -> Result<&Inode, InodeError> { - if ino_id <= 0 { - return Err(InodeError::InvalidInoId); - } - let ino_idx = (ino_id - 1) as usize; - if ino_idx >= (MAX_NUM_INODES as usize) { - return Err(InodeError::InodeNotFound); - } - - match self.inodes[ino_idx].as_ref() { - Some(inode) => Ok(inode), - None => Err(InodeError::InodeNotFound), - } - } + } // we have to implement Default ourselves here From 68bb40bbd58d49b75b6ce541232d0edd532f93a9 Mon Sep 17 00:00:00 2001 From: Raghumani Mehta Date: Mon, 29 Dec 2025 10:42:15 +0530 Subject: [PATCH 07/11] fixed formatting --- src/main.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index 17a552d..963bc1c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -196,9 +196,7 @@ enum InodeError { InvalidInoId } -impl FSState { - -} +impl FSState {} // we have to implement Default ourselves here // because the Default trait is not implemented for static arrays From 7fdf3810a09bfe314d289f30a19394a1b4d3baba Mon Sep 17 00:00:00 2001 From: Raghumani Mehta Date: Mon, 29 Dec 2025 10:44:45 +0530 Subject: [PATCH 08/11] formatting fix --- src/main.rs | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/src/main.rs b/src/main.rs index 963bc1c..647b207 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,7 +11,7 @@ impl Filesystem for NullFS {} // this includes the space used for the FSMetadata, free object bitmaps, and file data and metadata const FS_SIZE_BYTES: u64 = 1u64 * (0b1 << 30) as u64; // 1 GB const BLK_SIZE_BYTES: u64 = 4096u64; -// 0 -> FSMetadata, 1->InodeBitmap, 2 -> Freeblock bitmap +// 0 -> FSMetadata, 1->InodeBitmap, 2 -> Freeblock bitmap const RESERVED_DATA_BLKS: u32 = 3; const NUM_DATA_BLKS: u32 = (FS_SIZE_BYTES / BLK_SIZE_BYTES) as u32; const FREE_BLK_BMAP_SIZE_BYTES: usize = ((NUM_DATA_BLKS + 7) / 8) as usize; @@ -55,15 +55,14 @@ struct Block { #[derive(Debug)] enum BitMapError { - RestrictedEntry, + RestrictedEntry, AlreadyAlloced, - AlreadyFree + AlreadyFree, } - trait FreeObjectBitmap { - const RESERVED: usize; - const MAX: usize; + const RESERVED: usize; + const MAX: usize; fn map(&mut self) -> &mut BitArray<[u8; N], Lsb0>; @@ -78,12 +77,12 @@ trait FreeObjectBitmap { fn set_alloc(&mut self, idx: usize) -> Result<(), BitMapError> { if idx < Self::RESERVED || idx > Self::MAX { - return Err(BitMapError::RestrictedEntry) - } + return Err(BitMapError::RestrictedEntry); + } if self.map()[idx] == true { error!("The index is already alloced, no change"); - return Err(BitMapError::AlreadyAlloced); - } else { + return Err(BitMapError::AlreadyAlloced); + } else { self.map().set(idx, true); Ok(()) } @@ -91,12 +90,12 @@ trait FreeObjectBitmap { fn set_free(&mut self, idx: usize) -> Result<(), BitMapError> { if idx < Self::RESERVED || idx > Self::MAX { - return Err(BitMapError::RestrictedEntry) - } + return Err(BitMapError::RestrictedEntry); + } if self.map()[idx] == false { error!("The index is already free, no change"); - return Err(BitMapError::AlreadyFree); - } else { + return Err(BitMapError::AlreadyFree); + } else { self.map().set(idx, false); Ok(()) } @@ -116,7 +115,7 @@ impl Default for FreeBlockBitmap { } impl FreeObjectBitmap for FreeBlockBitmap { - const RESERVED: usize = RESERVED_DATA_BLKS as usize; + const RESERVED: usize = RESERVED_DATA_BLKS as usize; const MAX: usize = NUM_DATA_BLKS as usize; fn map(&mut self) -> &mut BitArray<[u8; FREE_BLK_BMAP_SIZE_BYTES], Lsb0> { &mut self.map @@ -193,10 +192,10 @@ struct FSState { enum InodeError { NoFreeInodesOnAlloc, InodeNotFound, - InvalidInoId + InvalidInoId, } -impl FSState {} +impl FSState {} // we have to implement Default ourselves here // because the Default trait is not implemented for static arrays @@ -305,7 +304,6 @@ mod tests { let mut bitmap = FreeInodeBitmap::default(); let result = bitmap.set_free(MAX_NUM_INODES as usize + 1); assert!(matches!(result, Err(BitMapError::RestrictedEntry))); - } #[test] @@ -327,11 +325,11 @@ mod tests { fn test_free_block_bitmap_set_alloc_and_free() { let mut bitmap = FreeBlockBitmap::default(); let idx = RESERVED_DATA_BLKS as usize; - + // Allocate assert!(bitmap.set_alloc(idx).is_ok()); assert_eq!(bitmap.map[idx], true); - + // Free assert!(bitmap.set_free(idx).is_ok()); assert_eq!(bitmap.map[idx], false); From 8e8d5e09d8739350a32164320558cd56a8262ac5 Mon Sep 17 00:00:00 2001 From: Raghumani Mehta <115026448+raghumanimehta@users.noreply.github.com> Date: Tue, 30 Dec 2025 13:23:37 +0530 Subject: [PATCH 09/11] Rename free_blk_bitmap to blk_bitmap --- src/main.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index 647b207..7bf36bc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -184,7 +184,7 @@ struct FSState { metadata: FSMetadata, inode_bitmap: FreeInodeBitmap, inodes: [Option; MAX_NUM_INODES as usize], - free_blk_bitmap: FreeBlockBitmap, + blk_bitmap : FreeBlockBitmap, blks: [Option; NUM_DATA_BLKS as usize], } @@ -205,14 +205,14 @@ impl Default for FSState { let metadata = FSMetadata::default(); let inode_bitmap = FreeInodeBitmap::default(); let inodes = [None; MAX_NUM_INODES as usize]; - let free_blk_bitmap = FreeBlockBitmap::default(); + let blk_bitmap = FreeBlockBitmap::default(); let blks = [None; NUM_DATA_BLKS as usize]; Self { metadata, inode_bitmap, inodes, - free_blk_bitmap, + blk_bitmap , blks, } } From 4f15c5dd1cec83fba6fc13f994f82f2bf8030ed8 Mon Sep 17 00:00:00 2001 From: Raghumani Mehta Date: Tue, 30 Dec 2025 13:28:35 +0530 Subject: [PATCH 10/11] cargo fmt --- src/main.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index 7bf36bc..9abfe71 100644 --- a/src/main.rs +++ b/src/main.rs @@ -184,7 +184,7 @@ struct FSState { metadata: FSMetadata, inode_bitmap: FreeInodeBitmap, inodes: [Option; MAX_NUM_INODES as usize], - blk_bitmap : FreeBlockBitmap, + blk_bitmap: FreeBlockBitmap, blks: [Option; NUM_DATA_BLKS as usize], } @@ -205,14 +205,14 @@ impl Default for FSState { let metadata = FSMetadata::default(); let inode_bitmap = FreeInodeBitmap::default(); let inodes = [None; MAX_NUM_INODES as usize]; - let blk_bitmap = FreeBlockBitmap::default(); + let blk_bitmap = FreeBlockBitmap::default(); let blks = [None; NUM_DATA_BLKS as usize]; Self { metadata, inode_bitmap, inodes, - blk_bitmap , + blk_bitmap, blks, } } From 7b69c9cbf2ebb6a9f43e73705c2397683a27abee Mon Sep 17 00:00:00 2001 From: Raghumani Mehta Date: Tue, 30 Dec 2025 13:35:40 +0530 Subject: [PATCH 11/11] changed the indexing bug in object bitmap and added a test case for it --- src/main.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 9abfe71..47762bc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -76,7 +76,7 @@ trait FreeObjectBitmap { } fn set_alloc(&mut self, idx: usize) -> Result<(), BitMapError> { - if idx < Self::RESERVED || idx > Self::MAX { + if idx < Self::RESERVED || idx >= Self::MAX { return Err(BitMapError::RestrictedEntry); } if self.map()[idx] == true { @@ -89,7 +89,7 @@ trait FreeObjectBitmap { } fn set_free(&mut self, idx: usize) -> Result<(), BitMapError> { - if idx < Self::RESERVED || idx > Self::MAX { + if idx < Self::RESERVED || idx >= Self::MAX { return Err(BitMapError::RestrictedEntry); } if self.map()[idx] == false { @@ -334,4 +334,17 @@ mod tests { assert!(bitmap.set_free(idx).is_ok()); assert_eq!(bitmap.map[idx], false); } + + #[test] + fn test_free_block_bitmap_max() { + let mut bitmap = FreeBlockBitmap::default(); + let idx = NUM_DATA_BLKS as usize; + let idx2 = 4 as usize; + + assert!(bitmap.set_alloc(idx2).is_ok()); + assert_eq!(bitmap.map[idx2], true); + + let result = bitmap.set_alloc(idx); + assert!(matches!(result, Err(BitMapError::RestrictedEntry))); + } }