[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20210527085707.91688-1-artem.blagodarenko@gmail.com>
Date: Thu, 27 May 2021 04:57:07 -0400
From: Artem Blagodarenko <artem.blagodarenko@...il.com>
To: linux-ext4@...r.kernel.org
Cc: adilger.kernel@...ger.ca,
Artem Blagodarenko <artem.blagodarenko@...il.com>
Subject: [PATCH] e2fsck: replay all commits except broken ones
E2fsck interrupts journal replay if a broken transaction is found.
Journal is replayed partly. Some useful transactions are not replayed.
Let's change this behavior and process all transactions except broken ones
if "-E repair_journal" option is set.
HPE-bug-id: LUS-9452
---
e2fsck/e2fsck.h | 1 +
e2fsck/journal.c | 3 +++
e2fsck/recovery.c | 41 +++++++++++++++++++++++++++++++----------
e2fsck/unix.c | 3 +++
lib/e2p/feature.c | 2 ++
lib/ext2fs/kernel-jbd.h | 5 ++++-
misc/ext4.5.in | 4 ++++
7 files changed, 48 insertions(+), 11 deletions(-)
diff --git a/e2fsck/e2fsck.h b/e2fsck/e2fsck.h
index 15d043ee..7dccc8e4 100644
--- a/e2fsck/e2fsck.h
+++ b/e2fsck/e2fsck.h
@@ -179,6 +179,7 @@ struct resource_track {
#define E2F_OPT_UNSHARE_BLOCKS 0x40000
#define E2F_OPT_CLEAR_UNINIT 0x80000 /* Hack to clear the uninit bit */
#define E2F_OPT_CHECK_ENCODING 0x100000 /* Force verification of encoded filenames */
+#define E2F_OPT_REPAIR_JOURNAL 0x200000 /* Apply all possible from journal */
/*
* E2fsck flags
diff --git a/e2fsck/journal.c b/e2fsck/journal.c
index a425bbd1..9b84c477 100644
--- a/e2fsck/journal.c
+++ b/e2fsck/journal.c
@@ -1620,6 +1620,9 @@ static errcode_t recover_ext3_journal(e2fsck_t ctx)
if (retval)
return retval;
+ if (ctx->options & E2F_OPT_REPAIR_JOURNAL)
+ jbd2_set_feature_repair(journal);
+
retval = e2fsck_journal_load(journal);
if (retval)
goto errout;
diff --git a/e2fsck/recovery.c b/e2fsck/recovery.c
index dc0694fc..5aa3e529 100644
--- a/e2fsck/recovery.c
+++ b/e2fsck/recovery.c
@@ -33,6 +33,7 @@ struct recovery_info
int nr_replays;
int nr_revokes;
int nr_revoke_hits;
+ int nr_skipped;
};
static int do_one_pass(journal_t *journal,
@@ -313,8 +314,9 @@ int jbd2_journal_recover(journal_t *journal)
jbd_debug(1, "JBD2: recovery, exit status %d, "
"recovered transactions %u to %u\n",
err, info.start_transaction, info.end_transaction);
- jbd_debug(1, "JBD2: Replayed %d and revoked %d/%d blocks\n",
- info.nr_replays, info.nr_revoke_hits, info.nr_revokes);
+ jbd_debug(1, "JBD2: Replayed %d, skipped %d, and revoked %d/%d blocks\n",
+ info.nr_replays, info.nr_skipped, info.nr_revoke_hits,
+ info.nr_revokes);
/* Restart the log at the next transaction ID, thus invalidating
* any existing commit records in the log. */
@@ -787,16 +789,35 @@ static int do_one_pass(journal_t *journal,
}
/* Neither checksum match nor unused? */
- if (!((crc32_sum == found_chksum &&
- cbh->h_chksum_type ==
- JBD2_CRC32_CHKSUM &&
- cbh->h_chksum_size ==
- JBD2_CRC32_CHKSUM_SIZE) ||
- (cbh->h_chksum_type == 0 &&
- cbh->h_chksum_size == 0 &&
- found_chksum == 0)))
+ if (cbh->h_chksum_type == 0 &&
+ cbh->h_chksum_size == 0 &&
+ found_chksum == 0)
goto chksum_error;
+ if (!(crc32_sum = found_chksum &&
+ cbh->h_chksum_type == JBD2_CRC32_CHKSUM &&
+ cbh->h_chksum_size ==
+ JBD2_CRC32_CHKSUM_SIZE)) {
+ if (jbd2_has_feature_repair(journal)) {
+ /*
+ * Commit with wrong checksum.
+ * Let's skip it. There are
+ * some corect commits after.
+ */
+ ++info->nr_skipped;
+ jbd_debug(1, "JBD2: "
+ "crc32_sum(0x%x)i !="
+ " found_chksum(0x%x)"
+ ". Skipped.\n",
+ crc32_sum,
+ found_chksum);
+ brelse(bh);
+ next_commit_ID++;
+ } else {
+ goto chksum_error;
+ }
+ }
+
crc32_sum = ~0;
}
if (pass == PASS_SCAN &&
diff --git a/e2fsck/unix.c b/e2fsck/unix.c
index c5f9e441..fc7649fc 100644
--- a/e2fsck/unix.c
+++ b/e2fsck/unix.c
@@ -763,6 +763,9 @@ static void parse_extended_opts(e2fsck_t ctx, const char *opts)
ctx->options |= E2F_OPT_CLEAR_UNINIT;
continue;
#endif
+ } else if (strcmp(token, "repair_journal") == 0) {
+ ctx->options |= E2F_OPT_REPAIR_JOURNAL;
+ continue;
} else {
fprintf(stderr, _("Unknown extended option: %s\n"),
token);
diff --git a/lib/e2p/feature.c b/lib/e2p/feature.c
index 22910602..6cd11384 100644
--- a/lib/e2p/feature.c
+++ b/lib/e2p/feature.c
@@ -134,6 +134,8 @@ static struct feature jrnl_feature_list[] = {
"journal_checksum_v2" },
{ E2P_FEATURE_INCOMPAT, JBD2_FEATURE_INCOMPAT_CSUM_V3,
"journal_checksum_v3" },
+ { E2P_FEATURE_INCOMPAT, JBD2_FEATURE_INCOMPAT_REPAIR,
+ "journal_repair" },
{ 0, 0, 0 },
};
diff --git a/lib/ext2fs/kernel-jbd.h b/lib/ext2fs/kernel-jbd.h
index 2978ccb6..4a2cef20 100644
--- a/lib/ext2fs/kernel-jbd.h
+++ b/lib/ext2fs/kernel-jbd.h
@@ -265,6 +265,7 @@ typedef struct journal_superblock_s
#define JBD2_FEATURE_INCOMPAT_CSUM_V2 0x00000008
#define JBD2_FEATURE_INCOMPAT_CSUM_V3 0x00000010
#define JBD2_FEATURE_INCOMPAT_FAST_COMMIT 0x00000020
+#define JBD2_FEATURE_INCOMPAT_REPAIR 0x00000040
/* Features known to this kernel version: */
#define JBD2_KNOWN_COMPAT_FEATURES 0
@@ -274,7 +275,8 @@ typedef struct journal_superblock_s
JBD2_FEATURE_INCOMPAT_64BIT|\
JBD2_FEATURE_INCOMPAT_CSUM_V2| \
JBD2_FEATURE_INCOMPAT_CSUM_V3 | \
- JBD2_FEATURE_INCOMPAT_FAST_COMMIT)
+ JBD2_FEATURE_INCOMPAT_FAST_COMMIT | \
+ JBD2_FEATURE_INCOMPAT_REPAIR)
#ifdef NO_INLINE_FUNCS
extern size_t journal_tag_bytes(journal_t *journal);
@@ -392,6 +394,7 @@ JBD2_FEATURE_INCOMPAT_FUNCS(async_commit, ASYNC_COMMIT)
JBD2_FEATURE_INCOMPAT_FUNCS(csum2, CSUM_V2)
JBD2_FEATURE_INCOMPAT_FUNCS(csum3, CSUM_V3)
JBD2_FEATURE_INCOMPAT_FUNCS(fast_commit, FAST_COMMIT)
+JBD2_FEATURE_INCOMPAT_FUNCS(repair, REPAIR)
#if (defined(E2FSCK_INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS))
/*
diff --git a/misc/ext4.5.in b/misc/ext4.5.in
index 90bc4f88..95266864 100644
--- a/misc/ext4.5.in
+++ b/misc/ext4.5.in
@@ -574,6 +574,10 @@ Commit block can be written to disk without waiting for descriptor blocks. If
enabled older kernels cannot mount the device.
This will enable 'journal_checksum' internally.
.TP
+.B journal_repair
+If journal is broken, apply all valid transactions and pass
+all broken ones(with invalid crc).
+.TP
.BR barrier=0 " / " barrier=1 " / " barrier " / " nobarrier
These mount options have the same effect as in ext3. The mount options
"barrier" and "nobarrier" are added for consistency with other ext4 mount
--
2.18.4
Powered by blists - more mailing lists