[PATCH] resize2fs: Fix support for the uninit_bg feature

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

 



Signed-off-by: "Theodore Ts'o" <tytso@xxxxxxx>
---
 resize/main.c      |    6 ----
 resize/resize2fs.c |   83 ++++++++++++++++++++++++++++++++++++++++-----------
 2 files changed, 65 insertions(+), 24 deletions(-)

diff --git a/resize/main.c b/resize/main.c
index e26cd8b..d7097ad 100644
--- a/resize/main.c
+++ b/resize/main.c
@@ -307,12 +307,6 @@ int main (int argc, char ** argv)
 		exit (1);
 	}
 
-	if (fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) {
-		com_err(program_name, EXT2_ET_RO_UNSUPP_FEATURE,
-			":- uninit_bg");
-		exit(1);
-	}
-
 	/*
 	 * Check for compatibility with the feature sets.  We need to
 	 * be more stringent than ext2fs_open().
diff --git a/resize/resize2fs.c b/resize/resize2fs.c
index 2d53873..027315c 100644
--- a/resize/resize2fs.c
+++ b/resize/resize2fs.c
@@ -188,7 +188,7 @@ errcode_t adjust_fs_info(ext2_filsys fs, ext2_filsys old_fs, blk_t new_size)
 	int		adj, old_numblocks, numblocks, adjblocks;
 	unsigned long	i, j, old_desc_blocks, max_group;
 	unsigned int	meta_bg, meta_bg_size;
-	int		has_super;
+	int		has_super, csum_flag;
 	unsigned long long new_inodes;	/* u64 to check for overflow */
 
 	fs->super->s_blocks_count = new_size;
@@ -359,6 +359,8 @@ retry:
 	group_block = fs->super->s_first_data_block +
 		old_fs->group_desc_count * fs->super->s_blocks_per_group;
 
+	csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
+					       EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
 	adj = old_fs->group_desc_count;
 	max_group = fs->group_desc_count - adj;
 	if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
@@ -372,18 +374,26 @@ retry:
 		       sizeof(struct ext2_group_desc));
 		adjblocks = 0;
 
+		fs->group_desc[i].bg_flags = 0;
+		if (csum_flag)
+			fs->group_desc[i].bg_flags |= EXT2_BG_INODE_UNINIT |
+				EXT2_BG_INODE_ZEROED;
 		if (i == 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
+		} else {
 			numblocks = fs->super->s_blocks_per_group;
+			if (csum_flag)
+				fs->group_desc[i].bg_flags |=
+					EXT2_BG_BLOCK_UNINIT;
+		}
 
 		has_super = ext2fs_bg_has_super(fs, i);
 		if (has_super) {
-			ext2fs_mark_block_bitmap(fs->block_map, group_block);
+			ext2fs_block_alloc_stats(fs, group_block, +1);
 			adjblocks++;
 		}
 		meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super);
@@ -393,8 +403,8 @@ retry:
 		    (meta_bg < fs->super->s_first_meta_bg)) {
 			if (has_super) {
 				for (j=0; j < old_desc_blocks; j++)
-					ext2fs_mark_block_bitmap(fs->block_map,
-							 group_block + 1 + j);
+					ext2fs_block_alloc_stats(fs,
+						 group_block + 1 + j, +1);
 				adjblocks += old_desc_blocks;
 			}
 		} else {
@@ -403,8 +413,8 @@ retry:
 			if (((i % meta_bg_size) == 0) ||
 			    ((i % meta_bg_size) == 1) ||
 			    ((i % meta_bg_size) == (meta_bg_size-1)))
-				ext2fs_mark_block_bitmap(fs->block_map,
-						 group_block + has_super);
+				ext2fs_block_alloc_stats(fs,
+						 group_block + has_super, +1);
 		}
 		
 		adjblocks += 2 + fs->inode_blocks_per_group;
