mirror of
https://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git
synced 2024-11-28 12:34:13 +08:00
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>
This commit is contained in:
parent
0cfce7f749
commit
0c37f456d9
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user