diff --git a/e2fsck/ChangeLog b/e2fsck/ChangeLog index 60cd802f..1fd3e1aa 100644 --- a/e2fsck/ChangeLog +++ b/e2fsck/ChangeLog @@ -1,3 +1,25 @@ +2001-05-14 Theodore Tso + + * super.c (check_super_block): Be more strict on checking + s_r_blocks_count superblock field. + +2001-05-13 Theodore Tso + + * problem.c, problem.h (PR_0_JOURNAL_UNSUPP_ROCOMPAT, + PR_0_JOURNAL_UNSUPP_INCOMPAT, PR_0_JOURNAL_RESET_COMPAT): + New problem codes. + + * journal.c (e2fsck_journal_load): Use a problem code to + report unsupported feature flags. There is code to + clear unsupported flags, but since this is dangerous, + it's not allowed in the problem code table. + +2001-05-11 Andreas Dilger + + * journal.c (e2fsck_journal_reset_super): initialize the journal + sequence number to a random value to avoid recovering + bad transactions from a corrupt journal. + 2001-05-13 Theodore Tso * journal.c: Code cleanup; initialize journal_enable_debug using diff --git a/e2fsck/e2fsck.h b/e2fsck/e2fsck.h index 1c7ecf97..1e42fd92 100644 --- a/e2fsck/e2fsck.h +++ b/e2fsck/e2fsck.h @@ -114,6 +114,7 @@ struct resource_track { #define E2F_FLAG_PROG_BAR 0x0020 /* Progress bar on screen */ #define E2F_FLAG_PROG_SUPPRESS 0x0040 /* Progress suspended */ +#define E2F_FLAG_JOURNAL_INODE 0x0080 /* Create a new ext3 journal inode */ /* * Defines for indicating the e2fsck pass number diff --git a/e2fsck/journal.c b/e2fsck/journal.c index 2b5260f7..f5366bb2 100644 --- a/e2fsck/journal.c +++ b/e2fsck/journal.c @@ -289,6 +289,7 @@ static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx, "filesystem is now ext2 only ***\n\n"); sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL; sb->s_journal_inum = 0; + ctx->flags |= E2F_FLAG_JOURNAL_INODE; /* FIXME: todo */ e2fsck_clear_recover(ctx, 1); return 0; } @@ -344,17 +345,17 @@ static errcode_t e2fsck_journal_load(journal_t *journal) } if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES)) { - com_err(ctx->program_name, EXT2_ET_UNSUPP_FEATURE, - _("%s: journal has incompatible features\n"), - ctx->device_name); - return EXT2_ET_UNSUPP_FEATURE; + if (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_INCOMPAT, &pctx)) + return EXT2_ET_UNSUPP_FEATURE; + journal->j_superblock->s_feature_incompat &= + JFS_KNOWN_INCOMPAT_FEATURES; } - + if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES)) { - com_err(ctx->program_name, EXT2_ET_UNSUPP_FEATURE, - _("%s: journal has readonly-incompatible features\n"), - ctx->device_name); - return EXT2_ET_RO_UNSUPP_FEATURE; + if (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_ROCOMPAT, &pctx)) + return EXT2_ET_RO_UNSUPP_FEATURE; + journal->j_superblock->s_feature_ro_compat &= + JFS_KNOWN_ROCOMPAT_FEATURES; } /* We have now checked whether we know enough about the journal @@ -389,7 +390,13 @@ static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb, journal_t *journal) { char *p; - + union { + uuid_t uuid; + __u32 val[4]; + } u; + __u32 new_seq = 0; + int i; + /* Leave a valid existing V1 superblock signature alone. * Anything unrecognisable we overwrite with a new V2 * signature. */ @@ -410,9 +417,15 @@ static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb, jsb->s_first = htonl(1); jsb->s_sequence = htonl(1); - /* In theory we should also re-zero the entire journal here. - * Initialising s_sequence to a random value would be a - * reasonable compromise. */ + /* Initialize the journal sequence number so that there is "no" + * chance we will find old "valid" transactions in the journal. + * This avoids the need to zero the whole journal (slow to do, + * and risky when we are just recovering the filesystem). + */ + uuid_generate(u.uuid); + for (i = 0; i < 4; i ++) + new_seq ^= u.val[i]; + jsb->s_sequence = htonl(new_seq); ll_rw_block(WRITE, 1, &journal->j_sb_buffer); } diff --git a/e2fsck/problem.c b/e2fsck/problem.c index a44f014d..2ac545c6 100644 --- a/e2fsck/problem.c +++ b/e2fsck/problem.c @@ -112,7 +112,7 @@ static const struct e2fsck_problem problem_table[] = { N_("\nThe @S could not be read or does not describe a correct ext2\n" "@f. If the @v is valid and it really contains an ext2\n" "@f (and not swap or ufs or something else), then the @S\n" - "is corrupt, and you might try running e2fsck with an alternate @S:\n" + "is corrupt, and you might try running e2fsck with an alternate @S:\n" " e2fsck -b %S <@v>\n\n"), PROMPT_NONE, PR_FATAL }, @@ -200,9 +200,12 @@ static const struct e2fsck_problem problem_table[] = { PROMPT_CLEAR, PR_PREEN_OK }, /* Journal has an unknown superblock type */ - { PR_0_JOURNAL_UNSUPP_SUPER, - N_("Ext3 @j @S is unknown type %N (unsupported).\n"), - PROMPT_ABORT, PR_NO_OK | PR_AFTER_CODE, PR_0_JOURNAL_BAD_SUPER }, + { PR_0_JOURNAL_UNSUPP_SUPER, + N_("Ext3 @j @S is unknown type %N (unsupported).\n" + "It is likely that your copy of e2fsck is old and/or doesn't " + "support this @j format.\n" + "It is also possible the @j @S is corrupt.\n"), + PROMPT_ABORT, PR_NO_OK | PR_AFTER_CODE, PR_0_JOURNAL_BAD_SUPER }, /* Journal superblock is corrupt */ { PR_0_JOURNAL_BAD_SUPER, @@ -259,6 +262,21 @@ static const struct e2fsck_problem problem_table[] = { "@f has feature flag(s) set, but is a revision 0 @f. ", PROMPT_FIX, PR_PREEN_OK | PR_NO_OK }, + /* Journal superblock has an unknown read-only feature flag set */ + { PR_0_JOURNAL_UNSUPP_ROCOMPAT, + N_("Ext3 @j @S has an unknown read-only feature flag set.\n"), + PROMPT_NONE, PR_FATAL, PR_0_JOURNAL_RESET_COMPAT }, + + /* Journal superblock has an unknown incompatible feature flag set */ + { PR_0_JOURNAL_UNSUPP_INCOMPAT, + N_("Ext3 @j @S has an unknown incompatible feature flag set.\n"), + PROMPT_NONE, PR_FATAL, PR_0_JOURNAL_RESET_COMPAT }, + + /* Journal superblock has an unknown feature flag set */ + { PR_0_JOURNAL_RESET_COMPAT, + N_("Ext3 @j @S has bad feature flag(s) set.\n"), + PROMPT_CLEAR, PR_PREEN_OK|PR_PREEN_NOMSG }, + /* Pass 1 errors */ /* Pass 1: Checking inodes, blocks, and sizes */ diff --git a/e2fsck/problem.h b/e2fsck/problem.h index b6c0d007..1c4ffe38 100644 --- a/e2fsck/problem.h +++ b/e2fsck/problem.h @@ -145,6 +145,15 @@ struct problem_context { /* Illegal inode in orphaned inode list */ #define PR_0_ORPHAN_ILLEGAL_INODE 0x000024 +/* Journal has unsupported read-only feature - abort */ +#define PR_0_JOURNAL_UNSUPP_ROCOMPAT 0x000025 + +/* Journal has unsupported incompatible feature - abort */ +#define PR_0_JOURNAL_UNSUPP_INCOMPAT 0x000026 + +/* Journal has unsupported feature - reset */ +#define PR_0_JOURNAL_RESET_COMPAT 0x000027 + /* * Pass 1 errors */ diff --git a/e2fsck/super.c b/e2fsck/super.c index ce78715a..7a4a64ab 100644 --- a/e2fsck/super.c +++ b/e2fsck/super.c @@ -336,7 +336,7 @@ void check_super_block(e2fsck_t ctx) MIN_CHECK | MAX_CHECK, inodes_per_block, inodes_per_block * (blocks_per_group-4)); check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count, - MAX_CHECK, 0, sb->s_blocks_count); + MAX_CHECK, 0, sb->s_blocks_count / 4); if (!ctx->num_blocks) { pctx.errcode = e2fsck_get_device_size(ctx);