From: Theodore Ts'o Date: Sun, 7 Oct 2001 06:13:30 +0000 (-0400) Subject: journal.c (clear_v2_journal_fields, e2fsck_journal_load): If the X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=62e3e7fe4f32c2186e848f37b7f977835975413e;p=tools%2Fe2fsprogs.git journal.c (clear_v2_journal_fields, e2fsck_journal_load): If the V2 fields are set on a V1 journal superblock, or an internal V2 journal has s_nr_users is non-zero, clear the entire journal superblock beyond the V1 superblock. This fixes botched V1->V2 updates. problem.c, problem.h (PR_0_CLEAR_V2_JOURNAL): Add new problem code. f_bad_local_jnl: New test which tests for a V2 journal with bad fields caused by a botched V1->V2 upgrade. --- diff --git a/e2fsck/ChangeLog b/e2fsck/ChangeLog index ad944da..629b012 100644 --- a/e2fsck/ChangeLog +++ b/e2fsck/ChangeLog @@ -1,3 +1,13 @@ +2001-10-07 Theodore Tso + + * journal.c (clear_v2_journal_fields, e2fsck_journal_load): If the + V2 fields are set on a V1 journal superblock, or an + internal V2 journal has s_nr_users is non-zero, clear the + entire journal superblock beyond the V1 superblock. This + fixes botched V1->V2 updates. + + * problem.c, problem.h (PR_0_CLEAR_V2_JOURNAL): Add new problem code. + 2001-09-20 Theodore Tso * e2fsck.h, journal.c (e2fsck_move_ext3_journal): Add new function diff --git a/e2fsck/journal.c b/e2fsck/journal.c index 0bff025..62d4812 100644 --- a/e2fsck/journal.c +++ b/e2fsck/journal.c @@ -351,6 +351,24 @@ static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx, return 0; } +#define V1_SB_SIZE 0x0024 +static void clear_v2_journal_fields(journal_t *journal) +{ + e2fsck_t ctx = journal->j_dev; + struct buffer_head *jbh = journal->j_sb_buffer; + struct problem_context pctx; + + clear_problem_context(&pctx); + + if (!fix_problem(ctx, PR_0_CLEAR_V2_JOURNAL, &pctx)) + return; + + memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0, + ctx->fs->blocksize-V1_SB_SIZE); + mark_buffer_dirty(journal->j_sb_buffer, 1); +} + + static errcode_t e2fsck_journal_load(journal_t *journal) { e2fsck_t ctx = journal->j_dev; @@ -375,10 +393,18 @@ static errcode_t e2fsck_journal_load(journal_t *journal) switch (ntohl(jsb->s_header.h_blocktype)) { case JFS_SUPERBLOCK_V1: journal->j_format_version = 1; + if (jsb->s_feature_compat || + jsb->s_feature_incompat || + jsb->s_feature_ro_compat || + jsb->s_nr_users) + clear_v2_journal_fields(journal); break; case JFS_SUPERBLOCK_V2: journal->j_format_version = 2; + if (jsb->s_nr_users && + (ctx->fs->io == ctx->journal_io)) + clear_v2_journal_fields(journal); if (ntohl(jsb->s_nr_users) > 1) { fix_problem(ctx, PR_0_JOURNAL_UNSUPP_MULTIFS, &pctx); return EXT2_ET_JOURNAL_UNSUPP_VERSION; diff --git a/e2fsck/problem.c b/e2fsck/problem.c index 34f4f30..58b8724 100644 --- a/e2fsck/problem.c +++ b/e2fsck/problem.c @@ -287,6 +287,12 @@ static const struct e2fsck_problem problem_table[] = { N_("Error moving @j: %m\n\n"), PROMPT_NONE, 0 }, + /* Clearing V2 journal superblock */ + { PR_0_CLEAR_V2_JOURNAL, + N_("Found invalid V2 @j @S fields (from V1 journal).\n" + "Clearing fields beyond the V1 @j @S...\n\n"), + PROMPT_NONE, 0 }, + /* Pass 1 errors */ /* Pass 1: Checking inodes, blocks, and sizes */ diff --git a/e2fsck/problem.h b/e2fsck/problem.h index e7ddf76..6a234b7 100644 --- a/e2fsck/problem.h +++ b/e2fsck/problem.h @@ -161,6 +161,9 @@ struct problem_context { /* Error moving journal */ #define PR_0_ERR_MOVE_JOURNAL 0x000029 +/* Clearing V2 journal superblock */ +#define PR_0_CLEAR_V2_JOURNAL 0x00002A + /* * Pass 1 errors */ diff --git a/tests/ChangeLog b/tests/ChangeLog index 9b0e810..2fd5c6c 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,8 @@ +2001-10-07 Theodore Tso + + * f_bad_local_jnl: New test which tests for a V2 journal with bad + fields caused by a botched V1->V2 upgrade. + 2001-09-20 Theodore Tso * Release of E2fsprogs 1.25 diff --git a/tests/f_bad_local_jnl/expect.1 b/tests/f_bad_local_jnl/expect.1 new file mode 100644 index 0000000..d8f6551 --- /dev/null +++ b/tests/f_bad_local_jnl/expect.1 @@ -0,0 +1,10 @@ +Found invalid V2 journal superblock fields (from V1 journal). +Clearing fields beyond the V1 journal superblock... + +Pass 1: Checking inodes, blocks, and sizes +Pass 2: Checking directory structure +Pass 3: Checking directory connectivity +Pass 4: Checking reference counts +Pass 5: Checking group summary information +test_filesys: 11/256 files (0.0% non-contiguous), 1080/8192 blocks +Exit status is 0 diff --git a/tests/f_bad_local_jnl/expect.2 b/tests/f_bad_local_jnl/expect.2 new file mode 100644 index 0000000..632dc71 --- /dev/null +++ b/tests/f_bad_local_jnl/expect.2 @@ -0,0 +1,7 @@ +Pass 1: Checking inodes, blocks, and sizes +Pass 2: Checking directory structure +Pass 3: Checking directory connectivity +Pass 4: Checking reference counts +Pass 5: Checking group summary information +test_filesys: 11/256 files (0.0% non-contiguous), 1080/8192 blocks +Exit status is 0 diff --git a/tests/f_bad_local_jnl/image.gz b/tests/f_bad_local_jnl/image.gz new file mode 100644 index 0000000..addd58a Binary files /dev/null and b/tests/f_bad_local_jnl/image.gz differ diff --git a/tests/f_bad_local_jnl/name b/tests/f_bad_local_jnl/name new file mode 100644 index 0000000..8b77264 --- /dev/null +++ b/tests/f_bad_local_jnl/name @@ -0,0 +1 @@ +test for corrupt local journal (bad V1->V2 journal upgrade)