11use super :: Ext2Error ;
22use super :: cache:: BlockCache ;
3- use super :: ondisk:: Inode ;
3+ use super :: ext2_alloc;
4+ use super :: ondisk:: { Inode , Superblock } ;
45use super :: types:: { BlockNum , FileBlock } ;
56use 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
2621pub 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.
6761fn 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.
7871fn 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.
115105pub 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) ;
0 commit comments