Skip to content

Commit 97feda7

Browse files
committed
ext2: delete legacy.rs, migrate all operations to new modular Ext2Fs
Remove the 1226-line legacy.rs entirely. All filesystem operations now go through the new Ext2Fs struct in mod.rs which delegates to the type-safe submodules (cache, blockmap, dir, file, alloc). Key changes: - Ext2Fs::read_inode/write_inode use the block cache (no stack buffers) - Ext2Fs::write_file delegates to file::write_file with superblock passed directly (no closure-based allocation, avoids borrow conflicts) - Ext2Fs::create_inode_entry orchestrates inode+block allocation and directory entry append using decomposed field borrows - blockmap::ensure_data_block takes &mut Superblock directly instead of alloc_fn closure, calling ext2_alloc internally - dir::append_dir_entry takes &mut Superblock instead of alloc_fn - Removed ops.rs (functionality absorbed into Ext2Fs methods) - ext2_vfs.rs updated for InodeNum newtype (.raw() conversions) Net: -1170 lines. All 2262 tests pass.
1 parent b0ebc9f commit 97feda7

File tree

7 files changed

+541
-1711
lines changed

7 files changed

+541
-1711
lines changed

fs/src/ext2/blockmap.rs

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use super::Ext2Error;
22
use super::cache::BlockCache;
3-
use super::ondisk::Inode;
3+
use super::ext2_alloc;
4+
use super::ondisk::{Inode, Superblock};
45
use super::types::{BlockNum, FileBlock};
56
use crate::blockdev::BlockDevice;
67

@@ -17,12 +18,6 @@ pub struct BlockPath {
1718
}
1819

1920
/// Convert a logical file block to a chain of offsets into the indirect tree.
20-
///
21-
/// For 4KB blocks (ptrs_per_block=1024):
22-
/// direct: [0..12) -> depth=1
23-
/// single: [12..1036) -> depth=2
24-
/// double: [1036..1049612) -> depth=3
25-
/// triple: [1049612..~1B) -> depth=4
2621
pub fn block_to_path(file_block: FileBlock, ptrs_per_block: u32) -> Result<BlockPath, Ext2Error> {
2722
let fb = file_block.raw();
2823
let n = ptrs_per_block;
@@ -63,7 +58,6 @@ pub fn block_to_path(file_block: FileBlock, ptrs_per_block: u32) -> Result<Block
6358
Err(Ext2Error::InvalidBlock)
6459
}
6560

