aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/jbd2/commit.c19
-rw-r--r--fs/jbd2/recovery.c31
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
88static 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
378static 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
378static int do_one_pass(journal_t *journal, 396static 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;