aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@us.ibm.com>2012-04-29 18:27:10 -0400
committerTheodore Ts'o <tytso@mit.edu>2012-04-29 18:27:10 -0400
commit0441984a3398970ab4820410b9cf4ff85bf3a6b0 (patch)
tree23c22fad52554003b39d35e6dee7729df3e0797d
parentd25425f8e0ed01fc0167c043aee7e619fc3f6ab2 (diff)
ext4: load the crc32c driver if necessary
Obtain a reference to the cryptoapi and crc32c if we mount a filesystem with metadata checksumming enabled. Signed-off-by: Darrick J. Wong <djwong@us.ibm.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
-rw-r--r--fs/ext4/Kconfig2
-rw-r--r--fs/ext4/ext4.h23
-rw-r--r--fs/ext4/super.c16
3 files changed, 41 insertions, 0 deletions
diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig
index 9ed1bb1f319f..c22f17021b6e 100644
--- a/fs/ext4/Kconfig
+++ b/fs/ext4/Kconfig
@@ -2,6 +2,8 @@ config EXT4_FS
2 tristate "The Extended 4 (ext4) filesystem" 2 tristate "The Extended 4 (ext4) filesystem"
3 select JBD2 3 select JBD2
4 select CRC16 4 select CRC16
5 select CRYPTO
6 select CRYPTO_CRC32C
5 help 7 help
6 This is the next generation of the ext3 filesystem. 8 This is the next generation of the ext3 filesystem.
7 9
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 61dd739b64f0..f19192bde094 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -29,6 +29,7 @@
29#include <linux/wait.h> 29#include <linux/wait.h>
30#include <linux/blockgroup_lock.h> 30#include <linux/blockgroup_lock.h>
31#include <linux/percpu_counter.h> 31#include <linux/percpu_counter.h>
32#include <crypto/hash.h>
32#ifdef __KERNEL__ 33#ifdef __KERNEL__
33#include <linux/compat.h> 34#include <linux/compat.h>
34#endif 35#endif
@@ -1276,6 +1277,9 @@ struct ext4_sb_info {
1276 1277
1277 /* record the last minlen when FITRIM is called. */ 1278 /* record the last minlen when FITRIM is called. */
1278 atomic_t s_last_trim_minblks; 1279 atomic_t s_last_trim_minblks;
1280
1281 /* Reference to checksum algorithm driver via cryptoapi */
1282 struct crypto_shash *s_chksum_driver;
1279}; 1283};
1280 1284
1281static inline struct ext4_sb_info *EXT4_SB(struct super_block *sb) 1285static inline struct ext4_sb_info *EXT4_SB(struct super_block *sb)
@@ -1639,6 +1643,25 @@ static inline __le16 ext4_rec_len_to_disk(unsigned len, unsigned blocksize)
1639#define DX_HASH_HALF_MD4_UNSIGNED 4 1643#define DX_HASH_HALF_MD4_UNSIGNED 4
1640#define DX_HASH_TEA_UNSIGNED 5 1644#define DX_HASH_TEA_UNSIGNED 5
1641 1645
1646static inline u32 ext4_chksum(struct ext4_sb_info *sbi, u32 crc,
1647 const void *address, unsigned int length)
1648{
1649 struct {
1650 struct shash_desc shash;
1651 char ctx[crypto_shash_descsize(sbi->s_chksum_driver)];
1652 } desc;
1653 int err;
1654
1655 desc.shash.tfm = sbi->s_chksum_driver;
1656 desc.shash.flags = 0;
1657 *(u32 *)desc.ctx = crc;
1658
1659 err = crypto_shash_update(&desc.shash, address, length);
1660 BUG_ON(err);
1661
1662 return *(u32 *)desc.ctx;
1663}
1664
1642#ifdef __KERNEL__ 1665#ifdef __KERNEL__
1643 1666
1644/* hash info structure used by the directory hash */ 1667/* hash info structure used by the directory hash */
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index f489ffb3605d..11a0a7078da7 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -915,6 +915,8 @@ static void ext4_put_super(struct super_block *sb)
915 unlock_super(sb); 915 unlock_super(sb);
916 kobject_put(&sbi->s_kobj); 916 kobject_put(&sbi->s_kobj);
917 wait_for_completion(&sbi->s_kobj_unregister); 917 wait_for_completion(&sbi->s_kobj_unregister);
918 if (sbi->s_chksum_driver)
919 crypto_free_shash(sbi->s_chksum_driver);
918 kfree(sbi->s_blockgroup_lock); 920 kfree(sbi->s_blockgroup_lock);
919 kfree(sbi); 921 kfree(sbi);
920} 922}
@@ -3043,6 +3045,18 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
3043 goto cantfind_ext4; 3045 goto cantfind_ext4;
3044 } 3046 }
3045 3047
3048 /* Load the checksum driver */
3049 if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
3050 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) {
3051 sbi->s_chksum_driver = crypto_alloc_shash("crc32c", 0, 0);
3052 if (IS_ERR(sbi->s_chksum_driver)) {
3053 ext4_msg(sb, KERN_ERR, "Cannot load crc32c driver.");
3054 ret = PTR_ERR(sbi->s_chksum_driver);
3055 sbi->s_chksum_driver = NULL;
3056 goto failed_mount;
3057 }
3058 }
3059
3046 /* Set defaults before we parse the mount options */ 3060 /* Set defaults before we parse the mount options */
3047 def_mount_opts = le32_to_cpu(es->s_default_mount_opts); 3061 def_mount_opts = le32_to_cpu(es->s_default_mount_opts);
3048 set_opt(sb, INIT_INODE_TABLE); 3062 set_opt(sb, INIT_INODE_TABLE);
@@ -3728,6 +3742,8 @@ failed_mount2:
3728 brelse(sbi->s_group_desc[i]); 3742 brelse(sbi->s_group_desc[i]);
3729 ext4_kvfree(sbi->s_group_desc); 3743 ext4_kvfree(sbi->s_group_desc);
3730failed_mount: 3744failed_mount:
3745 if (sbi->s_chksum_driver)
3746 crypto_free_shash(sbi->s_chksum_driver);
3731 if (sbi->s_proc) { 3747 if (sbi->s_proc) {
3732 remove_proc_entry("options", sbi->s_proc); 3748 remove_proc_entry("options", sbi->s_proc);
3733 remove_proc_entry(sb->s_id, ext4_proc_root); 3749 remove_proc_entry(sb->s_id, ext4_proc_root);