[PATCH: e2fsprogs: resize2fs failed when "mkfs.ext4 -O flex_bg"]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



When mkfs.ext4 with flex_bg option, resize2fs with -M option will fail.

Steps to reproduce:

# mkfs.ext4 -O flex_bg /dev/sda6
# resize2fs /dev/sda6 -M

resize2fs: No space left on device while trying to resize /dev/sda6

I found that the group which hand been moved out its meta-data still 
in the orignally block after resize2fs,but its meta-data was invalidation.
I try to fix it and the patch likes below.

Signed-off-by: Gui Xiaohua <guixh@xxxxxxxxxxxxxx>
--- e2fsprogs-1.41.3/resize/resize2fs.c	2008-10-07 22:22:39.000000000 +0800
+++ e2fsprogs-1.41.3_org/resize/resize2fs.c	2009-02-03 01:56:24.000000000 +0800
@@ -49,6 +49,10 @@ static errcode_t inode_ref_fix(ext2_resi
 static errcode_t move_itables(ext2_resize_t rfs);
 static errcode_t fix_resize_inode(ext2_filsys fs);
 static errcode_t ext2fs_calculate_summary_stats(ext2_filsys fs);
+static int calculate_extent(ext2_filsys fs);
+static blk_t  count_map(ext2fs_block_bitmap bitmap, blk_t begin, blk_t end);
+static void adjust_flex_group(ext2_filsys old_fs, ext2_filsys new_fs);
+
 
 /*
  * Some helper CPP macros
@@ -112,6 +116,12 @@ errcode_t resize_fs(ext2_filsys fs, blk_
 
 	*new_size = rfs->new_fs->super->s_blocks_count;
 
+		/*umark meta-data of would be removed groups*/
+	 if (fs->group_desc_count > rfs->new_fs->group_desc_count &&
+		fs->super->s_log_groups_per_flex) {
+		adjust_flex_group(rfs->old_fs, rfs->new_fs);
+	 }
+
 	retval = blocks_to_move(rfs);
 	if (retval)
 		goto errout;
@@ -1792,7 +1802,7 @@ blk_t calculate_minimum_resize_size(ext2
 {
 	blk_t inode_count, blks_needed, groups, data_blocks;
 	blk_t grp, data_needed, last_start;
-	int overhead = 0, num_of_superblocks = 0;
+	int overhead = 0, num_of_superblocks = 0, extent = 0, i = 0;
 
 	/*
 	 * first figure out how many group descriptors we need to
@@ -1918,5 +1928,110 @@ blk_t calculate_minimum_resize_size(ext2
 	blks_needed = (groups-1) * EXT2_BLOCKS_PER_GROUP(fs->super);
 	blks_needed += overhead;
 
+	/*figure out how many fragment will be produced*/
+	if (fs->group_desc_count > groups && fs->super->s_log_groups_per_flex) {
+		extent = calculate_extent(fs);
+		i = (sizeof(__u32) * EXT2_N_BLOCKS -
+		sizeof(struct ext3_extent_header))/sizeof(struct ext3_extent);
+		if (extent >= i)
+			blks_needed += 1;
+	}
+
 	return blks_needed;
 }
+
+static int calculate_extent(ext2_filsys fs)
+{
+	blk_t start_blk, end_blk, range;
+	dgrp_t group_count;
+	blk_t map = 0;
+	int extent = 0;
+
+	int flex_size = 1 << fs->super->s_log_groups_per_flex;
+	group_count = fs->group_desc_count;
+
+	ext2fs_read_bitmaps(fs);
+	fix_uninit_block_bitmaps(fs);
+
+	/*block_map*/
+	start_blk = fs->group_desc[group_count-1].bg_block_bitmap;
+	end_blk = fs->group_desc[0].bg_block_bitmap + flex_size;
+	range = end_blk - start_blk;
+	map = count_map(fs->block_map, start_blk, end_blk);
+	if (map == range || map == 1)
+		extent += 1;
+	else
+		extent += 2;
+
+	/*inode_map*/
+	start_blk = fs->group_desc[group_count-1].bg_inode_bitmap;
+	end_blk = fs->group_desc[0].bg_inode_bitmap + flex_size;
+	range = end_blk - start_blk;
+	map = count_map(fs->block_map, start_blk, end_blk);
+	if (map == range || map == 1)
+		extent += 1;
+	else
+		extent += 2;
+
+	/*inode_table*/
+	start_blk = fs->group_desc[group_count-1].bg_inode_table +
+			fs->inode_blocks_per_group;
+	end_blk = start_blk + 1;
+	map = count_map(fs->block_map, start_blk, end_blk);
+	if (map)
+		extent += 1;
+
+	return extent;
+}
+
+static blk_t count_map(ext2fs_block_bitmap bitmap, blk_t begin, blk_t end)
+{
+	blk_t map = 0;
+	blk_t i = 0;
+
+	for (i = begin; i < end; i++) {
+		if (ext2fs_test_block_bitmap(bitmap, i))
+			map++;
+	}
+	return map;
+}
+
+static void adjust_flex_group(ext2_filsys old_fs, ext2_filsys new_fs)
+{
+	blk_t			b;
+	unsigned int		j;
+	unsigned int		start, end;
+	dgrp_t			i = new_fs->group_desc_count;
+	ext2fs_block_bitmap new_bitmap = new_fs->block_map;
+	ext2fs_block_bitmap old_bitmap = old_fs->block_map;
+
+	start = ext2fs_get_block_bitmap_start(new_bitmap);
+	end = ext2fs_get_block_bitmap_end(new_bitmap);
+
+	for (; i < old_fs->group_desc_count; i++) {
+		for (j = 0, b = old_fs->group_desc[i].bg_inode_table;
+		     j < (unsigned int) old_fs->inode_blocks_per_group;
+		     j++, b++) {
+			ext2fs_unmark_block_bitmap(old_bitmap, b);
+
+			if (start <= b && end >= b)
+				ext2fs_unmark_block_bitmap(new_bitmap, b);
+		}
+
+		ext2fs_unmark_block_bitmap(old_bitmap,
+				old_fs->group_desc[i].bg_block_bitmap);
+		ext2fs_unmark_block_bitmap(old_bitmap,
+				old_fs->group_desc[i].bg_inode_bitmap);
+		if ((start <= old_fs->group_desc[i].bg_inode_bitmap) &&
+			(end >= old_fs->group_desc[i].bg_inode_bitmap)) {
+			ext2fs_unmark_block_bitmap(new_bitmap,
+					 old_fs->group_desc[i].bg_inode_bitmap);
+		}
+		if ((start <= old_fs->group_desc[i].bg_block_bitmap) &&
+			(end >= old_fs->group_desc[i].bg_block_bitmap)) {
+			ext2fs_unmark_block_bitmap(new_bitmap,
+					 old_fs->group_desc[i].bg_block_bitmap);
+		}
+	}
+}
+



--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Reiser Filesystem Development]     [Ceph FS]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux FS]     [Yosemite National Park]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Device Mapper]     [Linux Media]

  Powered by Linux