Ejemplo n.º 1
0
int ddfs_hash_write(ext2_filsys fs, __u32 blk_no, __u8 hash[DDFS_HASH_LEN]) {

	blk_t phy_blk_no =0;
	unsigned inBlockIndex;
	//struct buffer_head * bh;
	unsigned long group;
	 group = ext2fs_group_of_blk(fs,blk_no) & (~0x3);
	blk_t  first_block = ext2fs_group_first_block(fs, group);
    unsigned offset;
    struct ext2_group_desc  *	desc = &fs->group_desc[group];
    phy_blk_no = (blk_no - ext2fs_group_first_block(fs,group)) / 128 + desc->bg_block_store;
    inBlockIndex = (blk_no - ext2fs_group_first_block(fs,group)) % 128;
    


	io_channel_read_blk(fs->io,phy_blk_no,1,blk_buf);

	//bh = sb_bread(sb, phy_blk_no);

	//TODO: Error check
	memcpy( blk_buf + 32 * inBlockIndex + 8,hash, 24);


    memcpy(blk_buf + DDFS_HASH_LEN * inBlockIndex, hash, DDFS_HASH_LEN);
	io_channel_write_blk(fs->io,phy_blk_no,1,blk_buf);
    return 0;
}
Ejemplo n.º 2
0
blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block, dgrp_t i)
{
	int	bg;
	int	has_super = 0;
	int	ret_blk;

	if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) ||
	    (i < fs->super->s_first_meta_bg))
		return (group_block + i + 1);

	bg = EXT2_DESC_PER_BLOCK(fs->super) * i;
	if (ext2fs_bg_has_super(fs, bg))
		has_super = 1;
	ret_blk = ext2fs_group_first_block(fs, bg) + has_super;
	/*
	 * If group_block is not the normal value, we're trying to use
	 * the backup group descriptors and superblock --- so use the
	 * alternate location of the second block group in the
	 * metablock group.  Ideally we should be testing each bg
	 * descriptor block individually for correctness, but we don't
	 * have the infrastructure in place to do that.
	 */
	if (group_block != fs->super->s_first_data_block &&
	    ((ret_blk + fs->super->s_blocks_per_group) <
	     fs->super->s_blocks_count))
		ret_blk += fs->super->s_blocks_per_group;
	return ret_blk;
}
Ejemplo n.º 3
0
static void print_bg_rel_offset(ext2_filsys fs, blk64_t block, int itable,
				blk64_t first_block, blk64_t last_block)
{
	if ((block >= first_block) && (block <= last_block)) {
		if (itable && block == first_block)
			return;
		printf(" (+%u)", (unsigned)(block - first_block));
	} else if (fs->super->s_feature_incompat &
		   EXT4_FEATURE_INCOMPAT_FLEX_BG) {
		dgrp_t flex_grp = ext2fs_group_of_blk(fs, block);
		printf(" (bg #%u + %u)", flex_grp,
		       (unsigned)(block-ext2fs_group_first_block(fs,flex_grp)));
	}
}
Ejemplo n.º 4
0
int ddfs_count_read(ext2_filsys fs, __u32 blk_no, __u32 * count) {

	blk_t phy_blk_no =0;
	unsigned inBlockIndex;
	//struct buffer_head * bh;
	unsigned long group;
	 group = ext2fs_group_of_blk(fs,blk_no) & (~0x3);
	blk_t  first_block = ext2fs_group_first_block(fs, group);
    unsigned offset;
    struct ext2_group_desc  *	desc = &fs->group_desc[group];
    phy_blk_no = (blk_no - ext2fs_group_first_block(fs,group)) / 128 + desc->bg_block_store;
    inBlockIndex = (blk_no - ext2fs_group_first_block(fs,group)) % 128;
    


	io_channel_read_blk(fs->io,phy_blk_no,1,blk_buf);

	//bh = sb_bread(sb, phy_blk_no);

	//TODO: Error check
	memcpy(count, blk_buf + 32 * inBlockIndex , 4);

	return 0;
}
Ejemplo n.º 5
0
static int ddfs_get_range(ext2_filsys fs,blk_t blk_no,blk_t *start,blk_t * end){
    unsigned entry_per_block = 128;
	unsigned long group;
	struct ext2_group_desc *	desc;
	blk_t first_block;

	group = ext2fs_group_of_blk(fs,blk_no);
	first_block = ext2fs_group_first_block(fs, group);
    desc = &fs->group_desc[group];

    unsigned pos = blk_no - desc->bg_block_store;
    
    *start = pos * entry_per_block + first_block;
    *end = *start + entry_per_block;
    return 0;
}
Ejemplo n.º 6
0
/*
 * This routine searches for free blocks that can allocate a full
 * group of bitmaps or inode tables for a flexbg group.  Returns the
 * block number with a correct offset were the bitmaps and inode
 * tables can be allocated continously and in order.
 */
