aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jbd2
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@us.ibm.com>2012-05-27 08:10:25 -0400
committerTheodore Ts'o <tytso@mit.edu>2012-05-27 08:10:25 -0400
commit1f56c5890e3e815c6f4eabfc87a8a81f439b6f3d (patch)
tree667650c31970f9a89b26d701bf595c5599776eda /fs/jbd2
parent3caa487f53f65fd1e3950a6b6ae1709e6c43b334 (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')
-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;