Whamcloud - gitweb
Add SIGINT and SIGTERM handling to fsck and e2fsck. For e2fsck,
[tools/e2fsprogs.git] / e2fsck / super.c
index 352a6b4..49e9750 100644 (file)
@@ -172,6 +172,9 @@ static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
        errcode_t                       retval;
        struct process_block_struct     pb;
 
+       if (!ext2fs_inode_has_valid_blocks(inode))
+               return 0;
+
        pb.buf = block_buf + 3 * ctx->fs->blocksize;
        pb.ctx = ctx;
        pb.abort = 0;
@@ -234,6 +237,14 @@ static int release_orphan_inodes(e2fsck_t ctx)
         */
        fs->super->s_last_orphan = 0;
        ext2fs_mark_super_dirty(fs);
+
+       /*
+        * If the filesystem contains errors, don't run the orphan
+        * list, since the orphan list can't be trusted; and we're
+        * going to be running a full e2fsck run anyway...
+        */
+       if (fs->super->s_state & EXT2_ERROR_FS)
+               return 0;
        
        if ((ino < EXT2_FIRST_INODE(fs->super)) ||
            (ino > fs->super->s_inodes_count)) {
@@ -252,7 +263,8 @@ static int release_orphan_inodes(e2fsck_t ctx)
                clear_problem_context(&pctx);
                pctx.ino = ino;
                pctx.inode = &inode;
-               pctx.str = inode.i_links_count ? "Truncating" : "Clearing";
+               pctx.str = inode.i_links_count ? _("Truncating") :
+                       _("Clearing");
 
                fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx);
 
@@ -282,6 +294,7 @@ static int release_orphan_inodes(e2fsck_t ctx)
                e2fsck_write_inode(ctx, ino, &inode, "delete_file");
                ino = next_ino;
        }
+       ext2fs_free_mem((void **) &block_buf);
        return 0;
 return_abort:
        ext2fs_free_mem((void **) &block_buf);
@@ -295,14 +308,20 @@ void check_super_block(e2fsck_t ctx)
        blk_t   first_block, last_block;
        struct ext2_super_block *sb = fs->super;
        blk_t   blocks_per_group = fs->super->s_blocks_per_group;
+       blk_t   bpg_max;
        int     inodes_per_block;
+       int     ipg_max;
        dgrp_t  i;
        blk_t   should_be;
        struct problem_context  pctx;
-       
-       inodes_per_block = (EXT2_INODE_SIZE(fs->super) + 
-                           EXT2_BLOCK_SIZE(fs->super) - 1) /
-                                   EXT2_BLOCK_SIZE(fs->super);
+
+       inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
+       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);
+       if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb))
+               bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb);
 
        ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
                 sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap");
@@ -310,7 +329,7 @@ void check_super_block(e2fsck_t ctx)
                 sizeof(int) * fs->group_desc_count, "invalid_block_bitmap");
        ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx,
                sizeof(int) * fs->group_desc_count, "invalid_inode_table");
-               
+
        clear_problem_context(&pctx);
 
        /*
@@ -322,20 +341,20 @@ void check_super_block(e2fsck_t ctx)
                          MIN_CHECK, 1, 0);
        check_super_value(ctx, "first_data_block", sb->s_first_data_block,
                          MAX_CHECK, 0, sb->s_blocks_count);
-       check_super_value(ctx, "log_frag_size", sb->s_log_frag_size,
-                         MAX_CHECK, 0, 2);
        check_super_value(ctx, "log_block_size", sb->s_log_block_size,
-                         MIN_CHECK | MAX_CHECK, sb->s_log_frag_size,
-                         2);
+                         MIN_CHECK | MAX_CHECK, 0,
+                         EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE);
+       check_super_value(ctx, "log_frag_size", sb->s_log_frag_size,
+                         MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size);
        check_super_value(ctx, "frags_per_group", sb->s_frags_per_group,
-                         MIN_CHECK | MAX_CHECK, 1, 8 * EXT2_BLOCK_SIZE(sb));
+                         MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group,
+                         bpg_max);
        check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group,
-                         MIN_CHECK | MAX_CHECK, 1, 8 * EXT2_BLOCK_SIZE(sb));
+                         MIN_CHECK | MAX_CHECK, 8, bpg_max);
        check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group,
-                         MIN_CHECK | MAX_CHECK, 1,
-                         inodes_per_block * blocks_per_group);
+                         MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max);
        check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count,
-                         MAX_CHECK, 0, sb->s_blocks_count);
+                         MAX_CHECK, 0, sb->s_blocks_count / 4);
 
        if (!ctx->num_blocks) {
                pctx.errcode = e2fsck_get_device_size(ctx);
@@ -406,30 +425,33 @@ void check_super_block(e2fsck_t ctx)
                if ((fs->group_desc[i].bg_block_bitmap < first_block) ||
                    (fs->group_desc[i].bg_block_bitmap >= last_block)) {
                        pctx.blk = fs->group_desc[i].bg_block_bitmap;
-                       if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx)) {
+                       if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
                                fs->group_desc[i].bg_block_bitmap = 0;
-                               ctx->invalid_block_bitmap_flag[i]++;
-                               ctx->invalid_bitmaps++;
-                       }
+               }
+               if (fs->group_desc[i].bg_block_bitmap == 0) {
+                       ctx->invalid_block_bitmap_flag[i]++;
+                       ctx->invalid_bitmaps++;
                }
                if ((fs->group_desc[i].bg_inode_bitmap < first_block) ||
                    (fs->group_desc[i].bg_inode_bitmap >= last_block)) {
                        pctx.blk = fs->group_desc[i].bg_inode_bitmap;
-                       if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx)) {
+                       if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
                                fs->group_desc[i].bg_inode_bitmap = 0;
-                               ctx->invalid_inode_bitmap_flag[i]++;
-                               ctx->invalid_bitmaps++;
-                       }
+               }
+               if (fs->group_desc[i].bg_inode_bitmap == 0) {
+                       ctx->invalid_inode_bitmap_flag[i]++;
+                       ctx->invalid_bitmaps++;
                }
                if ((fs->group_desc[i].bg_inode_table < first_block) ||
                    ((fs->group_desc[i].bg_inode_table +
                      fs->inode_blocks_per_group - 1) >= last_block)) {
                        pctx.blk = fs->group_desc[i].bg_inode_table;
-                       if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx)) {
+                       if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
                                fs->group_desc[i].bg_inode_table = 0;
-                               ctx->invalid_inode_table_flag[i]++;
-                               ctx->invalid_bitmaps++;
-                       }
+               }
+               if (fs->group_desc[i].bg_inode_table == 0) {
+                       ctx->invalid_inode_table_flag[i]++;
+                       ctx->invalid_bitmaps++;
                }
                first_block += fs->super->s_blocks_per_group;
                last_block += fs->super->s_blocks_per_group;
@@ -497,6 +519,10 @@ void check_super_block(e2fsck_t ctx)
                ext2fs_mark_super_dirty(fs);
        }
 
+       /*
+        * Move the ext3 journal file, if necessary.
+        */
+       e2fsck_move_ext3_journal(ctx);
        return;
 }