summaryrefslogtreecommitdiff
path: root/e2fsck
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2001-10-07 02:13:30 -0400
committerTheodore Ts'o <tytso@mit.edu>2001-10-07 02:13:30 -0400
commit62e3e7fe4f32c2186e848f37b7f977835975413e (patch)
treef8a89e8f421f08b0277cfb2286e1ed1bbd59c832 /e2fsck
parent773fd8a1d4202af708a37bdc7754134e6fdcfe22 (diff)
downloade2fsprogs-62e3e7fe4f32c2186e848f37b7f977835975413e.tar.gz
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.
Diffstat (limited to 'e2fsck')
-rw-r--r--e2fsck/ChangeLog10
-rw-r--r--e2fsck/journal.c26
-rw-r--r--e2fsck/problem.c6
-rw-r--r--e2fsck/problem.h3
4 files changed, 45 insertions, 0 deletions
diff --git a/e2fsck/ChangeLog b/e2fsck/ChangeLog
index ad944da0..629b0127 100644
--- a/e2fsck/ChangeLog
+++ b/e2fsck/ChangeLog
@@ -1,3 +1,13 @@
+2001-10-07 Theodore Tso <tytso@valinux.com>
+
+ * 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 <tytso@valinux.com>
* e2fsck.h, journal.c (e2fsck_move_ext3_journal): Add new function
diff --git a/e2fsck/journal.c b/e2fsck/journal.c
index 0bff025a..62d4812f 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 34f4f305..58b87244 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 e7ddf768..6a234b7f 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
*/