Skip to content

Commit

Permalink
jbd2: checksum commit blocks
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Darrick J. Wong authored and Theodore Ts'o committed May 27, 2012
1 parent 3caa487 commit 1f56c58
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 0 deletions.
19 changes: 19 additions & 0 deletions fs/jbd2/commit.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,24 @@ static void release_buffer_page(struct buffer_head *bh)
__brelse(bh);
}

static void jbd2_commit_block_csum_set(journal_t *j,
struct journal_head *descriptor)
{
struct commit_header *h;
__u32 csum;

if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
return;

h = (struct commit_header *)(jh2bh(descriptor)->b_data);
h->h_chksum_type = 0;
h->h_chksum_size = 0;
h->h_chksum[0] = 0;
csum = jbd2_chksum(j, j->j_csum_seed, jh2bh(descriptor)->b_data,
j->j_blocksize);
h->h_chksum[0] = cpu_to_be32(csum);
}

/*
* Done it all: now submit the commit record. We should have
* cleaned up our previous buffers by now, so if we are in abort
Expand Down Expand Up @@ -128,6 +146,7 @@ static int journal_submit_commit_record(journal_t *journal,
tmp->h_chksum_size = JBD2_CRC32_CHKSUM_SIZE;
tmp->h_chksum[0] = cpu_to_be32(crc32_sum);
}
jbd2_commit_block_csum_set(journal, descriptor);

JBUFFER_TRACE(descriptor, "submit commit block");
lock_buffer(bh);
Expand Down
31 changes: 31 additions & 0 deletions fs/jbd2/recovery.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 1f56c58

Please sign in to comment.