diff options
-rw-r--r-- | fs/jbd2/Kconfig | 2 | ||||
-rw-r--r-- | fs/jbd2/journal.c | 25 | ||||
-rw-r--r-- | include/linux/jbd2.h | 23 |
3 files changed, 50 insertions, 0 deletions
diff --git a/fs/jbd2/Kconfig b/fs/jbd2/Kconfig index f32f346f4b0a..69a48c2944da 100644 --- a/fs/jbd2/Kconfig +++ b/fs/jbd2/Kconfig | |||
@@ -1,6 +1,8 @@ | |||
1 | config JBD2 | 1 | config JBD2 |
2 | tristate | 2 | tristate |
3 | select CRC32 | 3 | select CRC32 |
4 | select CRYPTO | ||
5 | select CRYPTO_CRC32C | ||
4 | help | 6 | help |
5 | This is a generic journaling layer for block devices that support | 7 | This is a generic journaling layer for block devices that support |
6 | both 32-bit and 64-bit block numbers. It is currently used by | 8 | both 32-bit and 64-bit block numbers. It is currently used by |
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 63175f9391ab..f04ab6c4b428 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c | |||
@@ -1438,6 +1438,17 @@ static int journal_get_superblock(journal_t *journal) | |||
1438 | goto out; | 1438 | goto out; |
1439 | } | 1439 | } |
1440 | 1440 | ||
1441 | /* Load the checksum driver */ | ||
1442 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) { | ||
1443 | journal->j_chksum_driver = crypto_alloc_shash("crc32c", 0, 0); | ||
1444 | if (IS_ERR(journal->j_chksum_driver)) { | ||
1445 | printk(KERN_ERR "JBD: Cannot load crc32c driver.\n"); | ||
1446 | err = PTR_ERR(journal->j_chksum_driver); | ||
1447 | journal->j_chksum_driver = NULL; | ||
1448 | goto out; | ||
1449 | } | ||
1450 | } | ||
1451 | |||
1441 | set_buffer_verified(bh); | 1452 | set_buffer_verified(bh); |
1442 | 1453 | ||
1443 | return 0; | 1454 | return 0; |
@@ -1591,6 +1602,8 @@ int jbd2_journal_destroy(journal_t *journal) | |||
1591 | iput(journal->j_inode); | 1602 | iput(journal->j_inode); |
1592 | if (journal->j_revoke) | 1603 | if (journal->j_revoke) |
1593 | jbd2_journal_destroy_revoke(journal); | 1604 | jbd2_journal_destroy_revoke(journal); |
1605 | if (journal->j_chksum_driver) | ||
1606 | crypto_free_shash(journal->j_chksum_driver); | ||
1594 | kfree(journal->j_wbuf); | 1607 | kfree(journal->j_wbuf); |
1595 | kfree(journal); | 1608 | kfree(journal); |
1596 | 1609 | ||
@@ -1707,6 +1720,18 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat, | |||
1707 | sb->s_checksum_type = JBD2_CRC32C_CHKSUM; | 1720 | sb->s_checksum_type = JBD2_CRC32C_CHKSUM; |
1708 | sb->s_feature_compat &= | 1721 | sb->s_feature_compat &= |
1709 | ~cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM); | 1722 | ~cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM); |
1723 | |||
1724 | /* Load the checksum driver */ | ||
1725 | if (journal->j_chksum_driver == NULL) { | ||
1726 | journal->j_chksum_driver = crypto_alloc_shash("crc32c", | ||
1727 | 0, 0); | ||
1728 | if (IS_ERR(journal->j_chksum_driver)) { | ||
1729 | printk(KERN_ERR "JBD: Cannot load crc32c " | ||
1730 | "driver.\n"); | ||
1731 | journal->j_chksum_driver = NULL; | ||
1732 | return 0; | ||
1733 | } | ||
1734 | } | ||
1710 | } | 1735 | } |
1711 | 1736 | ||
1712 | /* If enabling v1 checksums, downgrade superblock */ | 1737 | /* If enabling v1 checksums, downgrade superblock */ |
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index 809c439066c5..71e77dddebf1 100644 --- a/include/linux/jbd2.h +++ b/include/linux/jbd2.h | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/mutex.h> | 31 | #include <linux/mutex.h> |
32 | #include <linux/timer.h> | 32 | #include <linux/timer.h> |
33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
34 | #include <crypto/hash.h> | ||
34 | #endif | 35 | #endif |
35 | 36 | ||
36 | #define journal_oom_retry 1 | 37 | #define journal_oom_retry 1 |
@@ -965,6 +966,9 @@ struct journal_s | |||
965 | * superblock pointer here | 966 | * superblock pointer here |
966 | */ | 967 | */ |
967 | void *j_private; | 968 | void *j_private; |
969 | |||
970 | /* Reference to checksum algorithm driver via cryptoapi */ | ||
971 | struct crypto_shash *j_chksum_driver; | ||
968 | }; | 972 | }; |
969 | 973 | ||
970 | /* | 974 | /* |
@@ -1294,6 +1298,25 @@ static inline int jbd_space_needed(journal_t *journal) | |||
1294 | 1298 | ||
1295 | extern int jbd_blocks_per_page(struct inode *inode); | 1299 | extern int jbd_blocks_per_page(struct inode *inode); |
1296 | 1300 | ||
1301 | static inline u32 jbd2_chksum(journal_t *journal, u32 crc, | ||
1302 | const void *address, unsigned int length) | ||
1303 | { | ||
1304 | struct { | ||
1305 | struct shash_desc shash; | ||
1306 | char ctx[crypto_shash_descsize(journal->j_chksum_driver)]; | ||
1307 | } desc; | ||
1308 | int err; | ||
1309 | |||
1310 | desc.shash.tfm = journal->j_chksum_driver; | ||
1311 | desc.shash.flags = 0; | ||
1312 | *(u32 *)desc.ctx = crc; | ||
1313 | |||
1314 | err = crypto_shash_update(&desc.shash, address, length); | ||
1315 | BUG_ON(err); | ||
1316 | |||
1317 | return *(u32 *)desc.ctx; | ||
1318 | } | ||
1319 | |||
1297 | #ifdef __KERNEL__ | 1320 | #ifdef __KERNEL__ |
1298 | 1321 | ||
1299 | #define buffer_trace_init(bh) do {} while (0) | 1322 | #define buffer_trace_init(bh) do {} while (0) |