static blk_t flexbg_offset(ext2_filsys fs, dgrp_t group, blk64_t start_blk,
			   ext2fs_block_bitmap bmap, int offset, int size,
			   int elem_size)
{
	int		flexbg, flexbg_size;
	blk_t		last_blk, first_free = 0;
	dgrp_t		last_grp;

	flexbg_size = 1 << fs->super->s_log_groups_per_flex;
	flexbg = group / flexbg_size;

	if (size > (int) (fs->super->s_blocks_per_group / 8))
		size = (int) fs->super->s_blocks_per_group / 8;

	if (offset)
		offset -= 1;

	/*
	 * Don't do a long search if the previous block
	 * search is still valid.
	 */
	if (start_blk && group % flexbg_size) {
		if (ext2fs_test_block_bitmap_range2(bmap, start_blk + elem_size,
						   size))
			return start_blk + elem_size;
	}

	start_blk = ext2fs_group_first_block(fs, flexbg_size * flexbg);
	last_grp = group | (flexbg_size - 1);
	if (last_grp > fs->group_desc_count)
		last_grp = fs->group_desc_count;
	last_blk = ext2fs_group_last_block(fs, last_grp);

	/* Find the first available block */
	if (ext2fs_get_free_blocks(fs, start_blk, last_blk, 1, bmap,
				   &first_free))
		return first_free;

	if (ext2fs_get_free_blocks(fs, first_free + offset, last_blk, size,
				   bmap, &first_free))
		return first_free;

	return first_free;
}
Ejemplo n.º 7
0
/*
 * This routine sanity checks the group descriptors
 */
errcode_t ext2fs_check_desc(ext2_filsys fs)
{
	dgrp_t i;
	blk_t first_block = fs->super->s_first_data_block;
	blk_t last_block;

	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);

	for (i = 0; i < fs->group_desc_count; i++) {
		first_block = ext2fs_group_first_block(fs, i);
		last_block = ext2fs_group_last_block(fs, i);

		/*
		 * Check to make sure block bitmap for group is
		 * located within the group.
		 */
		if (fs->group_desc[i].bg_block_bitmap < first_block ||
		    fs->group_desc[i].bg_block_bitmap > last_block)
			return EXT2_ET_GDESC_BAD_BLOCK_MAP;
		/*
		 * Check to make sure inode bitmap for group is
		 * located within the group
		 */
		if (fs->group_desc[i].bg_inode_bitmap < first_block ||
		    fs->group_desc[i].bg_inode_bitmap > last_block)
			return EXT2_ET_GDESC_BAD_INODE_MAP;
		/*
		 * Check to make sure inode table for group is located
		 * within the group
		 */
		if (fs->group_desc[i].bg_inode_table < first_block ||
		    ((fs->group_desc[i].bg_inode_table +
		      fs->inode_blocks_per_group) > last_block))
			return EXT2_ET_GDESC_BAD_INODE_TABLE;
	}
	return 0;
}
Ejemplo n.º 8
0
int ddfs_is_hash_block(ext2_filsys fs,blk_t blk_no){
	unsigned long group;
	struct ext2_group_desc *	desc;
	blk_t first_block;

	group = ext2fs_group_of_blk(fs,blk_no);
	first_block = ext2fs_group_first_block(fs, group);
    	desc = &fs->group_desc[group];

    if(group % 4 == 0 && blk_no >= desc->bg_block_store &&
            blk_no <= desc->bg_block_store + fs->super->s_blocks_per_group * 4 / 128){
        printf("YES!\n");
        return 1;
    }
#ifdef DDFS_STORE_DEBUG
    printf("blk_no = %u,first_block = %u,"
            "desc->bg_block_store = %u\n",
            blk_no,first_block,
            desc->bg_block_store
            );
#endif
    return 0;
    
}
Ejemplo n.º 9
0
/*
 * This function returns the location of the superblock, block group
 * descriptors for a given block group.  It currently returns the
 * number of free blocks assuming that inode table and allocation
 * bitmaps will be in the group.  This is not necessarily the case
 * when the flex_bg feature is enabled, so callers should take care!
 * It was only really intended for use by mke2fs, and even there it's
 * not that useful.  In the future, when we redo this function for
 * 64-bit block numbers, we should probably return the number of
 * blocks used by the super block and group descriptors instead.
 *
 * See also the comment for ext2fs_reserve_super_and_bgd()
 */
