summaryrefslogtreecommitdiff
path: root/e2fsck/journal.c
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2014-09-08 16:11:43 -0700
committerTheodore Ts'o <tytso@mit.edu>2014-09-11 12:40:54 -0400
commit38d5adf33993264d8db78ebb3d924e9d9e155590 (patch)
treec8518731a667f9852f9b07bce49d2143a197ff31 /e2fsck/journal.c
parent330cebc0e95aa8d81477a63932381bcc84eea3c1 (diff)
downloade2fsprogs-38d5adf33993264d8db78ebb3d924e9d9e155590.tar.gz
e2fsck/debugfs: fix descriptor block size handling errors with journal_csum
It turns out that there are some serious problems with the on-disk format of journal checksum v2. The foremost is that the function to calculate descriptor tag size returns sizes that are too big. This causes alignment issues on some architectures and is compounded by the fact that some parts of jbd2 use the structure size (incorrectly) to determine the presence of a 64bit journal instead of checking the feature flags. These errors regrettably lead to the journal corruption reported by Mr. Reardon. Therefore, introduce journal checksum v3, which enlarges the descriptor block tag format to allow for full 32-bit checksums of journal blocks, fix the journal tag function to return the correct sizes, and fix the jbd2 recovery code to use feature flags to determine 64bitness. Add a few function helpers so we don't have to open-code quite so many pieces. Switching to a 16-byte block size was found to increase journal size overhead by a maximum of 0.1%, to convert a 32-bit journal with no checksumming to a 32-bit journal with checksum v3 enabled. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Reported-by: TR Reardon <thomas_reardon@hotmail.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'e2fsck/journal.c')
-rw-r--r--e2fsck/journal.c14
1 files changed, 9 insertions, 5 deletions
diff --git a/e2fsck/journal.c b/e2fsck/journal.c
index 533b1d6f..a19d40b6 100644
--- a/e2fsck/journal.c
+++ b/e2fsck/journal.c
@@ -44,7 +44,7 @@ static int bh_count = 0;
static int e2fsck_journal_verify_csum_type(journal_t *j,
journal_superblock_t *jsb)
{
- if (!JFS_HAS_INCOMPAT_FEATURE(j, JFS_FEATURE_INCOMPAT_CSUM_V2))
+ if (!journal_has_csum_v2or3(j))
return 1;
return jsb->s_checksum_type == JBD2_CRC32C_CHKSUM;
@@ -68,7 +68,7 @@ static int e2fsck_journal_sb_csum_verify(journal_t *j,
{
__u32 provided, calculated;
- if (!JFS_HAS_INCOMPAT_FEATURE(j, JFS_FEATURE_INCOMPAT_CSUM_V2))
+ if (!journal_has_csum_v2or3(j))
return 1;
provided = ext2fs_be32_to_cpu(jsb->s_checksum);
@@ -82,7 +82,7 @@ static errcode_t e2fsck_journal_sb_csum_set(journal_t *j,
{
__u32 crc;
- if (!JFS_HAS_INCOMPAT_FEATURE(j, JFS_FEATURE_INCOMPAT_CSUM_V2))
+ if (!journal_has_csum_v2or3(j))
return 0;
crc = e2fsck_journal_sb_csum(jsb);
@@ -623,8 +623,12 @@ static errcode_t e2fsck_journal_load(journal_t *journal)
if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
return EXT2_ET_RO_UNSUPP_FEATURE;
- /* Checksum v1 and v2 are mutually exclusive features. */
+ /* Checksum v1-3 are mutually exclusive features. */
if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_CSUM_V2) &&
+ JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_CSUM_V3))
+ return EXT2_ET_CORRUPT_SUPERBLOCK;
+
+ if (journal_has_csum_v2or3(journal) &&
JFS_HAS_COMPAT_FEATURE(journal, JFS_FEATURE_COMPAT_CHECKSUM))
return EXT2_ET_CORRUPT_SUPERBLOCK;
@@ -632,7 +636,7 @@ static errcode_t e2fsck_journal_load(journal_t *journal)
!e2fsck_journal_sb_csum_verify(journal, jsb))
return EXT2_ET_CORRUPT_SUPERBLOCK;
- if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_CSUM_V2))
+ if (journal_has_csum_v2or3(journal))
journal->j_csum_seed = jbd2_chksum(journal, ~0, jsb->s_uuid,
sizeof(jsb->s_uuid));