diff options
| author | Darrick J. Wong <djwong@us.ibm.com> | 2012-05-27 08:08:22 -0400 |
|---|---|---|
| committer | Theodore Ts'o <tytso@mit.edu> | 2012-05-27 08:08:22 -0400 |
| commit | 4fd5ea43bc11602bfabe2c8f5378586d34bd2b0a (patch) | |
| tree | 2a5e49a91ecb67c5a89eb0abe55f2b15495f738f | |
| parent | 01b5adcebb977bc61b64167adce6d8260c9da33c (diff) | |
jbd2: checksum journal superblock
Calculate and verify a checksum covering the journal superblock.
Signed-off-by: Darrick J. Wong <djwong@us.ibm.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
| -rw-r--r-- | fs/jbd2/journal.c | 47 | ||||
| -rw-r--r-- | include/linux/jbd2.h | 3 |
2 files changed, 50 insertions, 0 deletions
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index f04ab6c4b428..9072f03d30b5 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c | |||
| @@ -106,6 +106,34 @@ int jbd2_verify_csum_type(journal_t *j, journal_superblock_t *sb) | |||
| 106 | return sb->s_checksum_type == JBD2_CRC32C_CHKSUM; | 106 | return sb->s_checksum_type == JBD2_CRC32C_CHKSUM; |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | static __u32 jbd2_superblock_csum(journal_t *j, journal_superblock_t *sb) | ||
| 110 | { | ||
| 111 | __u32 csum, old_csum; | ||
| 112 | |||
| 113 | old_csum = sb->s_checksum; | ||
| 114 | sb->s_checksum = 0; | ||
| 115 | csum = jbd2_chksum(j, ~0, (char *)sb, sizeof(journal_superblock_t)); | ||
| 116 | sb->s_checksum = old_csum; | ||
| 117 | |||
| 118 | return cpu_to_be32(csum); | ||
| 119 | } | ||
| 120 | |||
| 121 | int jbd2_superblock_csum_verify(journal_t *j, journal_superblock_t *sb) | ||
| 122 | { | ||
| 123 | if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) | ||
| 124 | return 1; | ||
| 125 | |||
| 126 | return sb->s_checksum == jbd2_superblock_csum(j, sb); | ||
| 127 | } | ||
| 128 | |||
| 129 | void jbd2_superblock_csum_set(journal_t *j, journal_superblock_t *sb) | ||
| 130 | { | ||
| 131 | if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) | ||
| 132 | return; | ||
| 133 | |||
| 134 | sb->s_checksum = jbd2_superblock_csum(j, sb); | ||
| 135 | } | ||
| 136 | |||
| 109 | /* | 137 | /* |
| 110 | * Helper function used to manage commit timeouts | 138 | * Helper function used to manage commit timeouts |
| 111 | */ | 139 | */ |
| @@ -1357,6 +1385,7 @@ static void jbd2_journal_update_sb_errno(journal_t *journal) | |||
| 1357 | jbd_debug(1, "JBD2: updating superblock error (errno %d)\n", | 1385 | jbd_debug(1, "JBD2: updating superblock error (errno %d)\n", |
| 1358 | journal->j_errno); | 1386 | journal->j_errno); |
| 1359 | sb->s_errno = cpu_to_be32(journal->j_errno); | 1387 | sb->s_errno = cpu_to_be32(journal->j_errno); |
| 1388 | jbd2_superblock_csum_set(journal, sb); | ||
| 1360 | read_unlock(&journal->j_state_lock); | 1389 | read_unlock(&journal->j_state_lock); |
| 1361 | 1390 | ||
| 1362 | jbd2_write_superblock(journal, WRITE_SYNC); | 1391 | jbd2_write_superblock(journal, WRITE_SYNC); |
| @@ -1449,6 +1478,17 @@ static int journal_get_superblock(journal_t *journal) | |||
| 1449 | } | 1478 | } |
| 1450 | } | 1479 | } |
| 1451 | 1480 | ||
| 1481 | /* Check superblock checksum */ | ||
| 1482 | if (!jbd2_superblock_csum_verify(journal, sb)) { | ||
| 1483 | printk(KERN_ERR "JBD: journal checksum error\n"); | ||
| 1484 | goto out; | ||
| 1485 | } | ||
| 1486 | |||
| 1487 | /* Precompute checksum seed for all metadata */ | ||
| 1488 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) | ||
| 1489 | journal->j_csum_seed = jbd2_chksum(journal, ~0, sb->s_uuid, | ||
| 1490 | sizeof(sb->s_uuid)); | ||
| 1491 | |||
| 1452 | set_buffer_verified(bh); | 1492 | set_buffer_verified(bh); |
| 1453 | 1493 | ||
| 1454 | return 0; | 1494 | return 0; |
| @@ -1732,6 +1772,13 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat, | |||
| 1732 | return 0; | 1772 | return 0; |
| 1733 | } | 1773 | } |
| 1734 | } | 1774 | } |
| 1775 | |||
| 1776 | /* Precompute checksum seed for all metadata */ | ||
| 1777 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, | ||
| 1778 | JBD2_FEATURE_INCOMPAT_CSUM_V2)) | ||
| 1779 | journal->j_csum_seed = jbd2_chksum(journal, ~0, | ||
| 1780 | sb->s_uuid, | ||
| 1781 | sizeof(sb->s_uuid)); | ||
| 1735 | } | 1782 | } |
| 1736 | 1783 | ||
| 1737 | /* If enabling v1 checksums, downgrade superblock */ | 1784 | /* If enabling v1 checksums, downgrade superblock */ |
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index 71e77dddebf1..a9632bc55d97 100644 --- a/include/linux/jbd2.h +++ b/include/linux/jbd2.h | |||
| @@ -969,6 +969,9 @@ struct journal_s | |||
| 969 | 969 | ||
| 970 | /* Reference to checksum algorithm driver via cryptoapi */ | 970 | /* Reference to checksum algorithm driver via cryptoapi */ |
| 971 | struct crypto_shash *j_chksum_driver; | 971 | struct crypto_shash *j_chksum_driver; |
| 972 | |||
| 973 | /* Precomputed journal UUID checksum for seeding other checksums */ | ||
| 974 | __u32 j_csum_seed; | ||
| 972 | }; | 975 | }; |
| 973 | 976 | ||
| 974 | /* | 977 | /* |