66-
/// Read a u32 block pointer from an indirect block at the given index.
6761
fn read_ptr(data: &[u8], idx: u32) -> BlockNum {
6862
let off = idx as usize * 4;
6963
BlockNum(u32::from_le_bytes([
@@ -74,7 +68,6 @@ fn read_ptr(data: &[u8], idx: u32) -> BlockNum {
7468
]))
7569
}
7670

77-
/// Write a u32 block pointer into an indirect block at the given index.
7871
fn write_ptr(data: &mut [u8], idx: u32, block: BlockNum) {
7972
let off = idx as usize * 4;
8073
data[off..off + 4].copy_from_slice(&block.raw().to_le_bytes());
@@ -91,13 +84,11 @@ pub fn map_block(
9184
) -> Result<BlockNum, Ext2Error> {
9285
let path = block_to_path(file_block, ptrs_per_block)?;
9386

94-
// First offset is always an index into inode.block[]
9587
let mut current = inode.block[path.offsets[0] as usize];
9688
if !current.is_valid() {
9789
return Ok(BlockNum::ZERO);
9890
}
9991

100-
// Walk through indirect blocks
10192
for level in 1..path.depth as usize {
10293
let block = cache.get(current, device)?;
10394
current = read_ptr(block.data(), path.offsets[level]);
@@ -110,41 +101,36 @@ pub fn map_block(
110101
}
111102

112103
/// Ensure a data block exists at the given file block offset.
113-
/// Allocates new blocks (including intermediate indirect blocks) as needed.
114-
/// Returns (physical_block, was_newly_allocated).
104+
/// Allocates blocks internally via the alloc module — no closure needed.
115105
pub fn ensure_data_block(
116106
inode: &mut Inode,
117107
file_block: FileBlock,
118108
ptrs_per_block: u32,
119109
cache: &mut BlockCache,
120110
device: &dyn BlockDevice,
121-
alloc_fn: &mut dyn FnMut() -> Result<BlockNum, Ext2Error>,
111+
superblock: &mut Superblock,
112+
block_size: u32,
122113
) -> Result<(BlockNum, bool), Ext2Error> {
123114
let path = block_to_path(file_block, ptrs_per_block)?;
124115

125116
if path.depth == 1 {
126-
// Direct block
127117
let idx = path.offsets[0] as usize;
128118
if inode.block[idx].is_valid() {
129119
return Ok((inode.block[idx], false));
130120
}
131-
let new_block = alloc_fn()?;
132-
let _zero = cache.get_zero(new_block, device)?;
121+
let new_block = ext2_alloc::allocate_block(superblock, cache, device, block_size)?;
122+
drop(cache.get_zero(new_block, device)?);
133123
inode.block[idx] = new_block;
134124
return Ok((new_block, true));
135125
}
136126

137-
// For indirect paths (depth 2, 3, or 4):
138-
// Ensure the top-level indirect block exists in inode.block[]
139127
let top_idx = path.offsets[0] as usize;
140128
if !inode.block[top_idx].is_valid() {
141-
let new_block = alloc_fn()?;
142-
// Zero-fill and immediately release the guard
129+
let new_block = ext2_alloc::allocate_block(superblock, cache, device, block_size)?;
143130
drop(cache.get_zero(new_block, device)?);
144131
inode.block[top_idx] = new_block;
145132
}
146133

147-
// Walk and allocate intermediate indirect blocks
148134
let mut current_indirect = inode.block[top_idx];
149135
for level in 1..path.depth as usize - 1 {
150136
let child = {
@@ -154,15 +140,14 @@ pub fn ensure_data_block(
154140
if child.is_valid() {
155141
current_indirect = child;
156142
} else {
157-
let new_block = alloc_fn()?;
143+
let new_block = ext2_alloc::allocate_block(superblock, cache, device, block_size)?;
158144
drop(cache.get_zero(new_block, device)?);
159145
let mut parent = cache.get(current_indirect, device)?;
160146
write_ptr(parent.data_mut(), path.offsets[level], new_block);
161147
current_indirect = new_block;
162148
}
163149
}
164150

165-
// Final level: the data block pointer
166151
let data_idx = path.offsets[path.depth as usize - 1];
167152
let existing = {
168153
let block = cache.get(current_indirect, device)?;
@@ -173,7 +158,7 @@ pub fn ensure_data_block(
173158
return Ok((existing, false));
174159
}
175160

176-
let new_data = alloc_fn()?;
161+
let new_data = ext2_alloc::allocate_block(superblock, cache, device, block_size)?;
177162
drop(cache.get_zero(new_data, device)?);
178163
let mut parent = cache.get(current_indirect, device)?;
179164
write_ptr(parent.data_mut(), data_idx, new_data);

fs/src/ext2/dir.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
use super::Ext2Error;
22
use super::blockmap;
33
use super::cache::BlockCache;
4-
use super::ondisk::{DIR_ENTRY_HEADER_SIZE, DirEntry, Inode, dir_entry_size, write_dir_entry};
5-
use super::types::{BlockNum, FileBlock, InodeNum};
4+
use super::ondisk::{
5+
DIR_ENTRY_HEADER_SIZE, DirEntry, Inode, Superblock, dir_entry_size, write_dir_entry,
6+
};
7+
use super::types::{FileBlock, InodeNum};
68
use crate::blockdev::BlockDevice;
79
use core::cmp;
810

@@ -202,7 +204,7 @@ pub fn append_dir_entry(
202204
device: &dyn BlockDevice,
203205
ptrs_per_block: u32,
204206
block_size: u32,
205-
alloc_fn: &mut dyn FnMut() -> Result<BlockNum, Ext2Error>,
207+
superblock: &mut Superblock,
206208
) -> Result<(), Ext2Error> {
207209
let needed = dir_entry_size(name.len());
208210
let bs = block_size as usize;
@@ -270,19 +272,19 @@ pub fn append_dir_entry(
270272
offset += block_size;
271273
}
272274

273-
// No space found: allocate a new block
274-
let new_block = alloc_fn()?;
275+
// No space found: allocate a new block and add to parent's block map
275276
let file_block = FileBlock(parent_inode.size / block_size);
276-
277-
// Store the new block pointer in the inode's block map
278277
blockmap::ensure_data_block(
279278
parent_inode,
280279
file_block,
281280
ptrs_per_block,
282281
cache,
283282
device,
284-
&mut || Ok(new_block),
283+
superblock,
284+
block_size,
285285
)?;
286+
// Re-map to get the newly allocated block number
287+
let new_block = blockmap::map_block(parent_inode, file_block, ptrs_per_block, cache, device)?;
286288

287289
// Write the new entry into the fresh block
288290
let mut block = cache.get_zero(new_block, device)?;

0 commit comments

Comments
 (0)