5
5
* you may not use this file except in compliance with the License.
6
6
* You may obtain a copy of the License at
7
7
*
8
- * http://www.apache.org/licenses/LICENSE-2.0
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
9
*
10
10
* Unless required by applicable law or agreed to in writing, software
11
11
* distributed under the License is distributed on an "AS IS" BASIS,
22
22
#include <stdio.h>
23
23
#include <stdlib.h>
24
24
25
+ struct region {
26
+ u32 block ;
27
+ u32 len ;
28
+ int bg ;
29
+ struct region * next ;
30
+ struct region * prev ;
31
+ };
32
+
33
+ struct block_group_info {
34
+ u32 first_block ;
35
+ int header_blocks ;
36
+ int data_blocks_used ;
37
+ int has_superblock ;
38
+ u8 * bitmaps ;
39
+ u8 * block_bitmap ;
40
+ u8 * inode_bitmap ;
41
+ u8 * inode_table ;
42
+ u32 free_blocks ;
43
+ u32 first_free_block ;
44
+ u32 free_inodes ;
45
+ u32 first_free_inode ;
46
+ u16 flags ;
47
+ u16 used_dirs ;
48
+ };
49
+
25
50
struct xattr_list_element {
26
51
struct ext4_inode * inode ;
27
52
struct ext4_xattr_header * header ;
@@ -81,7 +106,7 @@ static void region_list_remove(struct region_list *list, struct region *reg)
81
106
reg -> prev = NULL ;
82
107
}
83
108
84
- void region_list_append (struct region_list * list , struct region * reg )
109
+ static void region_list_append (struct region_list * list , struct region * reg )
85
110
{
86
111
if (list -> first == NULL ) {
87
112
list -> first = reg ;
@@ -119,12 +144,11 @@ static void dump_region_lists(struct block_allocation *alloc) {
119
144
void print_blocks (FILE * f , struct block_allocation * alloc )
120
145
{
121
146
struct region * reg ;
122
- fputc (' ' , f );
123
147
for (reg = alloc -> list .first ; reg ; reg = reg -> next ) {
124
148
if (reg -> len == 1 ) {
125
- fprintf (f , "%d, " , reg -> block );
149
+ fprintf (f , " %d " , reg -> block );
126
150
} else {
127
- fprintf (f , "%d-%d, " , reg -> block , reg -> block + reg -> len - 1 );
151
+ fprintf (f , " %d-%d" , reg -> block , reg -> block + reg -> len - 1 );
128
152
}
129
153
}
130
154
fputc ('\n' , f );
@@ -186,23 +210,26 @@ static int reserve_blocks(struct block_group_info *bg, u32 start, u32 num)
186
210
unsigned int i = 0 ;
187
211
188
212
u32 block = start ;
213
+ if (num > bg -> free_blocks )
214
+ return -1 ;
215
+
189
216
for (i = 0 ; i < num && block % 8 != 0 ; i ++ , block ++ ) {
190
217
if (bitmap_set_bit (bg -> block_bitmap , block )) {
191
- error ("attempted to reserve already reserved block %d and num is %d" , block , num );
218
+ error ("attempted to reserve already reserved block" );
192
219
return -1 ;
193
220
}
194
221
}
195
222
196
223
for (; i + 8 <= (num & ~7 ); i += 8 , block += 8 ) {
197
224
if (bitmap_set_8_bits (bg -> block_bitmap , block )) {
198
- error ("attempted to reserve already reserved block %d and num is %d" , block , num );
225
+ error ("attempted to reserve already reserved block" );
199
226
return -1 ;
200
227
}
201
228
}
202
229
203
230
for (; i < num ; i ++ , block ++ ) {
204
231
if (bitmap_set_bit (bg -> block_bitmap , block )) {
205
- error ("attempted to reserve already reserved block %d and num is %d" , block , num );
232
+ error ("attempted to reserve already reserved block" );
206
233
return -1 ;
207
234
}
208
235
}
@@ -282,24 +309,13 @@ static void init_bg(struct block_group_info *bg, unsigned int i)
282
309
bg -> first_free_inode = 1 ;
283
310
bg -> flags = 0 ;
284
311
285
- bg -> chunk_count = 0 ;
286
- bg -> max_chunk_count = 1 ;
287
- bg -> chunks = (struct region * ) calloc (bg -> max_chunk_count , sizeof (struct region ));
288
-
289
312
if (reserve_blocks (bg , bg -> first_free_block , bg -> header_blocks ) < 0 )
290
313
error ("failed to reserve %u blocks in block group %u\n" , bg -> header_blocks , i );
291
- // Add empty starting delimiter chunk
292
- reserve_bg_chunk (i , bg -> first_free_block , 0 );
293
314
294
315
if (bg -> first_block + info .blocks_per_group > aux_info .len_blocks ) {
295
316
u32 overrun = bg -> first_block + info .blocks_per_group - aux_info .len_blocks ;
296
317
reserve_blocks (bg , info .blocks_per_group - overrun , overrun );
297
- // Add empty ending delimiter chunk
298
- reserve_bg_chunk (i , info .blocks_per_group - overrun , 0 );
299
- } else {
300
- reserve_bg_chunk (i , info .blocks_per_group - 1 , 0 );
301
318
}
302
-
303
319
}
304
320
305
321
void block_allocator_init ()
@@ -325,78 +341,73 @@ void block_allocator_free()
325
341
free (aux_info .bgs );
326
342
}
327
343
344
+ static u32 ext4_allocate_blocks_from_block_group (u32 len , int bg_num )
345
+ {
346
+ if (get_free_blocks (bg_num ) < len )
347
+ return EXT4_ALLOCATE_FAILED ;
348
+
349
+ u32 block = aux_info .bgs [bg_num ].first_free_block ;
350
+ struct block_group_info * bg = & aux_info .bgs [bg_num ];
351
+ if (reserve_blocks (bg , bg -> first_free_block , len ) < 0 ) {
352
+ error ("failed to reserve %u blocks in block group %u\n" , len , bg_num );
353
+ return EXT4_ALLOCATE_FAILED ;
354
+ }
355
+
356
+ aux_info .bgs [bg_num ].data_blocks_used += len ;
357
+
358
+ return bg -> first_block + block ;
359
+ }
360
+
328
361
/* Allocate a single block and return its block number */
329
362
u32 allocate_block ()
330
363
{
331
- u32 block ;
332
- struct block_allocation * blk_alloc = allocate_blocks (1 );
333
- if (!blk_alloc ) {
334
- return EXT4_ALLOCATE_FAILED ;
364
+ unsigned int i ;
365
+ for (i = 0 ; i < aux_info .groups ; i ++ ) {
366
+ u32 block = ext4_allocate_blocks_from_block_group (1 , i );
367
+
368
+ if (block != EXT4_ALLOCATE_FAILED )
369
+ return block ;
335
370
}
336
- block = blk_alloc -> list .first -> block ;
337
- free_alloc (blk_alloc );
338
- return block ;
371
+
372
+ return EXT4_ALLOCATE_FAILED ;
339
373
}
340
374
341
375
static struct region * ext4_allocate_best_fit_partial (u32 len )
342
376
{
343
- unsigned int i , j ;
344
- unsigned int found_bg = 0 , found_prev_chunk = 0 , found_block = 0 ;
345
- u32 found_allocate_len = 0 ;
346
- bool minimize = false;
347
- struct block_group_info * bgs = aux_info .bgs ;
348
- struct region * reg ;
377
+ unsigned int i ;
378
+ unsigned int found_bg = 0 ;
379
+ u32 found_bg_len = 0 ;
380
+
349
381
for (i = 0 ; i < aux_info .groups ; i ++ ) {
350
- for (j = 1 ; j < bgs [i ].chunk_count ; j ++ ) {
351
- u32 hole_start , hole_size ;
352
- hole_start = bgs [i ].chunks [j - 1 ].block + bgs [i ].chunks [j - 1 ].len ;
353
- hole_size = bgs [i ].chunks [j ].block - hole_start ;
354
- if (hole_size == len ) {
355
- // Perfect fit i.e. right between 2 chunks no need to keep searching
356
- found_bg = i ;
357
- found_prev_chunk = j - 1 ;
358
- found_block = hole_start ;
359
- found_allocate_len = hole_size ;
360
- goto done ;
361
- } else if (hole_size > len && (found_allocate_len == 0 || (found_allocate_len > hole_size ))) {
362
- found_bg = i ;
363
- found_prev_chunk = j - 1 ;
364
- found_block = hole_start ;
365
- found_allocate_len = hole_size ;
366
- minimize = true;
367
- } else if (!minimize ) {
368
- if (found_allocate_len < hole_size ) {
369
- found_bg = i ;
370
- found_prev_chunk = j - 1 ;
371
- found_block = hole_start ;
372
- found_allocate_len = hole_size ;
373
- }
374
- }
382
+ u32 bg_len = aux_info .bgs [i ].free_blocks ;
383
+
384
+ if ((len <= bg_len && (found_bg_len == 0 || bg_len < found_bg_len )) ||
385
+ (len > found_bg_len && bg_len > found_bg_len )) {
386
+ found_bg = i ;
387
+ found_bg_len = bg_len ;
375
388
}
376
389
}
377
390
378
- if (found_allocate_len == 0 ) {
391
+ if (found_bg_len ) {
392
+ u32 allocate_len = min (len , found_bg_len );
393
+ struct region * reg ;
394
+ u32 block = ext4_allocate_blocks_from_block_group (allocate_len , found_bg );
395
+ if (block == EXT4_ALLOCATE_FAILED ) {
396
+ error ("failed to allocate %d blocks in block group %d" , allocate_len , found_bg );
397
+ return NULL ;
398
+ }
399
+ reg = malloc (sizeof (struct region ));
400
+ reg -> block = block ;
401
+ reg -> len = allocate_len ;
402
+ reg -> next = NULL ;
403
+ reg -> prev = NULL ;
404
+ reg -> bg = found_bg ;
405
+ return reg ;
406
+ } else {
379
407
error ("failed to allocate %u blocks, out of space?" , len );
380
- return NULL ;
381
408
}
382
- if (found_allocate_len > len ) found_allocate_len = len ;
383
- done :
384
- // reclaim allocated space in chunk
385
- bgs [found_bg ].chunks [found_prev_chunk ].len += found_allocate_len ;
386
- if (reserve_blocks (& bgs [found_bg ],
387
- found_block ,
388
- found_allocate_len ) < 0 ) {
389
- error ("failed to reserve %u blocks in block group %u\n" , found_allocate_len , found_bg );
390
- return NULL ;
391
- }
392
- bgs [found_bg ].data_blocks_used += found_allocate_len ;
393
- reg = malloc (sizeof (struct region ));
394
- reg -> block = found_block + bgs [found_bg ].first_block ;
395
- reg -> len = found_allocate_len ;
396
- reg -> next = NULL ;
397
- reg -> prev = NULL ;
398
- reg -> bg = found_bg ;
399
- return reg ;
409
+
410
+ return NULL ;
400
411
}
401
412
402
413
static struct region * ext4_allocate_best_fit (u32 len )
@@ -428,9 +439,9 @@ static struct region *ext4_allocate_best_fit(u32 len)
428
439
/* Allocate len blocks. The blocks may be spread across multiple block groups,
429
440
and are returned in a linked list of the blocks in each block group. The
430
441
allocation algorithm is:
431
- 1. If the remaining allocation is larger than any available contiguous region,
432
- allocate the largest contiguous region and loop
433
- 2. Otherwise, allocate the smallest contiguous region that it fits in
442
+ 1. If the remaining allocation is larger than any available contiguous region,
443
+ allocate the largest contiguous region and loop
444
+ 2. Otherwise, allocate the smallest contiguous region that it fits in
434
445
*/
435
446
struct block_allocation * allocate_blocks (u32 len )
436
447
{
@@ -441,8 +452,6 @@ struct block_allocation *allocate_blocks(u32 len)
441
452
442
453
struct block_allocation * alloc = create_allocation ();
443
454
alloc -> list .first = reg ;
444
- while (reg -> next != NULL )
445
- reg = reg -> next ;
446
455
alloc -> list .last = reg ;
447
456
alloc -> list .iter = alloc -> list .first ;
448
457
alloc -> list .partial_iter = 0 ;
@@ -770,20 +779,3 @@ void free_alloc(struct block_allocation *alloc)
770
779
771
780
free (alloc );
772
781
}
773
-
774
- void reserve_bg_chunk (int bg , u32 start_block , u32 size ) {
775
- struct block_group_info * bgs = aux_info .bgs ;
776
- int chunk_count ;
777
- if (bgs [bg ].chunk_count == bgs [bg ].max_chunk_count ) {
778
- bgs [bg ].max_chunk_count *= 2 ;
779
- bgs [bg ].chunks = realloc (bgs [bg ].chunks , bgs [bg ].max_chunk_count * sizeof (struct region ));
780
- if (!bgs [bg ].chunks )
781
- critical_error ("realloc failed" );
782
- }
783
- chunk_count = bgs [bg ].chunk_count ;
784
- bgs [bg ].chunks [chunk_count ].block = start_block ;
785
- bgs [bg ].chunks [chunk_count ].len = size ;
786
- bgs [bg ].chunks [chunk_count ].bg = bg ;
787
- bgs [bg ].chunk_count ++ ;
788
- }
789
-
0 commit comments