Skip to content

Commit

Permalink
Fix block bitmap area calculation (#638)
Browse files Browse the repository at this point in the history
* Fix block bitmap area calculation

* Update documentation

* Take reserved blocks into account for disk usage

* Fix out of space errors

* Fix off by one errors

* Remove pub attributes
  • Loading branch information
vinc authored Aug 11, 2024
1 parent dbb12d9 commit 9e05ed4
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 18 deletions.
4 changes: 2 additions & 2 deletions doc/filesystem.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ A hard drive is separated in blocks of 512 bytes, grouped into 4 areas:
+------------+
| Superblock | (2 blocks)
+------------+
| Bitmap | (n / (8 * 512) blocks)
| Bitmap | (n blocks)
+------------+
| Data | (n blocks)
| Data | (n * 512 * 8 blocks)
+------------+

The first area contains the bootloader and the kernel, the second is a
Expand Down
4 changes: 4 additions & 0 deletions src/sys/fs/bitmap_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ impl BitmapBlock {

pub fn next_free_addr() -> Option<u32> {
let sb = SuperBlock::read();
if sb.alloc_count() == sb.block_count() {
return None;
}

let n = sb.block_size();
let m = sb.block_count() / n / 8;
for i in 0..m {
Expand Down
9 changes: 6 additions & 3 deletions src/sys/fs/dir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,15 +120,18 @@ impl Dir {
if entry_len > space_left {
match entries.block.alloc_next() {
None => return None, // Disk is full
Some(new_block) => {
entries.block = new_block;
Some(block) => {
entries.block = block;
entries.block_offset = 0;
}
}
}

// Create a new entry
let entry_block = LinkedBlock::alloc().unwrap();
let entry_block = match LinkedBlock::alloc() {
None => return None,
Some(block) => block,
};
let entry_kind = kind as u8;
let entry_addr = entry_block.addr();
let entry_size = 0u32;
Expand Down
6 changes: 3 additions & 3 deletions src/sys/fs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use super_block::SuperBlock;

use alloc::string::{String, ToString};

pub const VERSION: u8 = 1;
pub const VERSION: u8 = 2;

// TODO: Move that to API
#[derive(Clone, Copy)]
Expand Down Expand Up @@ -157,11 +157,11 @@ pub fn canonicalize(path: &str) -> Result<String, ()> {
}

pub fn disk_size() -> usize {
(SuperBlock::read().block_count as usize) * BLOCK_SIZE
(SuperBlock::read().block_count() as usize) * BLOCK_SIZE
}

pub fn disk_used() -> usize {
(SuperBlock::read().alloc_count as usize) * BLOCK_SIZE
(SuperBlock::read().alloc_count() as usize) * BLOCK_SIZE
}

pub fn disk_free() -> usize {
Expand Down
42 changes: 32 additions & 10 deletions src/sys/fs/super_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ pub struct SuperBlock {
signature: &'static [u8; 8],
version: u8,
block_size: u32,
pub block_count: u32,
pub alloc_count: u32,
block_count: u32,
alloc_count: u32,
}

impl SuperBlock {
Expand All @@ -27,13 +27,18 @@ impl SuperBlock {

pub fn new() -> Option<Self> {
if let Some(ref dev) = *super::block_device::BLOCK_DEVICE.lock() {
Some(Self {
let mut sb = Self {
signature: SIGNATURE,
version: super::VERSION,
block_size: dev.block_size() as u32,
block_count: dev.block_count() as u32,
alloc_count: 0,
})
};

// Reserved blocks
sb.alloc_count = sb.data_area();

Some(sb)
} else {
None
}
Expand Down Expand Up @@ -78,16 +83,33 @@ impl SuperBlock {
self.block_count
}

pub fn alloc_count(&self) -> u32 {
self.alloc_count
}

pub fn bitmap_area(&self) -> u32 {
SUPERBLOCK_ADDR + 2
}

pub fn data_area(&self) -> u32 {
let bs = super::BITMAP_SIZE as u32;
let total = self.block_count;
let offset = self.bitmap_area();
let rest = (total - offset) * bs / (bs + 1);
self.bitmap_area() + rest / bs
let s = self.block_size * 8;
let n = self.block_count;
let a = self.bitmap_area();

if self.version == 1 {
a + ((n - a) / (s + 1)) // Incorrect formula fixed in v2
} else {
let mut p; // Previous bitmap count
let mut b = 0; // Bitmap count
loop {
p = b;
b = (n - (a + b) + s - 1) / s;
if b == p {
break;
}
}
a + b
}
}
}

Expand All @@ -99,6 +121,6 @@ pub fn inc_alloc_count() {

pub fn dec_alloc_count() {
let mut sb = SuperBlock::read();
sb.alloc_count -= 1;
sb.alloc_count -= 1; // FIXME: Use saturating substraction
sb.write();
}

0 comments on commit 9e05ed4

Please sign in to comment.