Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bd81d8ee authored by Laurent Vivier's avatar Laurent Vivier Committed by Linus Torvalds
Browse files

[PATCH] ext4: 64bit metadata



In-kernel super block changes to support >32 bit free blocks numbers.

Signed-off-by: default avatarLaurent Vivier <Laurent.Vivier@bull.net>
Signed-off-by: default avatarDave Kleikamp <shaggy@austin.ibm.com>
Signed-off-by: default avatarAlexandre Ratchov <alexandre.ratchov@bull.net>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent a1ddeb7e
Loading
Loading
Loading
Loading
+25 −25
Original line number Diff line number Diff line
@@ -99,12 +99,13 @@ read_block_bitmap(struct super_block *sb, unsigned int block_group)
	desc = ext4_get_group_desc (sb, block_group, NULL);
	if (!desc)
		goto error_out;
	bh = sb_bread(sb, le32_to_cpu(desc->bg_block_bitmap));
	bh = sb_bread(sb, ext4_block_bitmap(desc));
	if (!bh)
		ext4_error (sb, "read_block_bitmap",
			    "Cannot read block bitmap - "
			    "block_group = %d, block_bitmap = %u",
			    block_group, le32_to_cpu(desc->bg_block_bitmap));
			    "block_group = %d, block_bitmap = "E3FSBLK,
			    block_group,
			    ext4_block_bitmap(desc));
