Home | History | Annotate | Download | only in ext4_utils
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "ext4_utils.h"
     18 #include "allocate.h"
     19 #include "backed_block.h"
     20 #include "ext4.h"
     21 
     22 #include <stdio.h>
     23 #include <stdlib.h>
     24 
     25 struct region_list {
     26 	struct region *first;
     27 	struct region *last;
     28 	struct region *iter;
     29 	u32 partial_iter;
     30 };
     31 
     32 struct block_allocation {
     33 	struct region_list list;
     34 	struct region_list oob_list;
     35 };
     36 
     37 struct region {
     38 	u32 block;
     39 	u32 len;
     40 	int bg;
     41 	struct region *next;
     42 	struct region *prev;
     43 };
     44 
     45 struct block_group_info {
     46 	u32 first_block;
     47 	int header_blocks;
     48 	int data_blocks_used;
     49 	int has_superblock;
     50 	u8 *bitmaps;
     51 	u8 *block_bitmap;
     52 	u8 *inode_bitmap;
     53 	u8 *inode_table;
     54 	u32 free_blocks;
     55 	u32 first_free_block;
     56 	u32 free_inodes;
     57 	u32 first_free_inode;
     58 	u16 used_dirs;
     59 };
     60 
     61 struct block_allocation *create_allocation()
     62 {
     63 	struct block_allocation *alloc = malloc(sizeof(struct block_allocation));
     64 	alloc->list.first = NULL;
     65 	alloc->list.last = NULL;
     66 	alloc->oob_list.first = NULL;
     67 	alloc->oob_list.last = NULL;
     68 	alloc->list.iter = NULL;
     69 	alloc->list.partial_iter = 0;
     70 	alloc->oob_list.iter = NULL;
     71 	alloc->oob_list.partial_iter = 0;
     72 	return alloc;
     73 }
     74 
     75 static void region_list_remove(struct region_list *list, struct region *reg)
     76 {
     77 	if (reg->prev)
     78 		reg->prev->next = reg->next;
     79 
     80 	if (reg->next)
     81 		reg->next->prev = reg->prev;
     82 
     83 	if (list->first == reg)
     84 		list->first = reg->next;
     85 
     86 	if (list->last == reg)
     87 		list->last = reg->prev;
     88 
     89 	reg->next = NULL;
     90 	reg->prev = NULL;
     91 }
     92 
     93 static void region_list_append(struct region_list *list, struct region *reg)
     94 {
     95 	if (list->first == NULL) {
     96 		list->first = reg;
     97 		list->last = reg;
     98 		list->iter = reg;
     99 		list->partial_iter = 0;
    100 		reg->prev = NULL;
    101 	} else {
    102 		list->last->next = reg;
    103 		reg->prev = list->last;
    104 		list->last = reg;
    105 	}
    106 	reg->next = NULL;
    107 }
    108 
    109 #if 0
    110 static void dump_starting_from(struct region *reg)
    111 {
    112 	for (; reg; reg = reg->next) {
    113 		printf("%p: Blocks %d-%d (%d)\n", reg,
    114 				reg->bg * info.blocks_per_group + reg->block,
    115 				reg->bg * info.blocks_per_group + reg->block + reg->len - 1,
    116 				reg->len);
    117 	}
    118 }
    119 
    120 static void dump_region_lists(struct block_allocation *alloc) {
    121 
    122 	printf("Main list:\n");
    123 	dump_starting_from(alloc->list.first);
    124 
    125 	printf("OOB list:\n");
    126 	dump_starting_from(alloc->oob_list.first);
    127 }
    128 #endif
    129 
    130 void append_region(struct block_allocation *alloc,
    131 		u32 block, u32 len, int bg_num)
    132 {
    133 	struct region *reg;
    134 	reg = malloc(sizeof(struct region));
    135 	reg->block = block;
    136 	reg->len = len;
    137 	reg->bg = bg_num;
    138 	reg->next = NULL;
    139 
    140 	region_list_append(&alloc->list, reg);
    141 }
    142 
    143 static void allocate_bg_inode_table(struct block_group_info *bg)
    144 {
    145 	if (bg->inode_table != NULL)
    146 		return;
    147 
    148 	u32 block = bg->first_block + 2;
    149 
    150 	if (bg->has_superblock)
    151 		block += aux_info.bg_desc_blocks + info.bg_desc_reserve_blocks + 1;
    152 
    153 	bg->inode_table = calloc(aux_info.inode_table_blocks, info.block_size);
    154 	if (bg->inode_table == NULL)
    155 		critical_error_errno("calloc");
    156 
    157 	queue_data_block(bg->inode_table, aux_info.inode_table_blocks
    158 			* info.block_size, block);
    159 }
    160 
    161 void init_unused_inode_tables(void)
    162 {
    163 	unsigned int i;
    164 	u32 block;
    165 	struct block_group_info *bg;
    166 
    167 	for (i = 0; i < aux_info.groups; i++) {
    168 		if (!aux_info.bgs[i].inode_table) {
    169 			bg = &aux_info.bgs[i];
    170 			block = bg->first_block + 2;
    171 			if (bg->has_superblock)
    172 				block += aux_info.bg_desc_blocks + info.bg_desc_reserve_blocks + 1;
    173 			queue_fill_block(0, aux_info.inode_table_blocks * info.block_size, block);
    174                 }
    175        }
    176 }
    177 
    178 static int bitmap_set_bit(u8 *bitmap, u32 bit)
    179 {
    180 	if (bitmap[bit / 8] & 1 << (bit % 8))
    181 		return 1;
    182 
    183 	bitmap[bit / 8] |= 1 << (bit % 8);
    184 	return 0;
    185 }
    186 
    187 static int bitmap_set_8_bits(u8 *bitmap, u32 bit)
    188 {
    189 	int ret = bitmap[bit / 8];
    190 	bitmap[bit / 8] = 0xFF;
    191 	return ret;
    192 }
    193 
    194 /* Marks a the first num_blocks blocks in a block group as used, and accounts
    195  for them in the block group free block info. */
    196 static int reserve_blocks(struct block_group_info *bg, u32 start, u32 num)
    197 {
    198 	unsigned int i = 0;
    199 
    200 	u32 block = start;
    201 	if (num > bg->free_blocks)
    202 		return -1;
    203 
    204 	for (i = 0; i < num && block % 8 != 0; i++, block++) {
    205 		if (bitmap_set_bit(bg->block_bitmap, block)) {
    206 			error("attempted to reserve already reserved block");
    207 			return -1;
    208 		}
    209 	}
    210 
    211 	for (; i + 8 <= (num & ~7); i += 8, block += 8) {
    212 		if (bitmap_set_8_bits(bg->block_bitmap, block)) {
    213 			error("attempted to reserve already reserved block");
    214 			return -1;
    215 		}
    216 	}
    217 
    218 	for (; i < num; i++, block++) {
    219 		if (bitmap_set_bit(bg->block_bitmap, block)) {
    220 			error("attempted to reserve already reserved block");
    221 			return -1;
    222 		}
    223 	}
    224 
    225 	bg->free_blocks -= num;
    226 	if (start == bg->first_free_block)
    227 		bg->first_free_block = start + num;
    228 
    229 	return 0;
    230 }
    231 
    232 static void free_blocks(struct block_group_info *bg, u32 num_blocks)
    233 {
    234 	unsigned int i;
    235 	u32 block = bg->first_free_block - 1;
    236 	for (i = 0; i < num_blocks; i++, block--)
    237 		bg->block_bitmap[block / 8] &= ~(1 << (block % 8));
    238 	bg->free_blocks += num_blocks;
    239 	bg->first_free_block -= num_blocks;
    240 }
    241 
    242 /* Reduces an existing allocation by len blocks by return the last blocks
    243    to the free pool in their block group. Assumes that the blocks being
    244    returned were the last ones allocated out of the block group */
    245 void reduce_allocation(struct block_allocation *alloc, u32 len)
    246 {
    247 	while (len) {
    248 		struct region *last_reg = alloc->list.last;
    249 
    250 		if (last_reg->len > len) {
    251 			free_blocks(&aux_info.bgs[last_reg->bg], len);
    252 			last_reg->len -= len;
    253 			len = 0;
    254 		} else {
    255 			struct region *reg = alloc->list.last->prev;
    256 			free_blocks(&aux_info.bgs[last_reg->bg], last_reg->len);
    257 			len -= last_reg->len;
    258 			if (reg) {
    259 				reg->next = NULL;
    260 			} else {
    261 				alloc->list.first = NULL;
    262 				alloc->list.last = NULL;
    263 				alloc->list.iter = NULL;
    264 				alloc->list.partial_iter = 0;
    265 			}
    266 			free(last_reg);
    267 		}
    268 	}
    269 }
    270 
    271 static void init_bg(struct block_group_info *bg, unsigned int i)
    272 {
    273 	int header_blocks = 2 + aux_info.inode_table_blocks;
    274 
    275 	bg->has_superblock = ext4_bg_has_super_block(i);
    276 
    277 	if (bg->has_superblock)
    278 		header_blocks += 1 + aux_info.bg_desc_blocks + info.bg_desc_reserve_blocks;
    279 
    280 	bg->bitmaps = calloc(info.block_size, 2);
    281 	bg->block_bitmap = bg->bitmaps;
    282 	bg->inode_bitmap = bg->bitmaps + info.block_size;
    283 
    284 	bg->header_blocks = header_blocks;
    285 	bg->first_block = aux_info.first_data_block + i * info.blocks_per_group;
    286 
    287 	u32 block = bg->first_block;
    288 	if (bg->has_superblock)
    289 		block += 1 + aux_info.bg_desc_blocks +  info.bg_desc_reserve_blocks;
    290 	queue_data_block(bg->bitmaps, 2 * info.block_size, block);
    291 
    292 	bg->data_blocks_used = 0;
    293 	bg->free_blocks = info.blocks_per_group;
    294 	bg->first_free_block = 0;
    295 	bg->free_inodes = info.inodes_per_group;
    296 	bg->first_free_inode = 1;
    297 
    298 	if (reserve_blocks(bg, bg->first_free_block, bg->header_blocks) < 0)
    299 		error("failed to reserve %u blocks in block group %u\n", bg->header_blocks, i);
    300 
    301 	u32 overrun = bg->first_block + info.blocks_per_group - aux_info.len_blocks;
    302 	if (overrun > 0)
    303 		reserve_blocks(bg, info.blocks_per_group - overrun, overrun);
    304 }
    305 
    306 void block_allocator_init()
    307 {
    308 	unsigned int i;
    309 
    310 	aux_info.bgs = calloc(sizeof(struct block_group_info), aux_info.groups);
    311 	if (aux_info.bgs == NULL)
    312 		critical_error_errno("calloc");
    313 
    314 	for (i = 0; i < aux_info.groups; i++)
    315 		init_bg(&aux_info.bgs[i], i);
    316 }
    317 
    318 void block_allocator_free()
    319 {
    320 	unsigned int i;
    321 
    322 	for (i = 0; i < aux_info.groups; i++) {
    323 		free(aux_info.bgs[i].bitmaps);
    324 		free(aux_info.bgs[i].inode_table);
    325 	}
    326 	free(aux_info.bgs);
    327 }
    328 
    329 static u32 ext4_allocate_blocks_from_block_group(u32 len, int bg_num)
    330 {
    331 	if (get_free_blocks(bg_num) < len)
    332 		return EXT4_ALLOCATE_FAILED;
    333 
    334 	u32 block = aux_info.bgs[bg_num].first_free_block;
    335 	struct block_group_info *bg = &aux_info.bgs[bg_num];
    336 	if (reserve_blocks(bg, bg->first_free_block, len) < 0) {
    337 		error("failed to reserve %u blocks in block group %u\n", len, bg_num);
    338 		return EXT4_ALLOCATE_FAILED;
    339 	}
    340 
    341 	aux_info.bgs[bg_num].data_blocks_used += len;
    342 
    343 	return bg->first_block + block;
    344 }
    345 
    346 static struct region *ext4_allocate_contiguous_blocks(u32 len)
    347 {
    348 	unsigned int i;
    349 	struct region *reg;
    350 
    351 	for (i = 0; i < aux_info.groups; i++) {
    352 		u32 block = ext4_allocate_blocks_from_block_group(len, i);
    353 
    354 		if (block != EXT4_ALLOCATE_FAILED) {
    355 			reg = malloc(sizeof(struct region));
    356 			reg->block = block;
    357 			reg->len = len;
    358 			reg->next = NULL;
    359 			reg->prev = NULL;
    360 			reg->bg = i;
    361 			return reg;
    362 		}
    363 	}
    364 
    365 	return NULL;
    366 }
    367 
    368 /* Allocate a single block and return its block number */
    369 u32 allocate_block()
    370 {
    371 	unsigned int i;
    372 	for (i = 0; i < aux_info.groups; i++) {
    373 		u32 block = ext4_allocate_blocks_from_block_group(1, i);
    374 
    375 		if (block != EXT4_ALLOCATE_FAILED)
    376 			return block;
    377 	}
    378 
    379 	return EXT4_ALLOCATE_FAILED;
    380 }
    381 
    382 static struct region *ext4_allocate_partial(u32 len)
    383 {
    384 	unsigned int i;
    385 	struct region *reg;
    386 
    387 	for (i = 0; i < aux_info.groups; i++) {
    388 		if (aux_info.bgs[i].data_blocks_used == 0) {
    389 			u32 bg_len = aux_info.bgs[i].free_blocks;
    390 			u32 block;
    391 
    392 			if (len <= bg_len) {
    393 				/* If the requested length would fit in a block group,
    394 				 use the regular allocator to try to fit it in a partially
    395 				 used block group */
    396 				bg_len = len;
    397 				reg = ext4_allocate_contiguous_blocks(len);
    398 			} else {
    399 				block = ext4_allocate_blocks_from_block_group(bg_len, i);
    400 
    401 				if (block == EXT4_ALLOCATE_FAILED) {
    402 					error("failed to allocate %d blocks in block group %d", bg_len, i);
    403 					return NULL;
    404 				}
    405 
    406 				reg = malloc(sizeof(struct region));
    407 				reg->block = block;
    408 				reg->len = bg_len;
    409 				reg->next = NULL;
    410 				reg->prev = NULL;
    411 				reg->bg = i;
    412 			}
    413 
    414 			return reg;
    415 		}
    416 	}
    417 	return NULL;
    418 }
    419 
    420 static struct region *ext4_allocate_multiple_contiguous_blocks(u32 len)
    421 {
    422 	struct region *first_reg = NULL;
    423 	struct region *prev_reg = NULL;
    424 	struct region *reg;
    425 
    426 	while (len > 0) {
    427 		reg = ext4_allocate_partial(len);
    428 		if (reg == NULL)
    429 			return NULL;
    430 
    431 		if (first_reg == NULL)
    432 			first_reg = reg;
    433 
    434 		if (prev_reg) {
    435 			prev_reg->next = reg;
    436 			reg->prev = prev_reg;
    437 		}
    438 
    439 		prev_reg = reg;
    440 		len -= reg->len;
    441 	}
    442 
    443 	return first_reg;
    444 }
    445 
    446 struct region *do_allocate(u32 len)
    447 {
    448 	struct region *reg = ext4_allocate_contiguous_blocks(len);
    449 
    450 	if (reg == NULL)
    451 		reg = ext4_allocate_multiple_contiguous_blocks(len);
    452 
    453 	return reg;
    454 }
    455 
    456 /* Allocate len blocks.  The blocks may be spread across multiple block groups,
    457    and are returned in a linked list of the blocks in each block group.  The
    458    allocation algorithm is:
    459       1.  Try to allocate the entire block len in each block group
    460       2.  If the request doesn't fit in any block group, allocate as many
    461           blocks as possible into each block group that is completely empty
    462       3.  Put the last set of blocks in the first block group they fit in
    463 */
    464 struct block_allocation *allocate_blocks(u32 len)
    465 {
    466 	struct region *reg = do_allocate(len);
    467 
    468 	if (reg == NULL)
    469 		return NULL;
    470 
    471 	struct block_allocation *alloc = create_allocation();
    472 	alloc->list.first = reg;
    473 	alloc->list.last = reg;
    474 	alloc->list.iter = alloc->list.first;
    475 	alloc->list.partial_iter = 0;
    476 	return alloc;
    477 }
    478 
    479 /* Returns the number of discontiguous regions used by an allocation */
    480 int block_allocation_num_regions(struct block_allocation *alloc)
    481 {
    482 	unsigned int i;
    483 	struct region *reg = alloc->list.first;
    484 
    485 	for (i = 0; reg != NULL; reg = reg->next)
    486 		i++;
    487 
    488 	return i;
    489 }
    490 
    491 int block_allocation_len(struct block_allocation *alloc)
    492 {
    493 	unsigned int i;
    494 	struct region *reg = alloc->list.first;
    495 
    496 	for (i = 0; reg != NULL; reg = reg->next)
    497 		i += reg->len;
    498 
    499 	return i;
    500 }
    501 
    502 /* Returns the block number of the block'th block in an allocation */
    503 u32 get_block(struct block_allocation *alloc, u32 block)
    504 {
    505 	struct region *reg = alloc->list.iter;
    506 	block += alloc->list.partial_iter;
    507 
    508 	for (; reg; reg = reg->next) {
    509 		if (block < reg->len)
    510 			return reg->block + block;
    511 		block -= reg->len;
    512 	}
    513 	return EXT4_ALLOCATE_FAILED;
    514 }
    515 
    516 u32 get_oob_block(struct block_allocation *alloc, u32 block)
    517 {
    518 	struct region *reg = alloc->oob_list.iter;
    519 	block += alloc->oob_list.partial_iter;
    520 
    521 	for (; reg; reg = reg->next) {
    522 		if (block < reg->len)
    523 			return reg->block + block;
    524 		block -= reg->len;
    525 	}
    526 	return EXT4_ALLOCATE_FAILED;
    527 }
    528 
    529 /* Gets the starting block and length in blocks of the first region
    530    of an allocation */
    531 void get_region(struct block_allocation *alloc, u32 *block, u32 *len)
    532 {
    533 	*block = alloc->list.iter->block;
    534 	*len = alloc->list.iter->len - alloc->list.partial_iter;
    535 }
    536 
    537 /* Move to the next region in an allocation */
    538 void get_next_region(struct block_allocation *alloc)
    539 {
    540 	alloc->list.iter = alloc->list.iter->next;
    541 	alloc->list.partial_iter = 0;
    542 }
    543 
    544 /* Returns the number of free blocks in a block group */
    545 u32 get_free_blocks(u32 bg)
    546 {
    547 	return aux_info.bgs[bg].free_blocks;
    548 }
    549 
    550 int last_region(struct block_allocation *alloc)
    551 {
    552 	return (alloc->list.iter == NULL);
    553 }
    554 
    555 void rewind_alloc(struct block_allocation *alloc)
    556 {
    557 	alloc->list.iter = alloc->list.first;
    558 	alloc->list.partial_iter = 0;
    559 }
    560 
    561 static struct region *do_split_allocation(struct block_allocation *alloc, u32 len)
    562 {
    563 	struct region *reg = alloc->list.iter;
    564 	struct region *new;
    565 	struct region *tmp;
    566 
    567 	while (reg && len >= reg->len) {
    568 		len -= reg->len;
    569 		reg = reg->next;
    570 	}
    571 
    572 	if (reg == NULL && len > 0)
    573 		return NULL;
    574 
    575 	if (len > 0) {
    576 		new = malloc(sizeof(struct region));
    577 
    578 		new->bg = reg->bg;
    579 		new->block = reg->block + len;
    580 		new->len = reg->len - len;
    581 		new->next = reg->next;
    582 		new->prev = reg;
    583 
    584 		reg->next = new;
    585 		reg->len = len;
    586 
    587 		tmp = alloc->list.iter;
    588 		alloc->list.iter = new;
    589 		return tmp;
    590 	} else {
    591 		return reg;
    592 	}
    593 }
    594 
    595 /* Splits an allocation into two allocations.  The returned allocation will
    596    point to the first half, and the original allocation ptr will point to the
    597    second half. */
    598 static struct region *split_allocation(struct block_allocation *alloc, u32 len)
    599 {
    600 	/* First make sure there is a split at the current ptr */
    601 	do_split_allocation(alloc, alloc->list.partial_iter);
    602 
    603 	/* Then split off len blocks */
    604 	struct region *middle = do_split_allocation(alloc, len);
    605 	alloc->list.partial_iter = 0;
    606 	return middle;
    607 }
    608 
    609 /* Reserve the next blocks for oob data (indirect or extent blocks) */
    610 int reserve_oob_blocks(struct block_allocation *alloc, int blocks)
    611 {
    612 	struct region *oob = split_allocation(alloc, blocks);
    613 	struct region *next;
    614 
    615 	if (oob == NULL)
    616 		return -1;
    617 
    618 	while (oob && oob != alloc->list.iter) {
    619 		next = oob->next;
    620 		region_list_remove(&alloc->list, oob);
    621 		region_list_append(&alloc->oob_list, oob);
    622 		oob = next;
    623 	}
    624 
    625 	return 0;
    626 }
    627 
    628 static int advance_list_ptr(struct region_list *list, int blocks)
    629 {
    630 	struct region *reg = list->iter;
    631 
    632 	while (reg != NULL && blocks > 0) {
    633 		if (reg->len > list->partial_iter + blocks) {
    634 			list->partial_iter += blocks;
    635 			return 0;
    636 		}
    637 
    638 		blocks -= (reg->len - list->partial_iter);
    639 		list->partial_iter = 0;
    640 		reg = reg->next;
    641 	}
    642 
    643 	if (blocks > 0)
    644 		return -1;
    645 
    646 	return 0;
    647 }
    648 
    649 /* Move the allocation pointer forward */
    650 int advance_blocks(struct block_allocation *alloc, int blocks)
    651 {
    652 	return advance_list_ptr(&alloc->list, blocks);
    653 }
    654 
    655 int advance_oob_blocks(struct block_allocation *alloc, int blocks)
    656 {
    657 	return advance_list_ptr(&alloc->oob_list, blocks);
    658 }
    659 
    660 int append_oob_allocation(struct block_allocation *alloc, u32 len)
    661 {
    662 	struct region *reg = do_allocate(len);
    663 
    664 	if (reg == NULL) {
    665 		error("failed to allocate %d blocks", len);
    666 		return -1;
    667 	}
    668 
    669 	for (; reg; reg = reg->next)
    670 		region_list_append(&alloc->oob_list, reg);
    671 
    672 	return 0;
    673 }
    674 
    675 /* Returns an ext4_inode structure for an inode number */
    676 struct ext4_inode *get_inode(u32 inode)
    677 {
    678 	inode -= 1;
    679 	int bg = inode / info.inodes_per_group;
    680 	inode %= info.inodes_per_group;
    681 
    682 	allocate_bg_inode_table(&aux_info.bgs[bg]);
    683 	return (struct ext4_inode *)(aux_info.bgs[bg].inode_table + inode *
    684 		info.inode_size);
    685 }
    686 
    687 /* Mark the first len inodes in a block group as used */
    688 u32 reserve_inodes(int bg, u32 num)
    689 {
    690 	unsigned int i;
    691 	u32 inode;
    692 
    693 	if (get_free_inodes(bg) < num)
    694 		return EXT4_ALLOCATE_FAILED;
    695 
    696 	for (i = 0; i < num; i++) {
    697 		inode = aux_info.bgs[bg].first_free_inode + i - 1;
    698 		aux_info.bgs[bg].inode_bitmap[inode / 8] |= 1 << (inode % 8);
    699 	}
    700 
    701 	inode = aux_info.bgs[bg].first_free_inode;
    702 
    703 	aux_info.bgs[bg].first_free_inode += num;
    704 	aux_info.bgs[bg].free_inodes -= num;
    705 
    706 	return inode;
    707 }
    708 
    709 /* Returns the first free inode number
    710    TODO: Inodes should be allocated in the block group of the data? */
    711 u32 allocate_inode()
    712 {
    713 	unsigned int bg;
    714 	u32 inode;
    715 
    716 	for (bg = 0; bg < aux_info.groups; bg++) {
    717 		inode = reserve_inodes(bg, 1);
    718 		if (inode != EXT4_ALLOCATE_FAILED)
    719 			return bg * info.inodes_per_group + inode;
    720 	}
    721 
    722 	return EXT4_ALLOCATE_FAILED;
    723 }
    724 
    725 /* Returns the number of free inodes in a block group */
    726 u32 get_free_inodes(u32 bg)
    727 {
    728 	return aux_info.bgs[bg].free_inodes;
    729 }
    730 
    731 /* Increments the directory count of the block group that contains inode */
    732 void add_directory(u32 inode)
    733 {
    734 	int bg = (inode - 1) / info.inodes_per_group;
    735 	aux_info.bgs[bg].used_dirs += 1;
    736 }
    737 
    738 /* Returns the number of inodes in a block group that are directories */
    739 u16 get_directories(int bg)
    740 {
    741 	return aux_info.bgs[bg].used_dirs;
    742 }
    743 
    744 /* Frees the memory used by a linked list of allocation regions */
    745 void free_alloc(struct block_allocation *alloc)
    746 {
    747 	struct region *reg;
    748 
    749 	reg = alloc->list.first;
    750 	while (reg) {
    751 		struct region *next = reg->next;
    752 		free(reg);
    753 		reg = next;
    754 	}
    755 
    756 	reg = alloc->oob_list.first;
    757 	while (reg) {
    758 		struct region *next = reg->next;
    759 		free(reg);
    760 		reg = next;
    761 	}
    762 
    763 	free(alloc);
    764 }
    765