@@ -597,7 +607,7 @@ static void mark_fs_metablock(ext2_resize_t rfs,
 	ext2_filsys 	fs = rfs->new_fs;
 	
 	ext2fs_mark_block_bitmap(rfs->reserve_blocks, blk);
-	ext2fs_mark_block_bitmap(fs->block_map, blk);
+	ext2fs_block_alloc_stats(fs, blk, +1);
 
 	/*
 	 * Check to see if we overlap with the inode or block bitmap,
@@ -707,8 +717,7 @@ static errcode_t blocks_to_move(ext2_resize_t rfs)
 			}
 			for (blk = group_blk+1+new_blocks;
 			     blk < group_blk+1+old_blocks; blk++) {
-				ext2fs_unmark_block_bitmap(fs->block_map,
-							   blk);
+				ext2fs_block_alloc_stats(fs, blk, -1);
 				rfs->needed_blocks--;
 			}
 			group_blk += fs->super->s_blocks_per_group;
@@ -781,7 +790,7 @@ static errcode_t blocks_to_move(ext2_resize_t rfs)
 		 */
 		if (FS_BLOCK_BM(old_fs, i) !=
 		    (blk = FS_BLOCK_BM(fs, i))) {
-			ext2fs_mark_block_bitmap(fs->block_map, blk);
+			ext2fs_block_alloc_stats(fs, blk, +1);
 			if (ext2fs_test_block_bitmap(old_fs->block_map, blk) &&
 			    !ext2fs_test_block_bitmap(meta_bmap, blk))
 				ext2fs_mark_block_bitmap(rfs->move_blocks,
@@ -789,7 +798,7 @@ static errcode_t blocks_to_move(ext2_resize_t rfs)
 		}
 		if (FS_INODE_BM(old_fs, i) !=
 		    (blk = FS_INODE_BM(fs, i))) {
-			ext2fs_mark_block_bitmap(fs->block_map, blk);
+			ext2fs_block_alloc_stats(fs, blk, +1);
 			if (ext2fs_test_block_bitmap(old_fs->block_map, blk) &&
 			    !ext2fs_test_block_bitmap(meta_bmap, blk))
 				ext2fs_mark_block_bitmap(rfs->move_blocks,
@@ -815,7 +824,7 @@ static errcode_t blocks_to_move(ext2_resize_t rfs)
 		 */
 		for (blk = fs->group_desc[i].bg_inode_table, j=0;
 		     j < fs->inode_blocks_per_group ; j++, blk++) {
-			ext2fs_mark_block_bitmap(fs->block_map, blk);
+			ext2fs_block_alloc_stats(fs, blk, +1);
 			if (ext2fs_test_block_bitmap(old_fs->block_map, blk) &&
 			    !ext2fs_test_block_bitmap(meta_bmap, blk))
 				ext2fs_mark_block_bitmap(rfs->move_blocks,
@@ -953,7 +962,7 @@ static errcode_t block_mover(ext2_resize_t rfs)
 			retval = ENOSPC;
 			goto errout;
 		}
-		ext2fs_mark_block_bitmap(fs->block_map, new_blk);
+		ext2fs_block_alloc_stats(fs, new_blk, +1);
 		ext2fs_add_extent_entry(rfs->bmap, blk, new_blk);
 		to_move++;
 	}
@@ -1222,7 +1231,8 @@ static errcode_t inode_scan_and_fix(ext2_resize_t rfs)
 				goto errout;
 			}
 		}
-		ext2fs_mark_inode_bitmap(rfs->new_fs->inode_map, new_inode);
+		ext2fs_inode_alloc_stats2(rfs->new_fs, new_inode, +1,
+					  pb.is_dir);
 		if (pb.changed) {
 			/* Get the new version of the inode */
 			retval = ext2fs_read_inode_full(rfs->old_fs, ino,
@@ -1491,7 +1501,7 @@ static errcode_t move_itables(ext2_resize_t rfs)
 
 		for (blk = rfs->old_fs->group_desc[i].bg_inode_table, j=0;
 		     j < fs->inode_blocks_per_group ; j++, blk++)
-			ext2fs_unmark_block_bitmap(fs->block_map, blk);
+			ext2fs_block_alloc_stats(fs, blk, -1);
 
 		rfs->old_fs->group_desc[i].bg_inode_table = new_blk;
 		ext2fs_group_desc_csum_set(rfs->old_fs, i);
@@ -1579,13 +1589,35 @@ static errcode_t ext2fs_calculate_summary_stats(ext2_filsys fs)
 	unsigned int	count = 0;
 	int		total_free = 0;
 	int		group_free = 0;
+	int		uninit = 0;
+	blk_t		super_blk, old_desc_blk, new_desc_blk;
+	int		old_desc_blocks;
 
 	/*
 	 * First calculate the block statistics
 	 */
+	uninit = fs->group_desc[group].bg_flags & EXT2_BG_BLOCK_UNINIT;
+	ext2fs_super_and_bgd_loc(fs, group, &super_blk, &old_desc_blk,
+				 &new_desc_blk, 0);
+	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;
 	for (blk = fs->super->s_first_data_block;
 	     blk < fs->super->s_blocks_count; blk++) {
-		if (!ext2fs_fast_test_block_bitmap(fs->block_map, blk)) {
+		if ((uninit &&
+		     !((blk == super_blk) ||
+		       ((old_desc_blk && old_desc_blocks &&
+			 (blk >= old_desc_blk) &&
+			 (blk < old_desc_blk + old_desc_blocks))) ||
+		       ((new_desc_blk && (blk == new_desc_blk))) ||
+		       (blk == fs->group_desc[group].bg_block_bitmap) ||
+		       (blk == fs->group_desc[group].bg_inode_bitmap) ||
+		       ((blk >= fs->group_desc[group].bg_inode_table &&
+			 (blk < fs->group_desc[group].bg_inode_table
+			  + fs->inode_blocks_per_group))))) ||
+		    (!ext2fs_fast_test_block_bitmap(fs->block_map, blk))) {
 			group_free++;
 			total_free++;
 		}
@@ -1598,6 +1630,17 @@ static errcode_t ext2fs_calculate_summary_stats(ext2_filsys fs)
 			group++;
 			count = 0;
 			group_free = 0;
+			uninit = (fs->group_desc[group].bg_flags &
+				  EXT2_BG_BLOCK_UNINIT);
+			ext2fs_super_and_bgd_loc(fs, group, &super_blk,
+						 &old_desc_blk,
+						 &new_desc_blk, 0);
+			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;
 		}
 	}
 	fs->super->s_free_blocks_count = total_free;
@@ -1611,8 +1654,10 @@ static errcode_t ext2fs_calculate_summary_stats(ext2_filsys fs)
 	group = 0;
 
 	/* Protect loop from wrap-around if s_inodes_count maxed */
+	uninit = fs->group_desc[group].bg_flags & EXT2_BG_INODE_UNINIT;
 	for (ino = 1; ino <= fs->super->s_inodes_count && ino > 0; ino++) {
-		if (!ext2fs_fast_test_inode_bitmap(fs->inode_map, ino)) {
+		if (uninit ||
+		    !ext2fs_fast_test_inode_bitmap(fs->inode_map, ino)) {
 			group_free++;
 			total_free++;
 		}
@@ -1625,6 +1670,8 @@ static errcode_t ext2fs_calculate_summary_stats(ext2_filsys fs)
 			group++;
 			count = 0;
 			group_free = 0;
+			uninit = (fs->group_desc[group].bg_flags &
+				  EXT2_BG_INODE_UNINIT);
 		}
 	}
 	fs->super->s_free_inodes_count = total_free;
-- 
1.5.6.rc3.1.g36b7.dirty

--
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