int ext2fs_super_and_bgd_loc(ext2_filsys fs,
			     dgrp_t group,
			     blk_t *ret_super_blk,
			     blk_t *ret_old_desc_blk,
			     blk_t *ret_new_desc_blk,
			     int *ret_meta_bg)
{
	blk_t	group_block, super_blk = 0, old_desc_blk = 0, new_desc_blk = 0;
	unsigned int meta_bg, meta_bg_size;
	blk_t	numblocks, old_desc_blocks;
	int	has_super;

	group_block = ext2fs_group_first_block(fs, group);

	if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
		old_desc_blocks = fs->super->s_first_meta_bg;
	else
		old_desc_blocks =
			fs->desc_blocks + fs->super->s_reserved_gdt_blocks;

	if (group == fs->group_desc_count-1) {
		numblocks = (fs->super->s_blocks_count -
			     fs->super->s_first_data_block) %
			fs->super->s_blocks_per_group;
		if (!numblocks)
			numblocks = fs->super->s_blocks_per_group;
	} else
		numblocks = fs->super->s_blocks_per_group;

	has_super = ext2fs_bg_has_super(fs, group);

	if (has_super) {
		super_blk = group_block;
		numblocks--;
	}
	meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super);
	meta_bg = group / meta_bg_size;

	if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) ||
	    (meta_bg < fs->super->s_first_meta_bg)) {
		if (has_super) {
			old_desc_blk = group_block + 1;
			numblocks -= old_desc_blocks;
		}
	} else {
		if (((group % meta_bg_size) == 0) ||
		    ((group % meta_bg_size) == 1) ||
		    ((group % meta_bg_size) == (meta_bg_size-1))) {
			if (has_super)
				has_super = 1;
			new_desc_blk = group_block + has_super;
			numblocks--;
		}
	}

	numblocks -= 2 + fs->inode_blocks_per_group;

	if (ret_super_blk)
		*ret_super_blk = super_blk;
	if (ret_old_desc_blk)
		*ret_old_desc_blk = old_desc_blk;
	if (ret_new_desc_blk)
		*ret_new_desc_blk = new_desc_blk;
	if (ret_meta_bg)
		*ret_meta_bg = meta_bg;
	return (numblocks);
}
Ejemplo n.º 10
0
errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
				      ext2fs_block_bitmap bmap)
{
	errcode_t	retval;
	blk_t		group_blk, start_blk, last_blk, new_blk, blk;
	int		j;

	group_blk = ext2fs_group_first_block(fs, group);
	last_blk = ext2fs_group_last_block(fs, group);

	if (!bmap)
		bmap = fs->block_map;
	
	/*
	 * Allocate the block and inode bitmaps, if necessary
	 */
	if (fs->stride) {
		retval = ext2fs_get_free_blocks(fs, group_blk, last_blk,
						1, bmap, &start_blk);
		if (retval)
			return retval;
		start_blk += fs->inode_blocks_per_group;
		start_blk += ((fs->stride * group) %
			      (last_blk - start_blk + 1));
		if (start_blk >= last_blk)
			start_blk = group_blk;
	} else
		start_blk = group_blk;

	if (!fs->group_desc[group].bg_block_bitmap) {
		retval = ext2fs_get_free_blocks(fs, start_blk, last_blk,
						1, bmap, &new_blk);
		if (retval == EXT2_ET_BLOCK_ALLOC_FAIL) 
			retval = ext2fs_get_free_blocks(fs, group_blk,
					last_blk, 1, bmap, &new_blk);
		if (retval)
			return retval;
		ext2fs_mark_block_bitmap(bmap, new_blk);
		fs->group_desc[group].bg_block_bitmap = new_blk;
	}

	if (!fs->group_desc[group].bg_inode_bitmap) {
		retval = ext2fs_get_free_blocks(fs, start_blk, last_blk,
						1, bmap, &new_blk);
		if (retval == EXT2_ET_BLOCK_ALLOC_FAIL) 
			retval = ext2fs_get_free_blocks(fs, group_blk,
					last_blk, 1, bmap, &new_blk);
		if (retval)
			return retval;
		ext2fs_mark_block_bitmap(bmap, new_blk);
		fs->group_desc[group].bg_inode_bitmap = new_blk;
	}

	/*
	 * Allocate the inode table
	 */
	if (!fs->group_desc[group].bg_inode_table) {
		retval = ext2fs_get_free_blocks(fs, group_blk, last_blk,
						fs->inode_blocks_per_group,
						bmap, &new_blk);
		if (retval)
			return retval;
		for (j=0, blk = new_blk;
		     j < fs->inode_blocks_per_group;
		     j++, blk++)
			ext2fs_mark_block_bitmap(bmap, blk);
		fs->group_desc[group].bg_inode_table = new_blk;
	}

	
	return 0;
}
Ejemplo n.º 11
0
static void list_desc (ext2_filsys fs)
{
	unsigned long i;
	blk_t	first_block, last_block;
	blk_t	super_blk, old_desc_blk, new_desc_blk;
	char *block_bitmap=NULL, *inode_bitmap=NULL;
	int inode_blocks_per_group, old_desc_blocks, reserved_gdt;
	int		block_nbytes, inode_nbytes;
	int has_super;
	blk_t		blk_itr = fs->super->s_first_data_block;
	ext2_ino_t	ino_itr = 1;

	block_nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
	inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8;

	if (fs->block_map)
		block_bitmap = malloc(block_nbytes);
	if (fs->inode_map)
		inode_bitmap = malloc(inode_nbytes);

	inode_blocks_per_group = ((fs->super->s_inodes_per_group *
				   EXT2_INODE_SIZE(fs->super)) +
				  EXT2_BLOCK_SIZE(fs->super) - 1) /
				 EXT2_BLOCK_SIZE(fs->super);
	reserved_gdt = fs->super->s_reserved_gdt_blocks;
	fputc('\n', stdout);
	first_block = fs->super->s_first_data_block;
	if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
		old_desc_blocks = fs->super->s_first_meta_bg;
	else
		old_desc_blocks = fs->desc_blocks;
	for (i = 0; i < fs->group_desc_count; i++) {
		first_block = ext2fs_group_first_block(fs, i);
		last_block = ext2fs_group_last_block(fs, i);

		ext2fs_super_and_bgd_loc(fs, i, &super_blk,
					 &old_desc_blk, &new_desc_blk, 0);

		printf (_("Group %lu: (Blocks "), i);
		print_range(first_block, last_block);
		fputs(")", stdout);
		print_bg_opts(fs, i);
		if (fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM)
			printf(_("  Checksum 0x%04x, unused inodes %d\n"),
			       fs->group_desc[i].bg_checksum,
			       fs->group_desc[i].bg_itable_unused);
		has_super = ((i==0) || super_blk);
		if (has_super) {
			printf (_("  %s superblock at "),
				i == 0 ? _("Primary") : _("Backup"));
			print_number(super_blk);
		}
		if (old_desc_blk) {
			printf(_(", Group descriptors at "));
			print_range(old_desc_blk,
				    old_desc_blk + old_desc_blocks - 1);
			if (reserved_gdt) {
				printf(_("\n  Reserved GDT blocks at "));
				print_range(old_desc_blk + old_desc_blocks,
					    old_desc_blk + old_desc_blocks +
					    reserved_gdt - 1);
			}
		} else if (new_desc_blk) {
			fputc(has_super ? ',' : ' ', stdout);
			printf(_(" Group descriptor at "));
			print_number(new_desc_blk);
			has_super++;
		}
		if (has_super)
			fputc('\n', stdout);
		fputs(_("  Block bitmap at "), stdout);
		print_number(fs->group_desc[i].bg_block_bitmap);
		print_bg_rel_offset(fs, fs->group_desc[i].bg_block_bitmap, 0,
				    first_block, last_block);

		fputs(_(", Inode bitmap at "), stdout);
		print_number(fs->group_desc[i].bg_inode_bitmap);
		print_bg_rel_offset(fs, fs->group_desc[i].bg_inode_bitmap, 0,
				    first_block, last_block);

		fputs(_("\n  Inode table at "), stdout);
		print_range(fs->group_desc[i].bg_inode_table,
			    fs->group_desc[i].bg_inode_table +
			    inode_blocks_per_group - 1);
		print_bg_rel_offset(fs, fs->group_desc[i].bg_inode_table, 1,
				    first_block, last_block);

		printf (_("\n  %u free blocks, %u free inodes, "
			  "%u directories%s"),
			fs->group_desc[i].bg_free_blocks_count,
			fs->group_desc[i].bg_free_inodes_count,
			fs->group_desc[i].bg_used_dirs_count,
			fs->group_desc[i].bg_itable_unused ? "" : "\n");
		if (fs->group_desc[i].bg_itable_unused)
			printf (_(", %u unused inodes\n"),
				fs->group_desc[i].bg_itable_unused);
		if (block_bitmap) {
			fputs(_("  Free blocks: "), stdout);
			ext2fs_get_block_bitmap_range(fs->block_map,
				 blk_itr, block_nbytes << 3, block_bitmap);
			print_free (i, block_bitmap,
				    fs->super->s_blocks_per_group,
				    fs->super->s_first_data_block);
			fputc('\n', stdout);
			blk_itr += fs->super->s_blocks_per_group;
		}
		if (inode_bitmap) {
			fputs(_("  Free inodes: "), stdout);
			ext2fs_get_inode_bitmap_range(fs->inode_map,
				 ino_itr, inode_nbytes << 3, inode_bitmap);
			print_free (i, inode_bitmap,
				    fs->super->s_inodes_per_group, 1);
			fputc('\n', stdout);
			ino_itr += fs->super->s_inodes_per_group;
		}
	}
	if (block_bitmap)
		free(block_bitmap);
	if (inode_bitmap)
		free(inode_bitmap);
}
Ejemplo n.º 12
0
/*
 * This routine sanity checks the group descriptors
 */
