|
@@ -393,6 +393,23 @@ static int jbd2_commit_block_csum_verify(journal_t *j, void *buf)
|
|
|
return provided == calculated;
|
|
|
}
|
|
|
|
|
|
+static int jbd2_block_tag_csum_verify(journal_t *j, journal_block_tag_t *tag,
|
|
|
+ void *buf, __u32 sequence)
|
|
|
+{
|
|
|
+ __u32 provided, calculated;
|
|
|
+
|
|
|
+ if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
|
|
|
+ return 1;
|
|
|
+
|
|
|
+ sequence = cpu_to_be32(sequence);
|
|
|
+ calculated = jbd2_chksum(j, j->j_csum_seed, (__u8 *)&sequence,
|
|
|
+ sizeof(sequence));
|
|
|
+ calculated = jbd2_chksum(j, calculated, buf, j->j_blocksize);
|
|
|
+ provided = be32_to_cpu(tag->t_checksum);
|
|
|
+
|
|
|
+ return provided == cpu_to_be32(calculated);
|
|
|
+}
|
|
|
+
|
|
|
static int do_one_pass(journal_t *journal,
|
|
|
struct recovery_info *info, enum passtype pass)
|
|
|
{
|
|
@@ -569,6 +586,19 @@ static int do_one_pass(journal_t *journal,
|
|
|
goto skip_write;
|
|
|
}
|
|
|
|
|
|
+ /* Look for block corruption */
|
|
|
+ if (!jbd2_block_tag_csum_verify(
|
|
|
+ journal, tag, obh->b_data,
|
|
|
+ be32_to_cpu(tmp->h_sequence))) {
|
|
|
+ brelse(obh);
|
|
|
+ success = -EIO;
|
|
|
+ printk(KERN_ERR "JBD: Invalid "
|
|
|
+ "checksum recovering "
|
|
|
+ "block %llu in log\n",
|
|
|
+ blocknr);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
/* Find a buffer for the new
|
|
|
* data being restored */
|
|
|
nbh = __getblk(journal->j_fs_dev,
|