diff options
-rw-r--r-- | fs/jbd2/commit.c | 19 | ||||
-rw-r--r-- | fs/jbd2/recovery.c | 31 |
2 files changed, 50 insertions, 0 deletions
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 5d505cfd21c2..16e1fe2a769f 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c | |||
@@ -85,6 +85,24 @@ nope: | |||
85 | __brelse(bh); | 85 | __brelse(bh); |
86 | } | 86 | } |
87 | 87 | ||
88 | static void jbd2_commit_block_csum_set(journal_t *j, | ||
89 | struct journal_head *descriptor) | ||
90 | { | ||
91 | struct commit_header *h; | ||
92 | __u32 csum; | ||
93 | |||
94 | if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) | ||
95 | return; | ||
96 | |||
97 | h = (struct commit_header *)(jh2bh(descriptor)->b_data); | ||
98 | h->h_chksum_type = 0; | ||
99 | h->h_chksum_size = 0; | ||
100 | h->h_chksum[0] = 0; | ||
101 | csum = jbd2_chksum(j, j->j_csum_seed, jh2bh(descriptor)->b_data, | ||
102 | j->j_blocksize); | ||
103 | h->h_chksum[0] = cpu_to_be32(csum); | ||
104 | } | ||
105 | |||
88 | /* | 106 | /* |
89 | * Done it all: now submit the commit record. We should have | 107 | * Done it all: now submit the commit record. We should have |
90 | * cleaned up our previous buffers by now, so if we are in abort | 108 | * cleaned up our previous buffers by now, so if we are in abort |
@@ -128,6 +146,7 @@ static int journal_submit_commit_record(journal_t *journal, | |||
128 | tmp->h_chksum_size = JBD2_CRC32_CHKSUM_SIZE; | 146 | tmp->h_chksum_size = JBD2_CRC32_CHKSUM_SIZE; |
129 | tmp->h_chksum[0] = cpu_to_be32(crc32_sum); | 147 | tmp->h_chksum[0] = cpu_to_be32(crc32_sum); |
130 | } | 148 | } |
149 | jbd2_commit_block_csum_set(journal, descriptor); | ||
131 | 150 | ||
132 | JBUFFER_TRACE(descriptor, "submit commit block"); | 151 | JBUFFER_TRACE(descriptor, "submit commit block"); |
133 | lock_buffer(bh); | 152 | lock_buffer(bh); |
diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c index 066ee603db50..df4a20e7d854 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, | |||
375 | return 0; | 375 | return 0; |
376 | } | 376 | } |
377 | 377 | ||
378 | static int jbd2_commit_block_csum_verify(journal_t *j, void *buf) | ||
379 | { | ||
380 | struct commit_header *h; | ||
381 | __u32 provided, calculated; | ||
382 | |||
383 | if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) | ||
384 | return 1; | ||
385 | |||
386 | h = buf; | ||
387 | provided = h->h_chksum[0]; | ||
388 | h->h_chksum[0] = 0; | ||
389 | calculated = jbd2_chksum(j, j->j_csum_seed, buf, j->j_blocksize); | ||
390 | h->h_chksum[0] = provided; | ||
391 | |||
392 | provided = be32_to_cpu(provided); | ||
393 | return provided == calculated; | ||
394 | } | ||
395 | |||
378 | static int do_one_pass(journal_t *journal, | 396 | static int do_one_pass(journal_t *journal, |
379 | struct recovery_info *info, enum passtype pass) | 397 | struct recovery_info *info, enum passtype pass) |
380 | { | 398 | { |
@@ -685,6 +703,19 @@ static int do_one_pass(journal_t *journal, | |||
685 | } | 703 | } |
686 | crc32_sum = ~0; | 704 | crc32_sum = ~0; |
687 | } | 705 | } |
706 | if (pass == PASS_SCAN && | ||
707 | !jbd2_commit_block_csum_verify(journal, | ||
708 | bh->b_data)) { | ||
709 | info->end_transaction = next_commit_ID; | ||
710 | |||
711 | if (!JBD2_HAS_INCOMPAT_FEATURE(journal, | ||
712 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) { | ||
713 | journal->j_failed_commit = | ||
714 | next_commit_ID; | ||
715 | brelse(bh); | ||
716 | break; | ||
717 | } | ||
718 | } | ||
688 | brelse(bh); | 719 | brelse(bh); |
689 | next_commit_ID++; | 720 | next_commit_ID++; |
690 | continue; | 721 | continue; |