From: Theodore Ts'o Date: Fri, 10 Jun 2011 22:58:16 +0000 (-0400) Subject: e2fsck: add basic bigalloc support to check (but not yet repair) file systems X-Git-Tag: v1.42-WIP-0702~25 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=44fe08f1fa1e9a994ff304aa02022c53c9341519;p=thirdparty%2Fe2fsprogs.git e2fsck: add basic bigalloc support to check (but not yet repair) file systems Signed-off-by: "Theodore Ts'o" --- diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c index 67dd986fa..595d4b251 100644 --- a/e2fsck/pass1.c +++ b/e2fsck/pass1.c @@ -617,8 +617,9 @@ void e2fsck_pass1(e2fsck_t ctx) ctx->flags |= E2F_FLAG_ABORT; return; } - pctx.errcode = ext2fs_allocate_block_bitmap(fs, _("in-use block map"), - &ctx->block_found_map); + pctx.errcode = ext2fs_allocate_subcluster_bitmap(fs, + _("in-use block map"), + &ctx->block_found_map); if (pctx.errcode) { pctx.num = 1; fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx); @@ -668,6 +669,14 @@ void e2fsck_pass1(e2fsck_t ctx) } mark_table_blocks(ctx); + pctx.errcode = ext2fs_convert_subcluster_bitmap(fs, + &ctx->block_found_map); + if (pctx.errcode) { + fix_problem(ctx, PR_1_CONVERT_SUBCLUSTER, &pctx); + ctx->flags |= E2F_FLAG_ABORT; + ext2fs_free_mem(&inode); + return; + } block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3, "block interate buffer"); e2fsck_use_inode_shortcuts(ctx, 1); @@ -1789,7 +1798,15 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx, for (blk = extent.e_pblk, blockcnt = extent.e_lblk, i = 0; i < extent.e_len; blk++, blockcnt++, i++) { - mark_block_used(ctx, blk); + if (!(ctx->fs->cluster_ratio_bits && + pb->previous_block && + (EXT2FS_B2C(ctx->fs, blk) == + EXT2FS_B2C(ctx->fs, pb->previous_block)) && + (blk & EXT2FS_CLUSTER_MASK(ctx->fs)) == + (blockcnt & EXT2FS_CLUSTER_MASK(ctx->fs)))) + mark_block_used(ctx, blk); + + pb->previous_block = blk; if (is_dir) { pctx->errcode = ext2fs_add_dir_block2(ctx->fs->dblist, pctx->ino, blk, blockcnt); diff --git a/e2fsck/pass5.c b/e2fsck/pass5.c index b423d287f..878d1f693 100644 --- a/e2fsck/pass5.c +++ b/e2fsck/pass5.c @@ -156,13 +156,13 @@ static void check_block_bitmaps(e2fsck_t ctx) free_array = (int *) e2fsck_allocate_memory(ctx, fs->group_desc_count * sizeof(int), "free block count array"); - if ((fs->super->s_first_data_block < + if ((EXT2FS_B2C(fs, fs->super->s_first_data_block) < ext2fs_get_block_bitmap_start2(ctx->block_found_map)) || - (ext2fs_blocks_count(fs->super)-1 > + (EXT2FS_B2C(fs, ext2fs_blocks_count(fs->super)-1) > ext2fs_get_block_bitmap_end2(ctx->block_found_map))) { pctx.num = 1; - pctx.blk = fs->super->s_first_data_block; - pctx.blk2 = ext2fs_blocks_count(fs->super) -1; + pctx.blk = EXT2FS_B2C(fs, fs->super->s_first_data_block); + pctx.blk2 = EXT2FS_B2C(fs, ext2fs_blocks_count(fs->super) - 1); pctx.ino = ext2fs_get_block_bitmap_start2(ctx->block_found_map); pctx.ino2 = ext2fs_get_block_bitmap_end2(ctx->block_found_map); fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx); @@ -171,13 +171,13 @@ static void check_block_bitmaps(e2fsck_t ctx) goto errout; } - if ((fs->super->s_first_data_block < + if ((EXT2FS_B2C(fs, fs->super->s_first_data_block) < ext2fs_get_block_bitmap_start2(fs->block_map)) || - (ext2fs_blocks_count(fs->super)-1 > + (EXT2FS_B2C(fs, ext2fs_blocks_count(fs->super)-1) > ext2fs_get_block_bitmap_end2(fs->block_map))) { pctx.num = 2; - pctx.blk = fs->super->s_first_data_block; - pctx.blk2 = ext2fs_blocks_count(fs->super) -1; + pctx.blk = EXT2FS_B2C(fs, fs->super->s_first_data_block); + pctx.blk2 = EXT2FS_B2C(fs, ext2fs_blocks_count(fs->super) - 1); pctx.ino = ext2fs_get_block_bitmap_start2(fs->block_map); pctx.ino2 = ext2fs_get_block_bitmap_end2(fs->block_map); fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx); @@ -195,9 +195,9 @@ redo_counts: if (csum_flag && (ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT))) skip_group++; - for (i = fs->super->s_first_data_block; + for (i = EXT2FS_B2C(fs, fs->super->s_first_data_block); i < ext2fs_blocks_count(fs->super); - i++) { + i += EXT2FS_CLUSTER_RATIO(fs)) { actual = ext2fs_fast_test_block_bitmap2(ctx->block_found_map, i); if (skip_group) { @@ -333,8 +333,9 @@ redo_counts: first_free = ext2fs_blocks_count(fs->super); } blocks ++; - if ((blocks == fs->super->s_blocks_per_group) || - (i == ext2fs_blocks_count(fs->super)-1)) { + if ((blocks == fs->super->s_clusters_per_group) || + (EXT2FS_B2C(fs, i) == + EXT2FS_B2C(fs, ext2fs_blocks_count(fs->super)-1))) { free_array[group] = group_free; group ++; blocks = 0; @@ -741,7 +742,7 @@ static void check_block_end(e2fsck_t ctx) clear_problem_context(&pctx); end = ext2fs_get_block_bitmap_start2(fs->block_map) + - ((blk64_t)EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1; + ((blk64_t)EXT2_CLUSTERS_PER_GROUP(fs->super) * fs->group_desc_count) - 1; pctx.errcode = ext2fs_fudge_block_bitmap_end2(fs->block_map, end, &save_blocks_count); if (pctx.errcode) { @@ -755,11 +756,12 @@ static void check_block_end(e2fsck_t ctx) /* Protect loop from wrap-around if end is maxed */ for (i = save_blocks_count + 1; i <= end && i > save_blocks_count; i++) { - if (!ext2fs_test_block_bitmap2(fs->block_map, i)) { + if (!ext2fs_test_block_bitmap2(fs->block_map, + EXT2FS_C2B(fs, i))) { if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) { for (; i <= end; i++) ext2fs_mark_block_bitmap2(fs->block_map, - i); + EXT2FS_C2B(fs, i)); ext2fs_mark_bb_dirty(fs); } else ext2fs_unmark_valid(fs); diff --git a/e2fsck/problem.c b/e2fsck/problem.c index 8f0b211a6..fb9000717 100644 --- a/e2fsck/problem.c +++ b/e2fsck/problem.c @@ -890,6 +890,11 @@ static struct e2fsck_problem problem_table[] = { "(size %Is, lblk %r)\n"), PROMPT_CLEAR, PR_PREEN_OK }, + /* Failed to convert subcluster bitmap */ + { PR_1_CONVERT_SUBCLUSTER, + N_("Error converting subcluster @b @B: %m\n"), + PROMPT_NONE, PR_FATAL }, + /* Pass 1b errors */ /* Pass 1B: Rescan for duplicate/bad blocks */ diff --git a/e2fsck/problem.h b/e2fsck/problem.h index 7c4c1566e..38b3c7848 100644 --- a/e2fsck/problem.h +++ b/e2fsck/problem.h @@ -520,6 +520,9 @@ struct problem_context { /* EOFBLOCKS flag set when not necessary */ #define PR_1_EOFBLOCKS_FL_SET 0x010060 +/* Failed to convert subcluster bitmap */ +#define PR_1_CONVERT_SUBCLUSTER 0x010061 + /* * Pass 1b errors */ diff --git a/e2fsck/super.c b/e2fsck/super.c index 1728906b2..5d6aa7a34 100644 --- a/e2fsck/super.c +++ b/e2fsck/super.c @@ -460,7 +460,7 @@ void check_super_block(e2fsck_t ctx) struct ext2_super_block *sb = fs->super; problem_t problem; blk64_t blocks_per_group = fs->super->s_blocks_per_group; - __u32 bpg_max; + __u32 bpg_max, cpg_max; int inodes_per_block; int ipg_max; int inode_size; @@ -477,7 +477,10 @@ void check_super_block(e2fsck_t ctx) ipg_max = inodes_per_block * (blocks_per_group - 4); if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb)) ipg_max = EXT2_MAX_INODES_PER_GROUP(sb); - bpg_max = 8 * EXT2_BLOCK_SIZE(sb); + cpg_max = 8 * EXT2_BLOCK_SIZE(sb); + if (cpg_max > EXT2_MAX_CLUSTERS_PER_GROUP(sb)) + cpg_max = EXT2_MAX_CLUSTERS_PER_GROUP(sb); + bpg_max = 8 * EXT2_BLOCK_SIZE(sb) * EXT2FS_CLUSTER_RATIO(fs); if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb)) bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb); @@ -508,8 +511,7 @@ void check_super_block(e2fsck_t ctx) (EXT2_MAX_CLUSTER_LOG_SIZE - EXT2_MIN_CLUSTER_LOG_SIZE)); check_super_value(ctx, "clusters_per_group", sb->s_clusters_per_group, - MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group, - bpg_max); + MIN_CHECK | MAX_CHECK, 8, cpg_max); check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group, MIN_CHECK | MAX_CHECK, 8, bpg_max); check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group, @@ -527,6 +529,14 @@ void check_super_block(e2fsck_t ctx) check_super_value(ctx, "inode_size", inode_size, MIN_CHECK | MAX_CHECK, EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize); + if (sb->s_blocks_per_group != (sb->s_clusters_per_group * + EXT2FS_CLUSTER_RATIO(fs))) { + pctx.num = sb->s_clusters_per_group * EXT2FS_CLUSTER_RATIO(fs); + pctx.str = "block_size"; + fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx); + ctx->flags |= E2F_FLAG_ABORT; /* never get here! */ + return; + } if (inode_size & (inode_size - 1)) { pctx.num = inode_size; pctx.str = "inode_size"; @@ -545,14 +555,6 @@ void check_super_block(e2fsck_t ctx) } } - if (sb->s_log_block_size != (__u32) sb->s_log_cluster_size) { - pctx.blk = EXT2_BLOCK_SIZE(sb); - pctx.blk2 = EXT2_CLUSTER_SIZE(sb); - fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx); - ctx->flags |= E2F_FLAG_ABORT; - return; - } - should_be = (sb->s_log_block_size == 0) ? 1 : 0; if (sb->s_first_data_block != should_be) { pctx.blk = sb->s_first_data_block; diff --git a/lib/ext2fs/check_desc.c b/lib/ext2fs/check_desc.c index 7929cd95a..0b7052e86 100644 --- a/lib/ext2fs/check_desc.c +++ b/lib/ext2fs/check_desc.c @@ -41,7 +41,7 @@ errcode_t ext2fs_check_desc(ext2_filsys fs) EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - retval = ext2fs_allocate_block_bitmap(fs, "check_desc map", &bmap); + retval = ext2fs_allocate_subcluster_bitmap(fs, "check_desc map", &bmap); if (retval) return retval; diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h index 47be91c1a..a03541101 100644 --- a/lib/ext2fs/ext2fs.h +++ b/lib/ext2fs/ext2fs.h @@ -553,7 +553,8 @@ typedef struct ext2_icount *ext2_icount_t; EXT2_FEATURE_RO_COMPAT_LARGE_FILE|\ EXT4_FEATURE_RO_COMPAT_DIR_NLINK|\ EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE|\ - EXT4_FEATURE_RO_COMPAT_GDT_CSUM) + EXT4_FEATURE_RO_COMPAT_GDT_CSUM|\ + EXT4_FEATURE_RO_COMPAT_BIGALLOC) /* * These features are only allowed if EXT2_FLAG_SOFTSUPP_FEATURES is passed