Whamcloud - gitweb
Clarify copyright license status of lib/et and lib/ss in the COPYING file
[tools/e2fsprogs.git] / e2fsck / super.c
index e48a030..ae40531 100644 (file)
@@ -220,7 +220,7 @@ static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
                }
                if (retval) {
                        com_err("release_inode_blocks", retval,
-               _("while calling ext2fs_adjust_ea_refocunt for inode %d"),
+               _("while calling ext2fs_adjust_ea_refcount for inode %d"),
                                ino);
                        return 1;
                }
@@ -298,7 +298,7 @@ static int release_orphan_inodes(e2fsck_t ctx)
                if (!inode.i_links_count) {
                        ext2fs_inode_alloc_stats2(fs, ino, -1,
                                                  LINUX_S_ISDIR(inode.i_mode));
-                       inode.i_dtime = time(0);
+                       inode.i_dtime = ctx->now;
                } else {
                        inode.i_dtime = 0;
                }
@@ -329,17 +329,10 @@ void check_resize_inode(e2fsck_t ctx)
        errcode_t       retval;
 
        clear_problem_context(&pctx);
-       pctx.ino = EXT2_RESIZE_INO;
-       retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
-       if (retval) {
-               ctx->flags |= E2F_FLAG_RESIZE_INODE;
-               return;
-       }
 
        /* 
-        * If the resize inode feature isn't set, then
-        * s_reserved_gdt_blocks must be zero, and the resize inode
-        * must be cleared.
+        * If the resize inode feature isn't set, then 
+        * s_reserved_gdt_blocks must be zero.
         */
        if (!(fs->super->s_feature_compat & 
              EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
@@ -351,6 +344,24 @@ void check_resize_inode(e2fsck_t ctx)
                                ext2fs_mark_super_dirty(fs);
                        }
                }
+       }
+
+       /* Read the resize inode */
+       pctx.ino = EXT2_RESIZE_INO;
+       retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
+       if (retval) {
+               if (fs->super->s_feature_compat & 
+                   EXT2_FEATURE_COMPAT_RESIZE_INODE)
+                       ctx->flags |= E2F_FLAG_RESIZE_INODE;
+               return;
+       }
+
+       /* 
+        * If the resize inode feature isn't set, check to make sure 
+        * the resize inode is cleared; then we're done.
+        */
+       if (!(fs->super->s_feature_compat & 
+             EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
                for (i=0; i < EXT2_N_BLOCKS; i++) {
                        if (inode.i_block[i])
                                break;
@@ -363,6 +374,7 @@ void check_resize_inode(e2fsck_t ctx)
                }
                return;
        }
+
        /* 
         * The resize inode feature is enabled; check to make sure the
         * only block in use is the double indirect block
@@ -434,6 +446,7 @@ void check_super_block(e2fsck_t ctx)
        blk_t   bpg_max;
        int     inodes_per_block;
        int     ipg_max;
+       int     inode_size;
        dgrp_t  i;
        blk_t   should_be;
        struct problem_context  pctx;
@@ -482,7 +495,18 @@ void check_super_block(e2fsck_t ctx)
        check_super_value(ctx, "reserved_gdt_blocks", 
                          sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
                          fs->blocksize/4);
-
+       inode_size = EXT2_INODE_SIZE(sb);
+       check_super_value(ctx, "inode_size",
+                         inode_size, MIN_CHECK | MAX_CHECK,
+                         EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize);
+       if (inode_size & (inode_size - 1)) {
+               pctx.num = inode_size;
+               pctx.str = "inode_size";
+               fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
+               ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
+               return;
+       }
+               
        if (!ctx->num_blocks) {
                pctx.errcode = e2fsck_get_device_size(ctx);
                if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) {
@@ -542,15 +566,15 @@ void check_super_block(e2fsck_t ctx)
         * Verify the group descriptors....
         */
        first_block =  sb->s_first_data_block;
-       last_block = first_block + blocks_per_group;
 
        for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
                pctx.group = i;
-               
-               if (i == fs->group_desc_count - 1)
-                       last_block = sb->s_blocks_count;
+
+               first_block = ext2fs_group_first_block(fs, i);
+               last_block = ext2fs_group_last_block(fs, i);
+
                if ((gd->bg_block_bitmap < first_block) ||
-                   (gd->bg_block_bitmap >= last_block)) {
+                   (gd->bg_block_bitmap > last_block)) {
                        pctx.blk = gd->bg_block_bitmap;
                        if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
                                gd->bg_block_bitmap = 0;
@@ -560,7 +584,7 @@ void check_super_block(e2fsck_t ctx)
                        ctx->invalid_bitmaps++;
                }
                if ((gd->bg_inode_bitmap < first_block) ||
-                   (gd->bg_inode_bitmap >= last_block)) {
+                   (gd->bg_inode_bitmap > last_block)) {
                        pctx.blk = gd->bg_inode_bitmap;
                        if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
                                gd->bg_inode_bitmap = 0;
@@ -571,7 +595,7 @@ void check_super_block(e2fsck_t ctx)
                }
                if ((gd->bg_inode_table < first_block) ||
                    ((gd->bg_inode_table +
-                     fs->inode_blocks_per_group - 1) >= last_block)) {
+                     fs->inode_blocks_per_group - 1) > last_block)) {
                        pctx.blk = gd->bg_inode_table;
                        if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
                                gd->bg_inode_table = 0;
@@ -582,8 +606,6 @@ void check_super_block(e2fsck_t ctx)
                }
                free_blocks += gd->bg_free_blocks_count;
                free_inodes += gd->bg_free_inodes_count;
-               first_block += sb->s_blocks_per_group;
-               last_block += sb->s_blocks_per_group;
 
                if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
                    (gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
@@ -681,9 +703,34 @@ void check_super_block(e2fsck_t ctx)
                ext2fs_mark_super_dirty(fs);
        }
 
+       /* 
+        * Check to see if the superblock last mount time or last
+        * write time is in the future.
+        */
+       if (fs->super->s_mtime > ctx->now) {
+               pctx.num = fs->super->s_mtime;
+               if (fix_problem(ctx, PR_0_FUTURE_SB_LAST_MOUNT, &pctx)) {
+                       fs->super->s_mtime = ctx->now;
+                       ext2fs_mark_super_dirty(fs);
+               }
+       }
+       if (fs->super->s_wtime > ctx->now) {
+               pctx.num = fs->super->s_wtime;
+               if (fix_problem(ctx, PR_0_FUTURE_SB_LAST_WRITE, &pctx)) {
+                       fs->super->s_wtime = ctx->now;
+                       ext2fs_mark_super_dirty(fs);
+               }
+       }
+
        /*
         * Move the ext3 journal file, if necessary.
         */
        e2fsck_move_ext3_journal(ctx);
+
+       /*
+        * Fix journal hint, if necessary
+        */
+       e2fsck_fix_ext3_journal_hint(ctx);
+
        return;
 }