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