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