diff options
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r-- | fs/btrfs/disk-io.c | 46 |
1 files changed, 39 insertions, 7 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index c9ce0b002008..34222bbe4b48 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/crc32c.h> | 19 | #include <linux/crc32c.h> |
20 | #include <linux/sched/mm.h> | 20 | #include <linux/sched/mm.h> |
21 | #include <asm/unaligned.h> | 21 | #include <asm/unaligned.h> |
22 | #include <crypto/hash.h> | ||
22 | #include "ctree.h" | 23 | #include "ctree.h" |
23 | #include "disk-io.h" | 24 | #include "disk-io.h" |
24 | #include "transaction.h" | 25 | #include "transaction.h" |
@@ -2256,6 +2257,29 @@ static int btrfs_init_workqueues(struct btrfs_fs_info *fs_info, | |||
2256 | return 0; | 2257 | return 0; |
2257 | } | 2258 | } |
2258 | 2259 | ||
2260 | static int btrfs_init_csum_hash(struct btrfs_fs_info *fs_info, u16 csum_type) | ||
2261 | { | ||
2262 | struct crypto_shash *csum_shash; | ||
2263 | const char *csum_name = btrfs_super_csum_name(csum_type); | ||
2264 | |||
2265 | csum_shash = crypto_alloc_shash(csum_name, 0, 0); | ||
2266 | |||
2267 | if (IS_ERR(csum_shash)) { | ||
2268 | btrfs_err(fs_info, "error allocating %s hash for checksum", | ||
2269 | csum_name); | ||
2270 | return PTR_ERR(csum_shash); | ||
2271 | } | ||
2272 | |||
2273 | fs_info->csum_shash = csum_shash; | ||
2274 | |||
2275 | return 0; | ||
2276 | } | ||
2277 | |||
2278 | static void btrfs_free_csum_hash(struct btrfs_fs_info *fs_info) | ||
2279 | { | ||
2280 | crypto_free_shash(fs_info->csum_shash); | ||
2281 | } | ||
2282 | |||
2259 | static int btrfs_replay_log(struct btrfs_fs_info *fs_info, | 2283 | static int btrfs_replay_log(struct btrfs_fs_info *fs_info, |
2260 | struct btrfs_fs_devices *fs_devices) | 2284 | struct btrfs_fs_devices *fs_devices) |
2261 | { | 2285 | { |
@@ -2820,6 +2844,12 @@ int open_ctree(struct super_block *sb, | |||
2820 | goto fail_alloc; | 2844 | goto fail_alloc; |
2821 | } | 2845 | } |
2822 | 2846 | ||
2847 | ret = btrfs_init_csum_hash(fs_info, csum_type); | ||
2848 | if (ret) { | ||
2849 | err = ret; | ||
2850 | goto fail_alloc; | ||
2851 | } | ||
2852 | |||
2823 | /* | 2853 | /* |
2824 | * We want to check superblock checksum, the type is stored inside. | 2854 | * We want to check superblock checksum, the type is stored inside. |
2825 | * Pass the whole disk block of size BTRFS_SUPER_INFO_SIZE (4k). | 2855 | * Pass the whole disk block of size BTRFS_SUPER_INFO_SIZE (4k). |
@@ -2828,7 +2858,7 @@ int open_ctree(struct super_block *sb, | |||
2828 | btrfs_err(fs_info, "superblock checksum mismatch"); | 2858 | btrfs_err(fs_info, "superblock checksum mismatch"); |
2829 | err = -EINVAL; | 2859 | err = -EINVAL; |
2830 | brelse(bh); | 2860 | brelse(bh); |
2831 | goto fail_alloc; | 2861 | goto fail_csum; |
2832 | } | 2862 | } |
2833 | 2863 | ||
2834 | /* | 2864 | /* |
@@ -2865,11 +2895,11 @@ int open_ctree(struct super_block *sb, | |||
2865 | if (ret) { | 2895 | if (ret) { |
2866 | btrfs_err(fs_info, "superblock contains fatal errors"); | 2896 | btrfs_err(fs_info, "superblock contains fatal errors"); |
2867 | err = -EINVAL; | 2897 | err = -EINVAL; |
2868 | goto fail_alloc; | 2898 | goto fail_csum; |
2869 | } | 2899 | } |
2870 | 2900 | ||
2871 | if (!btrfs_super_root(disk_super)) | 2901 | if (!btrfs_super_root(disk_super)) |
2872 | goto fail_alloc; | 2902 | goto fail_csum; |
2873 | 2903 | ||
2874 | /* check FS state, whether FS is broken. */ | 2904 | /* check FS state, whether FS is broken. */ |
2875 | if (btrfs_super_flags(disk_super) & BTRFS_SUPER_FLAG_ERROR) | 2905 | if (btrfs_super_flags(disk_super) & BTRFS_SUPER_FLAG_ERROR) |
@@ -2891,7 +2921,7 @@ int open_ctree(struct super_block *sb, | |||
2891 | ret = btrfs_parse_options(fs_info, options, sb->s_flags); | 2921 | ret = btrfs_parse_options(fs_info, options, sb->s_flags); |
2892 | if (ret) { | 2922 | if (ret) { |
2893 | err = ret; | 2923 | err = ret; |
2894 | goto fail_alloc; | 2924 | goto fail_csum; |
2895 | } | 2925 | } |
2896 | 2926 | ||
2897 | features = btrfs_super_incompat_flags(disk_super) & | 2927 | features = btrfs_super_incompat_flags(disk_super) & |
@@ -2901,7 +2931,7 @@ int open_ctree(struct super_block *sb, | |||
2901 | "cannot mount because of unsupported optional features (%llx)", | 2931 | "cannot mount because of unsupported optional features (%llx)", |
2902 | features); | 2932 | features); |
2903 | err = -EINVAL; | 2933 | err = -EINVAL; |
2904 | goto fail_alloc; | 2934 | goto fail_csum; |
2905 | } | 2935 | } |
2906 | 2936 | ||
2907 | features = btrfs_super_incompat_flags(disk_super); | 2937 | features = btrfs_super_incompat_flags(disk_super); |
@@ -2945,7 +2975,7 @@ int open_ctree(struct super_block *sb, | |||
2945 | btrfs_err(fs_info, | 2975 | btrfs_err(fs_info, |
2946 | "unequal nodesize/sectorsize (%u != %u) are not allowed for mixed block groups", | 2976 | "unequal nodesize/sectorsize (%u != %u) are not allowed for mixed block groups", |
2947 | nodesize, sectorsize); | 2977 | nodesize, sectorsize); |
2948 | goto fail_alloc; | 2978 | goto fail_csum; |
2949 | } | 2979 | } |
2950 | 2980 | ||
2951 | /* | 2981 | /* |
@@ -2961,7 +2991,7 @@ int open_ctree(struct super_block *sb, | |||
2961 | "cannot mount read-write because of unsupported optional features (%llx)", | 2991 | "cannot mount read-write because of unsupported optional features (%llx)", |
2962 | features); | 2992 | features); |
2963 | err = -EINVAL; | 2993 | err = -EINVAL; |
2964 | goto fail_alloc; | 2994 | goto fail_csum; |
2965 | } | 2995 | } |
2966 | 2996 | ||
2967 | ret = btrfs_init_workqueues(fs_info, fs_devices); | 2997 | ret = btrfs_init_workqueues(fs_info, fs_devices); |
@@ -3339,6 +3369,8 @@ fail_tree_roots: | |||
3339 | fail_sb_buffer: | 3369 | fail_sb_buffer: |
3340 | btrfs_stop_all_workers(fs_info); | 3370 | btrfs_stop_all_workers(fs_info); |
3341 | btrfs_free_block_groups(fs_info); | 3371 | btrfs_free_block_groups(fs_info); |
3372 | fail_csum: | ||
3373 | btrfs_free_csum_hash(fs_info); | ||
3342 | fail_alloc: | 3374 | fail_alloc: |
3343 | fail_iput: | 3375 | fail_iput: |
3344 | btrfs_mapping_tree_free(&fs_info->mapping_tree); | 3376 | btrfs_mapping_tree_free(&fs_info->mapping_tree); |