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);