diff options
-rw-r--r-- | fs/ext4/Kconfig | 2 | ||||
-rw-r--r-- | fs/ext4/ext4.h | 23 | ||||
-rw-r--r-- | fs/ext4/super.c | 16 |
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 | ||
1281 | static inline struct ext4_sb_info *EXT4_SB(struct super_block *sb) | 1285 | static 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 | ||
1646 | static 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); |
3730 | failed_mount: | 3744 | failed_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); |