ChangeLog, e2fsck.h, journal.c, problem.c, problem.h, super.c:
super.c (check_super_block): Be more strict on checking
s_r_blocks_count superblock field.
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.
journal.c (e2fsck_journal_reset_super): initialize the journal
sequence number to a random value to avoid recovering bad transactions
from a corrupt journal.
diff --git a/e2fsck/ChangeLog b/e2fsck/ChangeLog
index 60cd802..1fd3e1a 100644
--- a/e2fsck/ChangeLog
+++ b/e2fsck/ChangeLog
@@ -1,3 +1,25 @@
+2001-05-14 Theodore Tso <tytso@valinux.com>
+
+ * super.c (check_super_block): Be more strict on checking
+ s_r_blocks_count superblock field.
+
+2001-05-13 Theodore Tso <tytso@valinux.com>
+
+ * 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 <adilger@turbolinux.com>
+
+ * 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 <tytso@valinux.com>
* journal.c: Code cleanup; initialize journal_enable_debug using
diff --git a/e2fsck/e2fsck.h b/e2fsck/e2fsck.h
index 1c7ecf9..1e42fd9 100644
--- a/e2fsck/e2fsck.h
+++ b/e2fsck/e2fsck.h
@@ -114,6 +114,7 @@
#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 2b5260f..f5366bb 100644
--- a/e2fsck/journal.c
+++ b/e2fsck/journal.c
@@ -289,6 +289,7 @@
"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 @@
}
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 @@
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 @@
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 a44f014..2ac545c 100644
--- a/e2fsck/problem.c
+++ b/e2fsck/problem.c
@@ -112,7 +112,7 @@
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 @@
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 @@
"@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 b6c0d00..1c4ffe3 100644
--- a/e2fsck/problem.h
+++ b/e2fsck/problem.h
@@ -145,6 +145,15 @@
/* 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 ce78715..7a4a64a 100644
--- a/e2fsck/super.c
+++ b/e2fsck/super.c
@@ -336,7 +336,7 @@
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);