Whamcloud - gitweb
e2fsck: backup superblocks if key constants have changed
authorTheodore Ts'o <tytso@mit.edu>
Mon, 1 Oct 2007 13:18:54 +0000 (09:18 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Sat, 6 Oct 2007 16:39:57 +0000 (12:39 -0400)
If the primary superblock differs from the backup superblock in
certain key respects, force a full check (if e2fsck was invoked in
preen mode).  If the filesystem check passes cleanly, and the
filesystem was opened in read/write mode, then write the primary
superblock to all of the backups.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
e2fsck/e2fsck.h
e2fsck/super.c
e2fsck/unix.c

index 57adb2a..5af82d5 100644 (file)
@@ -454,6 +454,7 @@ void e2fsck_rehash_directories(e2fsck_t ctx);
 
 /* super.c */
 void check_super_block(e2fsck_t ctx);
+int check_backup_super_block(e2fsck_t ctx);
 
 /* swapfs.c */
 void swap_filesys(e2fsck_t ctx);
index b4ddca2..a4835f7 100644 (file)
@@ -770,3 +770,61 @@ void check_super_block(e2fsck_t ctx)
 
        return;
 }
+
+/*
+ * Check to see if we should backup the master sb to the backup super
+ * blocks.
+ */
+int check_backup_super_block(e2fsck_t ctx)
+{
+       ext2_filsys     fs = ctx->fs;
+       ext2_filsys     tfs = 0;
+       io_manager      io_ptr;
+       errcode_t       retval;
+       dgrp_t          g;
+       blk_t           sb;
+       int             ret = 0;
+
+       /*
+        * If we are already writing out the backup blocks, then we
+        * don't need to test.  Also, if the filesystem is invalid, or
+        * the check was aborted or cancelled, we also don't want to
+        * do the backup.  If the filesystem was opened read-only then
+        * we can't do the backup.
+        */
+       if (((fs->flags & EXT2_FLAG_MASTER_SB_ONLY) == 0) ||
+           !ext2fs_test_valid(fs) ||
+           (fs->super->s_state & EXT2_ERROR_FS) ||
+           (ctx->flags & (E2F_FLAG_ABORT | E2F_FLAG_CANCEL)) ||
+           (ctx->options & E2F_OPT_READONLY))
+               return 0;
+
+       for (g = 1; g < fs->group_desc_count; g++) {
+               if (!ext2fs_bg_has_super(fs, g))
+                       continue;
+
+               sb = fs->super->s_first_data_block +
+                       (g * fs->super->s_blocks_per_group);
+
+               retval = ext2fs_open(ctx->filesystem_name, 0,
+                                    sb, fs->blocksize,
+                                    fs->io->manager, &tfs);
+               if (retval) {
+                       tfs = 0;
+                       continue;
+               }
+
+#define SUPER_DIFFERENT(x) (fs->super->x != tfs->super->x)
+               if (SUPER_DIFFERENT(s_feature_compat) ||
+                   SUPER_DIFFERENT(s_feature_incompat) ||
+                   SUPER_DIFFERENT(s_feature_ro_compat) ||
+                   SUPER_DIFFERENT(s_blocks_count) ||
+                   SUPER_DIFFERENT(s_inodes_count) ||
+                   memcmp(fs->super->s_uuid, tfs->super->s_uuid,
+                          sizeof(fs->super->s_uuid)))
+                       ret = 1;
+               ext2fs_close(tfs);
+               break;
+       }
+       return ret;
+}
index fbfd8e2..183116d 100644 (file)
@@ -280,6 +280,8 @@ static void check_if_skip(e2fsck_t ctx)
                reason = _(" contains a file system with errors");
        else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
                reason = _(" was not cleanly unmounted");
+       else if (check_backup_super_block(ctx))
+               reason = _(" primary superblock features different from backup");
        else if ((fs->super->s_max_mnt_count > 0) &&
                 (fs->super->s_mnt_count >=
                  (unsigned) fs->super->s_max_mnt_count)) {
@@ -1292,6 +1294,10 @@ no_journal:
        }
        if (run_result & E2F_FLAG_ABORT)
                fatal_error(ctx, _("aborted"));
+       if (check_backup_super_block(ctx)) {
+               fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
+               ext2fs_mark_super_dirty(fs);
+       }
 
 #ifdef MTRACE
        mtrace_print("Cleanup");