@@ -8,8 +8,14 @@ use alloc::sync::Arc;
88use alloc:: vec:: Vec ;
99
1010const EFS_MAGIC : u32 = 0x3b800001 ;
11- const INODE_DIRECT_COUNT : usize = 60 ;
11+ const INODE_DIRECT_COUNT : usize = 28 ;
1212const NAME_LENGTH_LIMIT : usize = 27 ;
13+ const INODE_INDIRECT1_COUNT : usize = BLOCK_SZ / 4 ;
14+ const INODE_INDIRECT2_COUNT : usize = INODE_INDIRECT1_COUNT * INODE_INDIRECT1_COUNT ;
15+ const DIRECT_BOUND : usize = INODE_DIRECT_COUNT ;
16+ const INDIRECT1_BOUND : usize = DIRECT_BOUND + INODE_INDIRECT1_COUNT ;
17+ #[ allow( unused) ]
18+ const INDIRECT2_BOUND : usize = INDIRECT1_BOUND + INODE_INDIRECT2_COUNT ;
1319
1420#[ repr( C ) ]
1521pub struct SuperBlock {
@@ -76,11 +82,11 @@ pub struct DiskInode {
7682}
7783
7884impl DiskInode {
79- /// indirect1 block is allocated when the file is created .
80- pub fn initialize ( & mut self , type_ : DiskInodeType , indirect1 : u32 ) {
85+ /// indirect1 and indirect2 block are allocated only when they are needed .
86+ pub fn initialize ( & mut self , type_ : DiskInodeType ) {
8187 self . size = 0 ;
8288 self . direct . iter_mut ( ) . for_each ( |v| * v = 0 ) ;
83- self . indirect1 = indirect1 ;
89+ self . indirect1 = 0 ;
8490 self . indirect2 = 0 ;
8591 self . type_ = type_;
8692 }
@@ -91,57 +97,146 @@ impl DiskInode {
9197 pub fn is_file ( & self ) -> bool {
9298 self . type_ == DiskInodeType :: File
9399 }
94- pub fn blocks ( & self ) -> u32 {
95- Self :: _blocks ( self . size )
100+ /// Return block number correspond to size.
101+ pub fn data_blocks ( & self ) -> u32 {
102+ Self :: _data_blocks ( self . size )
96103 }
97- fn _blocks ( size : u32 ) -> u32 {
104+ fn _data_blocks ( size : u32 ) -> u32 {
98105 ( size + BLOCK_SZ as u32 - 1 ) / BLOCK_SZ as u32
99106 }
107+ /// Return number of blocks needed include indirect1/2.
108+ pub fn total_blocks ( size : u32 ) -> u32 {
109+ let data_blocks = Self :: _data_blocks ( size) as usize ;
110+ let mut total = data_blocks as usize ;
111+ // indirect1
112+ if data_blocks > INODE_DIRECT_COUNT {
113+ total += 1 ;
114+ }
115+ // indirect2
116+ if data_blocks > INDIRECT1_BOUND {
117+ total += 1 ;
118+ // sub indirect1
119+ total += ( data_blocks - INDIRECT1_BOUND + INODE_INDIRECT1_COUNT - 1 ) / INODE_INDIRECT1_COUNT ;
120+ }
121+ total as u32
122+ }
123+ pub fn blocks_num_needed ( & self , new_size : u32 ) -> u32 {
124+ assert ! ( new_size >= self . size) ;
125+ Self :: total_blocks ( new_size) - Self :: total_blocks ( self . size )
126+ }
100127 pub fn get_block_id ( & self , inner_id : u32 , block_device : & Arc < dyn BlockDevice > ) -> u32 {
101128 let inner_id = inner_id as usize ;
102129 if inner_id < INODE_DIRECT_COUNT {
103130 self . direct [ inner_id]
104- } else {
105- // only support indirect1 now
131+ } else if inner_id < INDIRECT1_BOUND {
106132 get_block_cache ( self . indirect1 as usize , Arc :: clone ( block_device) )
107133 . lock ( )
108134 . read ( 0 , |indirect_block : & IndirectBlock | {
109135 indirect_block[ inner_id - INODE_DIRECT_COUNT ]
110136 } )
137+ } else {
138+ let last = inner_id - INDIRECT1_BOUND ;
139+ let indirect1 = get_block_cache (
140+ self . indirect2 as usize ,
141+ Arc :: clone ( block_device)
142+ )
143+ . lock ( )
144+ . read ( 0 , |indirect2 : & IndirectBlock | {
145+ indirect2[ last / INODE_INDIRECT1_COUNT ]
146+ } ) ;
147+ get_block_cache (
148+ indirect1 as usize ,
149+ Arc :: clone ( block_device)
150+ )
151+ . lock ( )
152+ . read ( 0 , |indirect1 : & IndirectBlock | {
153+ indirect1[ last % INODE_INDIRECT1_COUNT ]
154+ } )
111155 }
112156 }
113- pub fn blocks_num_needed ( & self , new_size : u32 ) -> u32 {
114- assert ! ( new_size >= self . size) ;
115- Self :: _blocks ( new_size) - self . blocks ( )
116- }
117157 pub fn increase_size (
118158 & mut self ,
119159 new_size : u32 ,
120160 new_blocks : Vec < u32 > ,
121161 block_device : & Arc < dyn BlockDevice > ,
122162 ) {
123- assert_eq ! ( new_blocks. len( ) as u32 , self . blocks_num_needed( new_size) ) ;
124- let last_blocks = self . blocks ( ) ;
163+ let mut current_blocks = self . data_blocks ( ) ;
125164 self . size = new_size;
126- let current_blocks = self . blocks ( ) ;
165+ let mut total_blocks = self . data_blocks ( ) ;
166+ let mut new_blocks = new_blocks. into_iter ( ) ;
167+ // fill direct
168+ while current_blocks < total_blocks. min ( INODE_DIRECT_COUNT as u32 ) {
169+ self . direct [ current_blocks as usize ] = new_blocks. next ( ) . unwrap ( ) ;
170+ current_blocks += 1 ;
171+ }
172+ // alloc indirect1
173+ if total_blocks > INODE_DIRECT_COUNT as u32 {
174+ if current_blocks == INODE_DIRECT_COUNT as u32 {
175+ self . indirect1 = new_blocks. next ( ) . unwrap ( ) ;
176+ }
177+ current_blocks -= INODE_DIRECT_COUNT as u32 ;
178+ total_blocks -= INODE_DIRECT_COUNT as u32 ;
179+ } else {
180+ return ;
181+ }
182+ // fill indirect1
127183 get_block_cache (
128184 self . indirect1 as usize ,
129185 Arc :: clone ( block_device)
130186 )
131187 . lock ( )
132- . modify ( 0 , |indirect_block : & mut IndirectBlock | {
133- for i in 0 ..current_blocks - last_blocks {
134- let inner_id = ( last_blocks + i) as usize ;
135- let new_block = new_blocks[ i as usize ] ;
136- if inner_id < INODE_DIRECT_COUNT {
137- self . direct [ inner_id] = new_block;
138- } else {
139- indirect_block[ inner_id - INODE_DIRECT_COUNT ] = new_block;
140- }
188+ . modify ( 0 , |indirect1 : & mut IndirectBlock | {
189+ while current_blocks < total_blocks. min ( INODE_INDIRECT1_COUNT as u32 ) {
190+ indirect1[ current_blocks as usize ] = new_blocks. next ( ) . unwrap ( ) ;
191+ current_blocks += 1 ;
141192 }
142193 } ) ;
194+ // alloc indirect2
195+ if total_blocks > INODE_INDIRECT1_COUNT as u32 {
196+ if current_blocks == INODE_INDIRECT1_COUNT as u32 {
197+ self . indirect2 = new_blocks. next ( ) . unwrap ( ) ;
198+ }
199+ current_blocks -= INODE_INDIRECT1_COUNT as u32 ;
200+ total_blocks -= INODE_INDIRECT1_COUNT as u32 ;
201+ } else {
202+ return ;
203+ }
204+ // fill indirect2 from (a0, b0) -> (a1, b1)
205+ let mut a0 = current_blocks as usize / INODE_INDIRECT1_COUNT ;
206+ let mut b0 = current_blocks as usize % INODE_INDIRECT1_COUNT ;
207+ let a1 = total_blocks as usize / INODE_INDIRECT1_COUNT ;
208+ let b1 = total_blocks as usize % INODE_INDIRECT1_COUNT ;
209+ // alloc low-level indirect1
210+ get_block_cache (
211+ self . indirect2 as usize ,
212+ Arc :: clone ( block_device)
213+ )
214+ . lock ( )
215+ . modify ( 0 , |indirect2 : & mut IndirectBlock | {
216+ while ( a0 < a1) || ( a0 == a1 && b0 < b1) {
217+ if b0 == 0 {
218+ indirect2[ a0] = new_blocks. next ( ) . unwrap ( ) ;
219+ }
220+ // fill current
221+ get_block_cache (
222+ indirect2[ a0] as usize ,
223+ Arc :: clone ( block_device)
224+ )
225+ . lock ( )
226+ . modify ( 0 , |indirect1 : & mut IndirectBlock | {
227+ indirect1[ b0] = new_blocks. next ( ) . unwrap ( ) ;
228+ } ) ;
229+ // move to next
230+ b0 += 1 ;
231+ if b0 == INODE_INDIRECT1_COUNT {
232+ b0 = 0 ;
233+ a0 += 1 ;
234+ }
235+ }
236+ } ) ;
143237 }
144- /// Clear size to zero and return blocks that should be deallocated.
238+
239+ /*
145240 pub fn clear_size(&mut self, block_device: &Arc<dyn BlockDevice>) -> Vec<u32> {
146241 let mut v: Vec<u32> = Vec::new();
147242 let blocks = self.blocks() as usize;
@@ -165,6 +260,97 @@ impl DiskInode {
165260 }
166261 v
167262 }
263+ */
264+
265+ /// Clear size to zero and return blocks that should be deallocated.
266+ ///
267+ /// We will clear the block contents to zero later.
268+ pub fn clear_size ( & mut self , block_device : & Arc < dyn BlockDevice > ) -> Vec < u32 > {
269+ let mut v: Vec < u32 > = Vec :: new ( ) ;
270+ let mut data_blocks = self . data_blocks ( ) as usize ;
271+ self . size = 0 ;
272+ let mut current_blocks = 0usize ;
273+ // direct
274+ while current_blocks < data_blocks. min ( INODE_DIRECT_COUNT ) {
275+ v. push ( self . direct [ current_blocks] ) ;
276+ self . direct [ current_blocks] = 0 ;
277+ current_blocks += 1 ;
278+ }
279+ // indirect1 block
280+ if data_blocks > INODE_DIRECT_COUNT {
281+ v. push ( self . indirect1 ) ;
282+ data_blocks -= INODE_DIRECT_COUNT ;
283+ current_blocks = 0 ;
284+ } else {
285+ return v;
286+ }
287+ // indirect1
288+ get_block_cache (
289+ self . indirect1 as usize ,
290+ Arc :: clone ( block_device) ,
291+ )
292+ . lock ( )
293+ . modify ( 0 , |indirect1 : & mut IndirectBlock | {
294+ while current_blocks < data_blocks. min ( INODE_INDIRECT1_COUNT ) {
295+ v. push ( indirect1[ current_blocks] ) ;
296+ //indirect1[current_blocks] = 0;
297+ current_blocks += 1 ;
298+ }
299+ } ) ;
300+ self . indirect1 = 0 ;
301+ // indirect2 block
302+ if data_blocks > INODE_INDIRECT1_COUNT {
303+ v. push ( self . indirect2 ) ;
304+ data_blocks -= INODE_INDIRECT1_COUNT ;
305+ } else {
306+ return v;
307+ }
308+ // indirect2
309+ assert ! ( data_blocks <= INODE_INDIRECT2_COUNT ) ;
310+ let a1 = data_blocks / INODE_INDIRECT1_COUNT ;
311+ let b1 = data_blocks % INODE_INDIRECT1_COUNT ;
312+ get_block_cache (
313+ self . indirect2 as usize ,
314+ Arc :: clone ( block_device) ,
315+ )
316+ . lock ( )
317+ . modify ( 0 , |indirect2 : & mut IndirectBlock | {
318+ // full indirect1 blocks
319+ for i in 0 ..a1 {
320+ v. push ( indirect2[ i] ) ;
321+ get_block_cache (
322+ indirect2[ i] as usize ,
323+ Arc :: clone ( block_device) ,
324+ )
325+ . lock ( )
326+ . modify ( 0 , |indirect1 : & mut IndirectBlock | {
327+ for j in 0 ..INODE_INDIRECT1_COUNT {
328+ v. push ( indirect1[ j] ) ;
329+ //indirect1[j] = 0;
330+ }
331+ } ) ;
332+ //indirect2[i] = 0;
333+ }
334+ // last indirect1 block
335+ if b1 > 0 {
336+ v. push ( indirect2[ a1] ) ;
337+ get_block_cache (
338+ indirect2[ a1] as usize ,
339+ Arc :: clone ( block_device) ,
340+ )
341+ . lock ( )
342+ . modify ( 0 , |indirect1 : & mut IndirectBlock | {
343+ for j in 0 ..b1 {
344+ v. push ( indirect1[ j] ) ;
345+ //indirect1[j] = 0;
346+ }
347+ } ) ;
348+ //indirect2[a1] = 0;
349+ }
350+ } ) ;
351+ self . indirect2 = 0 ;
352+ v
353+ }
168354 pub fn read_at (
169355 & self ,
170356 offset : usize ,
0 commit comments