errcode_t ext2fs_check_desc(ext2_filsys fs)
{
	ext2fs_block_bitmap bmap;
	errcode_t retval;
	dgrp_t i;
	blk_t first_block = fs->super->s_first_data_block;
	blk_t last_block = fs->super->s_blocks_count-1;
	blk_t blk, b;
	int j;

	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);

	retval = ext2fs_allocate_block_bitmap(fs, "check_desc map", &bmap);
	if (retval)
		return retval;

	for (i = 0; i < fs->group_desc_count; i++)
		ext2fs_reserve_super_and_bgd(fs, i, bmap);

	for (i = 0; i < fs->group_desc_count; i++) {
		if (!EXT2_HAS_INCOMPAT_FEATURE(fs->super,
					       EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
			first_block = ext2fs_group_first_block(fs, i);
			last_block = ext2fs_group_last_block(fs, i);
			if (i == (fs->group_desc_count - 1))
				last_block = fs->super->s_blocks_count-1;
		}

		/*
		 * Check to make sure the block bitmap for group is sane
		 */
		blk = fs->group_desc[i].bg_block_bitmap;
		if (blk < first_block || blk > last_block ||
		    ext2fs_test_block_bitmap2(bmap, blk)) {
			retval = EXT2_ET_GDESC_BAD_BLOCK_MAP;
			goto errout;
		}
		ext2fs_mark_block_bitmap2(bmap, blk);

		/*
		 * Check to make sure the inode bitmap for group is sane
		 */
		blk = fs->group_desc[i].bg_inode_bitmap;
		if (blk < first_block || blk > last_block ||
		    ext2fs_test_block_bitmap2(bmap, blk)) {
			retval = EXT2_ET_GDESC_BAD_INODE_MAP;
			goto errout;
		}
		ext2fs_mark_block_bitmap2(bmap, blk);

		/*
		 * Check to make sure the inode table for group is sane
		 */
		blk = fs->group_desc[i].bg_inode_table;
		if (blk < first_block ||
		    ((blk + fs->inode_blocks_per_group - 1) > last_block)) {
			retval = EXT2_ET_GDESC_BAD_INODE_TABLE;
			goto errout;
		}
		for (j = 0, b = blk; j < fs->inode_blocks_per_group;
		     j++, b++) {
			if (ext2fs_test_block_bitmap2(bmap, b)) {
				retval = EXT2_ET_GDESC_BAD_INODE_TABLE;
				goto errout;
			}
			ext2fs_mark_block_bitmap2(bmap, b);
		}
	}
errout:
	ext2fs_free_block_bitmap(bmap);
	return retval;
}
Ejemplo n.º 13
0
errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
				      ext2fs_block_bitmap bmap)
{
	errcode_t	retval;
	blk_t		group_blk, start_blk, last_blk, new_blk, blk;
	dgrp_t		last_grp = 0;
	int		j, rem_grps = 0, flexbg_size = 0;

	group_blk = ext2fs_group_first_block(fs, group);
	last_blk = ext2fs_group_last_block(fs, group);

	if (!bmap)
		bmap = fs->block_map;

	if (EXT2_HAS_INCOMPAT_FEATURE(fs->super,
				      EXT4_FEATURE_INCOMPAT_FLEX_BG) &&
	    fs->super->s_log_groups_per_flex) {
		flexbg_size = 1 << fs->super->s_log_groups_per_flex;
		last_grp = group | (flexbg_size - 1);
		rem_grps = last_grp - group;
		if (last_grp > fs->group_desc_count)
			last_grp = fs->group_desc_count;
	}

	/*
	 * Allocate the block and inode bitmaps, if necessary
	 */
	if (fs->stride) {
		retval = ext2fs_get_free_blocks(fs, group_blk, last_blk,
						1, bmap, &start_blk);
		if (retval)
			return retval;
		start_blk += fs->inode_blocks_per_group;
		start_blk += ((fs->stride * group) %
			      (last_blk - start_blk + 1));
		if (start_blk >= last_blk)
			start_blk = group_blk;
	} else
		start_blk = group_blk;

	if (flexbg_size) {
		blk64_t prev_block = 0;

		if (group && fs->group_desc[group-1].bg_block_bitmap)
			prev_block = fs->group_desc[group-1].bg_block_bitmap;
		start_blk = flexbg_offset(fs, group, prev_block, bmap,
						 0, rem_grps, 1);
		last_blk = ext2fs_group_last_block(fs, last_grp);
	}

	if (!fs->group_desc[group].bg_block_bitmap) {
		retval = ext2fs_get_free_blocks(fs, start_blk, last_blk,
						1, bmap, &new_blk);
		if (retval == EXT2_ET_BLOCK_ALLOC_FAIL)
			retval = ext2fs_get_free_blocks(fs, group_blk,
					last_blk, 1, bmap, &new_blk);
		if (retval)
			return retval;
		ext2fs_mark_block_bitmap2(bmap, new_blk);
		fs->group_desc[group].bg_block_bitmap = new_blk;
		if (flexbg_size) {
			dgrp_t gr = ext2fs_group_of_blk(fs, new_blk);
			fs->group_desc[gr].bg_free_blocks_count--;
			fs->super->s_free_blocks_count--;
			fs->group_desc[gr].bg_flags &= ~EXT2_BG_BLOCK_UNINIT;
			ext2fs_group_desc_csum_set(fs, gr);
		}
	}

	if (flexbg_size) {
		blk_t prev_block = 0;
		if (group && fs->group_desc[group-1].bg_inode_bitmap)
			prev_block = fs->group_desc[group-1].bg_inode_bitmap;
		start_blk = flexbg_offset(fs, group, prev_block, bmap,
						 flexbg_size, rem_grps, 1);
		last_blk = ext2fs_group_last_block(fs, last_grp);
	}

	if (!fs->group_desc[group].bg_inode_bitmap) {
		retval = ext2fs_get_free_blocks(fs, start_blk, last_blk,
						1, bmap, &new_blk);
		if (retval == EXT2_ET_BLOCK_ALLOC_FAIL)
			retval = ext2fs_get_free_blocks(fs, group_blk,
					last_blk, 1, bmap, &new_blk);
		if (retval)
			return retval;
		ext2fs_mark_block_bitmap2(bmap, new_blk);
		fs->group_desc[group].bg_inode_bitmap = new_blk;
		if (flexbg_size) {
			dgrp_t gr = ext2fs_group_of_blk(fs, new_blk);
			fs->group_desc[gr].bg_free_blocks_count--;
			fs->super->s_free_blocks_count--;
			fs->group_desc[gr].bg_flags &= ~EXT2_BG_BLOCK_UNINIT;
			ext2fs_group_desc_csum_set(fs, gr);
		}
	}

	/*
	 * Allocate the inode table
	 */
	if (flexbg_size) {
		blk_t prev_block = 0;
		if (group && fs->group_desc[group-1].bg_inode_table)
			prev_block = fs->group_desc[group-1].bg_inode_table;
		group_blk = flexbg_offset(fs, group, prev_block, bmap,
						 flexbg_size * 2,
						 fs->inode_blocks_per_group *
						 rem_grps,
						 fs->inode_blocks_per_group);
		last_blk = ext2fs_group_last_block(fs, last_grp);
	}

	if (!fs->group_desc[group].bg_inode_table) {
		retval = ext2fs_get_free_blocks(fs, group_blk, last_blk,
						fs->inode_blocks_per_group,
						bmap, &new_blk);
		if (retval)
			return retval;
		for (j=0, blk = new_blk;
		     j < fs->inode_blocks_per_group;
		     j++, blk++) {
			ext2fs_mark_block_bitmap2(bmap, blk);
			if (flexbg_size) {
				dgrp_t gr = ext2fs_group_of_blk(fs, blk);
				fs->group_desc[gr].bg_free_blocks_count--;
				fs->super->s_free_blocks_count--;
				fs->group_desc[gr].bg_flags &= ~EXT2_BG_BLOCK_UNINIT;
				ext2fs_group_desc_csum_set(fs, gr);
			}
		}
		fs->group_desc[group].bg_inode_table = new_blk;
	}
	ext2fs_group_desc_csum_set(fs, group);
	return 0;
}