jbd2: checksum data blocks that are stored in the journal
Calculate and verify checksums of each data block being stored in the journal. Signed-off-by: Darrick J. Wong <djwong@us.ibm.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
This commit is contained in:
committed by
Theodore Ts'o
parent
1f56c5890e
commit
c390087591
@@ -338,6 +338,26 @@ static void jbd2_descr_block_csum_set(journal_t *j,
|
|||||||
tail->t_checksum = cpu_to_be32(csum);
|
tail->t_checksum = cpu_to_be32(csum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void jbd2_block_tag_csum_set(journal_t *j, journal_block_tag_t *tag,
|
||||||
|
struct buffer_head *bh, __u32 sequence)
|
||||||
|
{
|
||||||
|
struct page *page = bh->b_page;
|
||||||
|
__u8 *addr;
|
||||||
|
__u32 csum;
|
||||||
|
|
||||||
|
if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
|
||||||
|
return;
|
||||||
|
|
||||||
|
sequence = cpu_to_be32(sequence);
|
||||||
|
addr = kmap_atomic(page, KM_USER0);
|
||||||
|
csum = jbd2_chksum(j, j->j_csum_seed, (__u8 *)&sequence,
|
||||||
|
sizeof(sequence));
|
||||||
|
csum = jbd2_chksum(j, csum, addr + offset_in_page(bh->b_data),
|
||||||
|
bh->b_size);
|
||||||
|
kunmap_atomic(addr, KM_USER0);
|
||||||
|
|
||||||
|
tag->t_checksum = cpu_to_be32(csum);
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* jbd2_journal_commit_transaction
|
* jbd2_journal_commit_transaction
|
||||||
*
|
*
|
||||||
@@ -669,6 +689,8 @@ void jbd2_journal_commit_transaction(journal_t *journal)
|
|||||||
tag = (journal_block_tag_t *) tagp;
|
tag = (journal_block_tag_t *) tagp;
|
||||||
write_tag_block(tag_bytes, tag, jh2bh(jh)->b_blocknr);
|
write_tag_block(tag_bytes, tag, jh2bh(jh)->b_blocknr);
|
||||||
tag->t_flags = cpu_to_be16(tag_flag);
|
tag->t_flags = cpu_to_be16(tag_flag);
|
||||||
|
jbd2_block_tag_csum_set(journal, tag, jh2bh(new_jh),
|
||||||
|
commit_transaction->t_tid);
|
||||||
tagp += tag_bytes;
|
tagp += tag_bytes;
|
||||||
space_left -= tag_bytes;
|
space_left -= tag_bytes;
|
||||||
|
|
||||||
|
@@ -2097,10 +2097,16 @@ int jbd2_journal_blocks_per_page(struct inode *inode)
|
|||||||
*/
|
*/
|
||||||
size_t journal_tag_bytes(journal_t *journal)
|
size_t journal_tag_bytes(journal_t *journal)
|
||||||
{
|
{
|
||||||
|
journal_block_tag_t tag;
|
||||||
|
size_t x = 0;
|
||||||
|
|
||||||
|
if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2))
|
||||||
|
x += sizeof(tag.t_checksum);
|
||||||
|
|
||||||
if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT))
|
if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT))
|
||||||
return JBD2_TAG_SIZE64;
|
return x + JBD2_TAG_SIZE64;
|
||||||
else
|
else
|
||||||
return JBD2_TAG_SIZE32;
|
return x + JBD2_TAG_SIZE32;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -393,6 +393,23 @@ static int jbd2_commit_block_csum_verify(journal_t *j, void *buf)
|
|||||||
return provided == calculated;
|
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,
|
static int do_one_pass(journal_t *journal,
|
||||||
struct recovery_info *info, enum passtype pass)
|
struct recovery_info *info, enum passtype pass)
|
||||||
{
|
{
|
||||||
@@ -569,6 +586,19 @@ static int do_one_pass(journal_t *journal,
|
|||||||
goto skip_write;
|
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
|
/* Find a buffer for the new
|
||||||
* data being restored */
|
* data being restored */
|
||||||
nbh = __getblk(journal->j_fs_dev,
|
nbh = __getblk(journal->j_fs_dev,
|
||||||
|
Reference in New Issue
Block a user