diff options
author | Theodore Ts'o <tytso@mit.edu> | 2007-10-01 09:18:54 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2007-10-06 12:39:57 -0400 |
commit | 0c37f456d929dac47fcf87374f1c1b9a9a96c9fa (patch) | |
tree | 7383210edcf8aa6ba42f4f191148a6d6aa1fec0c /e2fsck | |
parent | 0cfce7f749ea519522929d91e705cf90518594c4 (diff) | |
download | e2fsprogs-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.h | 1 | ||||
-rw-r--r-- | e2fsck/super.c | 58 | ||||
-rw-r--r-- | e2fsck/unix.c | 6 |
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"); |