Whamcloud - gitweb
e2fsck: add basic bigalloc support to check (but not yet repair) file systems
authorTheodore Ts'o <tytso@mit.edu>
Fri, 10 Jun 2011 22:58:16 +0000 (18:58 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Fri, 10 Jun 2011 22:58:16 +0000 (18:58 -0400)
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
e2fsck/pass1.c
e2fsck/pass5.c
e2fsck/problem.c
e2fsck/problem.h
e2fsck/super.c
lib/ext2fs/check_desc.c
lib/ext2fs/ext2fs.h

index 67dd986..595d4b2 100644 (file)
@@ -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);
index b423d28..878d1f6 100644 (file)
@@ -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);
index 8f0b211..fb90007 100644 (file)
@@ -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 */
index 7c4c156..38b3c78 100644 (file)
@@ -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
  */
index 1728906..5d6aa7a 100644 (file)
@@ -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;
index 7929cd9..0b7052e 100644 (file)
@@ -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;
 
index 47be91c..a035411 100644 (file)
@@ -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