diff options
author | Darrick J. Wong <djwong@us.ibm.com> | 2012-05-27 08:10:25 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2012-05-27 08:10:25 -0400 |
commit | 1f56c5890e3e815c6f4eabfc87a8a81f439b6f3d (patch) | |
tree | 667650c31970f9a89b26d701bf595c5599776eda /fs/jbd2/recovery.c | |
parent | 3caa487f53f65fd1e3950a6b6ae1709e6c43b334 (diff) |
jbd2: checksum commit blocks
Calculate and verify the checksum of commit blocks. In checksum v2,
deprecate most of the checksum v1 commit block checksum fields, since
each block has its own checksum.
Signed-off-by: Darrick J. Wong <djwong@us.ibm.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/jbd2/recovery.c')
-rw-r--r-- | fs/jbd2/recovery.c | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c index 066ee603db5..df4a20e7d85 100644 --- a/fs/jbd2/recovery.c +++ b/fs/jbd2/recovery.c @@ -375,6 +375,24 @@ static int calc_chksums(journal_t *journal, struct buffer_head *bh, return 0; } +static int jbd2_commit_block_csum_verify(journal_t *j, void *buf) +{ + struct commit_header *h; + __u32 provided, calculated; + + if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) + return 1; + + h = buf; + provided = h->h_chksum[0]; + h->h_chksum[0] = 0; + calculated = jbd2_chksum(j, j->j_csum_seed, buf, j->j_blocksize); + h->h_chksum[0] = provided; + + provided = be32_to_cpu(provided); + return provided == calculated; +} + static int do_one_pass(journal_t *journal, struct recovery_info *info, enum passtype pass) { @@ -685,6 +703,19 @@ static int do_one_pass(journal_t *journal, } crc32_sum = ~0; } + if (pass == PASS_SCAN && + !jbd2_commit_block_csum_verify(journal, + bh->b_data)) { + info->end_transaction = next_commit_ID; + + if (!JBD2_HAS_INCOMPAT_FEATURE(journal, + JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) { + journal->j_failed_commit = + next_commit_ID; + brelse(bh); + break; + } + } brelse(bh); next_commit_ID++; continue; |