summaryrefslogtreecommitdiff
path: root/e2fsck
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2007-10-01 09:18:54 -0400
committerTheodore Ts'o <tytso@mit.edu>2007-10-06 12:39:57 -0400
commit0c37f456d929dac47fcf87374f1c1b9a9a96c9fa (patch)
tree7383210edcf8aa6ba42f4f191148a6d6aa1fec0c /e2fsck
parent0cfce7f749ea519522929d91e705cf90518594c4 (diff)
downloade2fsprogs-0c37f456d929dac47fcf87374f1c1b9a9a96c9fa.tar.gz
e2fsck: backup superblocks if key constants have changed
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>
Diffstat (limited to 'e2fsck')
-rw-r--r--e2fsck/e2fsck.h1
-rw-r--r--e2fsck/super.c58
-rw-r--r--e2fsck/unix.c6
3 files changed, 65 insertions, 0 deletions
diff --git a/e2fsck/e2fsck.h b/e2fsck/e2fsck.h
index 57adb2a7..5af82d5c 100644
--- a/e2fsck/e2fsck.h
+++ b/e2fsck/e2fsck.h
@@ -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);
diff --git a/e2fsck/super.c b/e2fsck/super.c
index b4ddca20..a4835f76 100644
--- a/e2fsck/super.c
+++ b/e2fsck/super.c
@@ -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;
+}
diff --git a/e2fsck/unix.c b/e2fsck/unix.c
index fbfd8e20..183116df 100644
--- a/e2fsck/unix.c
+++ b/e2fsck/unix.c
@@ -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");