error_out:
	return bh;
}
@@ -432,14 +433,14 @@ void ext4_free_blocks_sb(handle_t *handle, struct super_block *sb,
	es = sbi->s_es;
	if (block < le32_to_cpu(es->s_first_data_block) ||
	    block + count < block ||
	    block + count > le32_to_cpu(es->s_blocks_count)) {
	    block + count > ext4_blocks_count(es)) {
		ext4_error (sb, "ext4_free_blocks",
			    "Freeing blocks not in datazone - "
			    "block = "E3FSBLK", count = %lu", block, count);
		goto error_return;
	}

	ext4_debug ("freeing block(s) %lu-%lu\n", block, block + count - 1);
	ext4_debug ("freeing block(s) %llu-%llu\n", block, block + count - 1);

do_more:
	overflow = 0;
@@ -460,11 +461,10 @@ void ext4_free_blocks_sb(handle_t *handle, struct super_block *sb,
	if (!desc)
		goto error_return;

	if (in_range (le32_to_cpu(desc->bg_block_bitmap), block, count) ||
	    in_range (le32_to_cpu(desc->bg_inode_bitmap), block, count) ||
	    in_range (block, le32_to_cpu(desc->bg_inode_table),
		      sbi->s_itb_per_group) ||
	    in_range (block + count - 1, le32_to_cpu(desc->bg_inode_table),
	if (in_range(ext4_block_bitmap(desc), block, count) ||
	    in_range(ext4_inode_bitmap(desc), block, count) ||
	    in_range(block, ext4_inode_table(desc), sbi->s_itb_per_group) ||
	    in_range(block + count - 1, ext4_inode_table(desc),
		     sbi->s_itb_per_group))
		ext4_error (sb, "ext4_free_blocks",
			    "Freeing blocks in system zones - "
@@ -553,7 +553,7 @@ void ext4_free_blocks_sb(handle_t *handle, struct super_block *sb,
			jbd_unlock_bh_state(bitmap_bh);
			ext4_error(sb, __FUNCTION__,
				   "bit already cleared for block "E3FSBLK,
				 block + i);
				   (ext4_fsblk_t)(block + i));
			jbd_lock_bh_state(bitmap_bh);
			BUFFER_TRACE(bitmap_bh, "bit already cleared");
		} else {
@@ -1351,7 +1351,7 @@ static int ext4_has_free_blocks(struct ext4_sb_info *sbi)
	ext4_fsblk_t free_blocks, root_blocks;

	free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
	root_blocks = le32_to_cpu(sbi->s_es->s_r_blocks_count);
	root_blocks = ext4_r_blocks_count(sbi->s_es);
	if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) &&
		sbi->s_resuid != current->fsuid &&
		(sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) {
@@ -1462,7 +1462,7 @@ ext4_fsblk_t ext4_new_blocks(handle_t *handle, struct inode *inode,
	 * First, test whether the goal block is free.
	 */
	if (goal < le32_to_cpu(es->s_first_data_block) ||
	    goal >= le32_to_cpu(es->s_blocks_count))
	    goal >= ext4_blocks_count(es))
		goal = le32_to_cpu(es->s_first_data_block);
	ext4_get_group_no_and_offset(sb, goal, &group_no, &grp_target_blk);
	goal_group = group_no;
@@ -1561,11 +1561,11 @@ ext4_fsblk_t ext4_new_blocks(handle_t *handle, struct inode *inode,

	ret_block = grp_alloc_blk + ext4_group_first_block_no(sb, group_no);

	if (in_range(le32_to_cpu(gdp->bg_block_bitmap), ret_block, num) ||
	    in_range(le32_to_cpu(gdp->bg_inode_bitmap), ret_block, num) ||
	    in_range(ret_block, le32_to_cpu(gdp->bg_inode_table),
	if (in_range(ext4_block_bitmap(gdp), ret_block, num) ||
	    in_range(ext4_block_bitmap(gdp), ret_block, num) ||
	    in_range(ret_block, ext4_inode_table(gdp),
		     EXT4_SB(sb)->s_itb_per_group) ||
	    in_range(ret_block + num - 1, le32_to_cpu(gdp->bg_inode_table),
	    in_range(ret_block + num - 1, ext4_inode_table(gdp),
		     EXT4_SB(sb)->s_itb_per_group))
		ext4_error(sb, "ext4_new_block",
			    "Allocating block in system zone - "
@@ -1604,11 +1604,11 @@ ext4_fsblk_t ext4_new_blocks(handle_t *handle, struct inode *inode,
	jbd_unlock_bh_state(bitmap_bh);
#endif

	if (ret_block + num - 1 >= le32_to_cpu(es->s_blocks_count)) {
	if (ret_block + num - 1 >= ext4_blocks_count(es)) {
		ext4_error(sb, "ext4_new_block",
			    "block("E3FSBLK") >= blocks count(%d) - "
			    "block("E3FSBLK") >= blocks count("E3FSBLK") - "
			    "block_group = %lu, es == %p ", ret_block,
			le32_to_cpu(es->s_blocks_count), group_no, es);
			ext4_blocks_count(es), group_no, es);
		goto out;
	}

@@ -1707,7 +1707,7 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
	brelse(bitmap_bh);
	printk("ext4_count_free_blocks: stored = "E3FSBLK
		", computed = "E3FSBLK", "E3FSBLK"\n",
	       le32_to_cpu(es->s_free_blocks_count),
	       EXT4_FREE_BLOCKS_COUNT(es),
		desc_count, bitmap_count);
	return bitmap_count;
#else
+4 −4
Original line number Diff line number Diff line
@@ -60,12 +60,12 @@ read_inode_bitmap(struct super_block * sb, unsigned long block_group)
	if (!desc)
		goto error_out;

	bh = sb_bread(sb, le32_to_cpu(desc->bg_inode_bitmap));
	bh = sb_bread(sb, ext4_inode_bitmap(desc));
	if (!bh)
		ext4_error(sb, "read_inode_bitmap",
			    "Cannot read inode bitmap - "
			    "block_group = %lu, inode_bitmap = %u",
			    block_group, le32_to_cpu(desc->bg_inode_bitmap));
			    "block_group = %lu, inode_bitmap = %llu",
			    block_group, ext4_inode_bitmap(desc));
error_out:
	return bh;
}
@@ -304,7 +304,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent)
		goto fallback;
	}

	blocks_per_dir = le32_to_cpu(es->s_blocks_count) - freeb;
	blocks_per_dir = ext4_blocks_count(es) - freeb;
	sector_div(blocks_per_dir, ndirs);

	max_dirs = ndirs / ngroups + inodes_per_group / 16;
+3 −3
Original line number Diff line number Diff line
@@ -2438,7 +2438,7 @@ static ext4_fsblk_t ext4_get_inode_block(struct super_block *sb,
	 */
	offset = ((ino - 1) % EXT4_INODES_PER_GROUP(sb)) *
		EXT4_INODE_SIZE(sb);
	block = le32_to_cpu(gdp[desc].bg_inode_table) +
	block = ext4_inode_table(gdp + desc) +
			(offset >> EXT4_BLOCK_SIZE_BITS(sb));

	iloc->block_group = block_group;
@@ -2506,7 +2506,7 @@ static int __ext4_get_inode_loc(struct inode *inode,
				goto make_io;

			bitmap_bh = sb_getblk(inode->i_sb,
					le32_to_cpu(desc->bg_inode_bitmap));
				ext4_inode_bitmap(desc));
			if (!bitmap_bh)
				goto make_io;

+28 −24
Original line number Diff line number Diff line
@@ -27,7 +27,7 @@ static int verify_group_input(struct super_block *sb,
{
	struct ext4_sb_info *sbi = EXT4_SB(sb);
	struct ext4_super_block *es = sbi->s_es;
	ext4_fsblk_t start = le32_to_cpu(es->s_blocks_count);
	ext4_fsblk_t start = ext4_blocks_count(es);
	ext4_fsblk_t end = start + input->blocks_count;
	unsigned group = input->group;
	ext4_fsblk_t itend = input->inode_table + sbi->s_itb_per_group;
@@ -68,43 +68,43 @@ static int verify_group_input(struct super_block *sb,
			     end - 1);
	else if (outside(input->block_bitmap, start, end))
		ext4_warning(sb, __FUNCTION__,
			     "Block bitmap not in group (block %u)",
			     "Block bitmap not in group (block %llu)",
			     input->block_bitmap);
	else if (outside(input->inode_bitmap, start, end))
		ext4_warning(sb, __FUNCTION__,
			     "Inode bitmap not in group (block %u)",
			     "Inode bitmap not in group (block %llu)",
			     input->inode_bitmap);
	else if (outside(input->inode_table, start, end) ||
	         outside(itend - 1, start, end))
		ext4_warning(sb, __FUNCTION__,
			     "Inode table not in group (blocks %u-"E3FSBLK")",
			     "Inode table not in group (blocks %llu-%llu)",
			     input->inode_table, itend - 1);
	else if (input->inode_bitmap == input->block_bitmap)
		ext4_warning(sb, __FUNCTION__,
			     "Block bitmap same as inode bitmap (%u)",
			     "Block bitmap same as inode bitmap (%llu)",
			     input->block_bitmap);
	else if (inside(input->block_bitmap, input->inode_table, itend))
		ext4_warning(sb, __FUNCTION__,
			     "Block bitmap (%u) in inode table (%u-"E3FSBLK")",
			     "Block bitmap (%llu) in inode table (%llu-%llu)",
			     input->block_bitmap, input->inode_table, itend-1);
	else if (inside(input->inode_bitmap, input->inode_table, itend))
		ext4_warning(sb, __FUNCTION__,
			     "Inode bitmap (%u) in inode table (%u-"E3FSBLK")",
			     "Inode bitmap (%llu) in inode table (%llu-%llu)",
			     input->inode_bitmap, input->inode_table, itend-1);
	else if (inside(input->block_bitmap, start, metaend))
		ext4_warning(sb, __FUNCTION__,
			     "Block bitmap (%u) in GDT table"
			     "Block bitmap (%llu) in GDT table"
			     " ("E3FSBLK"-"E3FSBLK")",
			     input->block_bitmap, start, metaend - 1);
	else if (inside(input->inode_bitmap, start, metaend))
		ext4_warning(sb, __FUNCTION__,
			     "Inode bitmap (%u) in GDT table"
			     "Inode bitmap (%llu) in GDT table"
			     " ("E3FSBLK"-"E3FSBLK")",
			     input->inode_bitmap, start, metaend - 1);
	else if (inside(input->inode_table, start, metaend) ||
	         inside(itend - 1, start, metaend))
		ext4_warning(sb, __FUNCTION__,
			     "Inode table (%u-"E3FSBLK") overlaps"
			     "Inode table ("E3FSBLK"-"E3FSBLK") overlaps"
			     "GDT table ("E3FSBLK"-"E3FSBLK")",
			     input->inode_table, itend - 1, start, metaend - 1);
	else
@@ -286,6 +286,7 @@ static int setup_new_group_blocks(struct super_block *sb,
	return err;
}


/*
 * Iterate through the groups which hold BACKUP superblock/GDT copies in an
 * ext4 filesystem.  The counters should be initialized to 1, 5, and 7 before
@@ -340,12 +341,15 @@ static int verify_reserved_gdb(struct super_block *sb,
	int gdbackups = 0;

	while ((grp = ext4_list_backups(sb, &three, &five, &seven)) < end) {
		if (le32_to_cpu(*p++) != grp * EXT4_BLOCKS_PER_GROUP(sb) + blk){
		if (le32_to_cpu(*p++) !=
		    grp * EXT4_BLOCKS_PER_GROUP(sb) + blk){
			ext4_warning(sb, __FUNCTION__,
				     "reserved GDT "E3FSBLK
				     " missing grp %d ("E3FSBLK")",
				     blk, grp,
				     grp * EXT4_BLOCKS_PER_GROUP(sb) + blk);
				     grp *
				     (ext4_fsblk_t)EXT4_BLOCKS_PER_GROUP(sb) +
				     blk);
			return -EINVAL;
		}
		if (++gdbackups > EXT4_ADDR_PER_BLOCK(sb))
@@ -731,8 +735,8 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
		return -EPERM;
	}

	if (le32_to_cpu(es->s_blocks_count) + input->blocks_count <
	    le32_to_cpu(es->s_blocks_count)) {
	if (ext4_blocks_count(es) + input->blocks_count <
	    ext4_blocks_count(es)) {
		ext4_warning(sb, __FUNCTION__, "blocks_count overflow\n");
		return -EINVAL;
	}
@@ -830,9 +834,9 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
	/* Update group descriptor block for new group */
	gdp = (struct ext4_group_desc *)primary->b_data + gdb_off;

	gdp->bg_block_bitmap = cpu_to_le32(input->block_bitmap);
	gdp->bg_inode_bitmap = cpu_to_le32(input->inode_bitmap);
	gdp->bg_inode_table = cpu_to_le32(input->inode_table);
	ext4_block_bitmap_set(gdp, input->block_bitmap); /* LV FIXME */
	ext4_inode_bitmap_set(gdp, input->inode_bitmap); /* LV FIXME */
	ext4_inode_table_set(gdp, input->inode_table); /* LV FIXME */
	gdp->bg_free_blocks_count = cpu_to_le16(input->free_blocks_count);
	gdp->bg_free_inodes_count = cpu_to_le16(EXT4_INODES_PER_GROUP(sb));

@@ -846,7 +850,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
	 * blocks/inodes before the group is live won't actually let us
	 * allocate the new space yet.
	 */
	es->s_blocks_count = cpu_to_le32(le32_to_cpu(es->s_blocks_count) +
	ext4_blocks_count_set(es, ext4_blocks_count(es) +
		input->blocks_count);
	es->s_inodes_count = cpu_to_le32(le32_to_cpu(es->s_inodes_count) +
		EXT4_INODES_PER_GROUP(sb));
@@ -882,7 +886,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)

	/* Update the reserved block counts only once the new group is
	 * active. */
	es->s_r_blocks_count = cpu_to_le32(le32_to_cpu(es->s_r_blocks_count) +
	ext4_r_blocks_count_set(es, ext4_r_blocks_count(es) +
		input->reserved_blocks);

	/* Update the free space counts */
@@ -933,7 +937,7 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
	/* We don't need to worry about locking wrt other resizers just
	 * yet: we're going to revalidate es->s_blocks_count after
	 * taking lock_super() below. */
	o_blocks_count = le32_to_cpu(es->s_blocks_count);
	o_blocks_count = ext4_blocks_count(es);
	o_groups_count = EXT4_SB(sb)->s_groups_count;

	if (test_opt(sb, DEBUG))
@@ -1004,7 +1008,7 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
	}

	lock_super(sb);
	if (o_blocks_count != le32_to_cpu(es->s_blocks_count)) {
	if (o_blocks_count != ext4_blocks_count(es)) {
		ext4_warning(sb, __FUNCTION__,
			     "multiple resizers run on filesystem!");
		unlock_super(sb);
@@ -1020,7 +1024,7 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
		ext4_journal_stop(handle);
		goto exit_put;
	}
	es->s_blocks_count = cpu_to_le32(o_blocks_count + add);
	ext4_blocks_count_set(es, o_blocks_count + add);
	ext4_journal_dirty_metadata(handle, EXT4_SB(sb)->s_sbh);
	sb->s_dirt = 1;
	unlock_super(sb);
@@ -1032,8 +1036,8 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
	if ((err = ext4_journal_stop(handle)))
		goto exit_put;
	if (test_opt(sb, DEBUG))
		printk(KERN_DEBUG "EXT4-fs: extended group to %u blocks\n",
		       le32_to_cpu(es->s_blocks_count));
		printk(KERN_DEBUG "EXT4-fs: extended group to %llu blocks\n",
		       ext4_blocks_count(es));
	update_backups(sb, EXT4_SB(sb)->s_sbh->b_blocknr, (char *)es,
		       sizeof(struct ext4_super_block));
exit_put:
+68 −28
Original line number Diff line number Diff line
@@ -62,6 +62,43 @@ static void ext4_unlockfs(struct super_block *sb);
static void ext4_write_super (struct super_block * sb);
static void ext4_write_super_lockfs(struct super_block *sb);


ext4_fsblk_t ext4_block_bitmap(struct ext4_group_desc *bg)
{
	return le32_to_cpu(bg->bg_block_bitmap) |
		((ext4_fsblk_t)le16_to_cpu(bg->bg_block_bitmap_hi) << 32);
}

ext4_fsblk_t ext4_inode_bitmap(struct ext4_group_desc *bg)
{
	return le32_to_cpu(bg->bg_inode_bitmap) |
		((ext4_fsblk_t)le16_to_cpu(bg->bg_inode_bitmap_hi) << 32);
}

ext4_fsblk_t ext4_inode_table(struct ext4_group_desc *bg)
{
	return le32_to_cpu(bg->bg_inode_table) |
		((ext4_fsblk_t)le16_to_cpu(bg->bg_inode_table_hi) << 32);
}

void ext4_block_bitmap_set(struct ext4_group_desc *bg, ext4_fsblk_t blk)
{
	bg->bg_block_bitmap = cpu_to_le32((u32)blk);
	bg->bg_block_bitmap_hi = cpu_to_le16(blk >> 32);
}

void ext4_inode_bitmap_set(struct ext4_group_desc *bg, ext4_fsblk_t blk)
{
	bg->bg_inode_bitmap  = cpu_to_le32((u32)blk);
	bg->bg_inode_bitmap_hi = cpu_to_le16(blk >> 32);
}

void ext4_inode_table_set(struct ext4_group_desc *bg, ext4_fsblk_t blk)
{
	bg->bg_inode_table = cpu_to_le32((u32)blk);
	bg->bg_inode_table_hi = cpu_to_le16(blk >> 32);
}

/*
 * Wrappers for jbd2_journal_start/end.
 *
@@ -1182,6 +1219,9 @@ static int ext4_check_descriptors (struct super_block * sb)
	struct ext4_sb_info *sbi = EXT4_SB(sb);
	ext4_fsblk_t first_block = le32_to_cpu(sbi->s_es->s_first_data_block);
	ext4_fsblk_t last_block;
	ext4_fsblk_t block_bitmap;
	ext4_fsblk_t inode_bitmap;
	ext4_fsblk_t inode_table;
	struct ext4_group_desc * gdp = NULL;
	int desc_block = 0;
	int i;
@@ -1191,7 +1231,7 @@ static int ext4_check_descriptors (struct super_block * sb)
	for (i = 0; i < sbi->s_groups_count; i++)
	{
		if (i == sbi->s_groups_count - 1)
			last_block = le32_to_cpu(sbi->s_es->s_blocks_count) - 1;
			last_block = ext4_blocks_count(sbi->s_es) - 1;
		else
			last_block = first_block +
				(EXT4_BLOCKS_PER_GROUP(sb) - 1);
@@ -1199,42 +1239,39 @@ static int ext4_check_descriptors (struct super_block * sb)
		if ((i % EXT4_DESC_PER_BLOCK(sb)) == 0)
			gdp = (struct ext4_group_desc *)
					sbi->s_group_desc[desc_block++]->b_data;
		if (le32_to_cpu(gdp->bg_block_bitmap) < first_block ||
		    le32_to_cpu(gdp->bg_block_bitmap) > last_block)
		block_bitmap = ext4_block_bitmap(gdp);
		if (block_bitmap < first_block || block_bitmap > last_block)
		{
			ext4_error (sb, "ext4_check_descriptors",
				    "Block bitmap for group %d"
				    " not in group (block %lu)!",
				    i, (unsigned long)
					le32_to_cpu(gdp->bg_block_bitmap));
				    " not in group (block "E3FSBLK")!",
				    i, block_bitmap);
			return 0;
		}
		if (le32_to_cpu(gdp->bg_inode_bitmap) < first_block ||
		    le32_to_cpu(gdp->bg_inode_bitmap) > last_block)
		inode_bitmap = ext4_inode_bitmap(gdp);
		if (inode_bitmap < first_block || inode_bitmap > last_block)
		{
			ext4_error (sb, "ext4_check_descriptors",
				    "Inode bitmap for group %d"
				    " not in group (block %lu)!",
				    i, (unsigned long)
					le32_to_cpu(gdp->bg_inode_bitmap));
				    " not in group (block "E3FSBLK")!",
				    i, inode_bitmap);
			return 0;
		}
		if (le32_to_cpu(gdp->bg_inode_table) < first_block ||
		    le32_to_cpu(gdp->bg_inode_table) + sbi->s_itb_per_group >
		    last_block)
		inode_table = ext4_inode_table(gdp);
		if (inode_table < first_block ||
		    inode_table + sbi->s_itb_per_group > last_block)
		{
			ext4_error (sb, "ext4_check_descriptors",
				    "Inode table for group %d"
				    " not in group (block %lu)!",
				    i, (unsigned long)
					le32_to_cpu(gdp->bg_inode_table));
				    " not in group (block "E3FSBLK")!",
				    i, inode_table);
			return 0;
		}
		first_block += EXT4_BLOCKS_PER_GROUP(sb);
		gdp++;
	}

	sbi->s_es->s_free_blocks_count=cpu_to_le32(ext4_count_free_blocks(sb));
	ext4_free_blocks_count_set(sbi->s_es, ext4_count_free_blocks(sb));
	sbi->s_es->s_free_inodes_count=cpu_to_le32(ext4_count_free_inodes(sb));
	return 1;
}
@@ -1411,6 +1448,7 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
	int i;
	int needs_recovery;
	__le32 features;
	__u64 blocks_count;

	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
	if (!sbi)
@@ -1620,7 +1658,7 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
		goto failed_mount;
	}

	if (le32_to_cpu(es->s_blocks_count) >
	if (ext4_blocks_count(es) >
		    (sector_t)(~0ULL) >> (sb->s_blocksize_bits - 9)) {
		printk(KERN_ERR "EXT4-fs: filesystem on %s:"
			" too large to mount safely\n", sb->s_id);
@@ -1632,9 +1670,11 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)

	if (EXT4_BLOCKS_PER_GROUP(sb) == 0)
		goto cantfind_ext4;
	sbi->s_groups_count = ((le32_to_cpu(es->s_blocks_count) -
			       le32_to_cpu(es->s_first_data_block) - 1)
				       / EXT4_BLOCKS_PER_GROUP(sb)) + 1;
	blocks_count = (ext4_blocks_count(es) -
			le32_to_cpu(es->s_first_data_block) +
			EXT4_BLOCKS_PER_GROUP(sb) - 1);
	do_div(blocks_count, EXT4_BLOCKS_PER_GROUP(sb));
	sbi->s_groups_count = blocks_count;
	db_count = (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) - 1) /
		   EXT4_DESC_PER_BLOCK(sb);
	sbi->s_group_desc = kmalloc(db_count * sizeof (struct buffer_head *),
@@ -1949,7 +1989,7 @@ static journal_t *ext4_get_dev_journal(struct super_block *sb,
		goto out_bdev;
	}

	len = le32_to_cpu(es->s_blocks_count);
	len = ext4_blocks_count(es);
	start = sb_block + 1;
	brelse(bh);	/* we're done with the superblock */

@@ -2119,7 +2159,7 @@ static void ext4_commit_super (struct super_block * sb,
	if (!sbh)
		return;
	es->s_wtime = cpu_to_le32(get_seconds());
	es->s_free_blocks_count = cpu_to_le32(ext4_count_free_blocks(sb));
	ext4_free_blocks_count_set(es, ext4_count_free_blocks(sb));
	es->s_free_inodes_count = cpu_to_le32(ext4_count_free_inodes(sb));
	BUFFER_TRACE(sbh, "marking dirty");
	mark_buffer_dirty(sbh);
@@ -2312,7 +2352,7 @@ static int ext4_remount (struct super_block * sb, int * flags, char * data)
	ext4_init_journal_params(sb, sbi->s_journal);

	if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY) ||
		n_blocks_count > le32_to_cpu(es->s_blocks_count)) {
		n_blocks_count > ext4_blocks_count(es)) {
		if (sbi->s_mount_opt & EXT4_MOUNT_ABORT) {
			err = -EROFS;
			goto restore_opts;
@@ -2431,10 +2471,10 @@ static int ext4_statfs (struct dentry * dentry, struct kstatfs * buf)

	buf->f_type = EXT4_SUPER_MAGIC;
	buf->f_bsize = sb->s_blocksize;
	buf->f_blocks = le32_to_cpu(es->s_blocks_count) - overhead;
	buf->f_blocks = ext4_blocks_count(es) - overhead;
	buf->f_bfree = percpu_counter_sum(&sbi->s_freeblocks_counter);
	buf->f_bavail = buf->f_bfree - le32_to_cpu(es->s_r_blocks_count);
	if (buf->f_bfree < le32_to_cpu(es->s_r_blocks_count))
	buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es);
	if (buf->f_bfree < ext4_r_blocks_count(es))
		buf->f_bavail = 0;
	buf->f_files = le32_to_cpu(es->s_inodes_count);
	buf->f_ffree = percpu_counter_sum(&sbi->s_freeinodes_counter);
Loading