diff options
Diffstat (limited to 'fs/btrfs/super.c')
-rw-r--r-- | fs/btrfs/super.c | 49 |
1 files changed, 27 insertions, 22 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 57080dffdfc6..8bd9d6d0e07a 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -197,7 +197,7 @@ static match_table_t tokens = { | |||
197 | {Opt_subvolrootid, "subvolrootid=%d"}, | 197 | {Opt_subvolrootid, "subvolrootid=%d"}, |
198 | {Opt_defrag, "autodefrag"}, | 198 | {Opt_defrag, "autodefrag"}, |
199 | {Opt_inode_cache, "inode_cache"}, | 199 | {Opt_inode_cache, "inode_cache"}, |
200 | {Opt_no_space_cache, "no_space_cache"}, | 200 | {Opt_no_space_cache, "nospace_cache"}, |
201 | {Opt_recovery, "recovery"}, | 201 | {Opt_recovery, "recovery"}, |
202 | {Opt_err, NULL}, | 202 | {Opt_err, NULL}, |
203 | }; | 203 | }; |
@@ -448,6 +448,7 @@ static int btrfs_parse_early_options(const char *options, fmode_t flags, | |||
448 | token = match_token(p, tokens, args); | 448 | token = match_token(p, tokens, args); |
449 | switch (token) { | 449 | switch (token) { |
450 | case Opt_subvol: | 450 | case Opt_subvol: |
451 | kfree(*subvol_name); | ||
451 | *subvol_name = match_strdup(&args[0]); | 452 | *subvol_name = match_strdup(&args[0]); |
452 | break; | 453 | break; |
453 | case Opt_subvolid: | 454 | case Opt_subvolid: |
@@ -710,7 +711,7 @@ static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
710 | if (btrfs_test_opt(root, SPACE_CACHE)) | 711 | if (btrfs_test_opt(root, SPACE_CACHE)) |
711 | seq_puts(seq, ",space_cache"); | 712 | seq_puts(seq, ",space_cache"); |
712 | else | 713 | else |
713 | seq_puts(seq, ",no_space_cache"); | 714 | seq_puts(seq, ",nospace_cache"); |
714 | if (btrfs_test_opt(root, CLEAR_CACHE)) | 715 | if (btrfs_test_opt(root, CLEAR_CACHE)) |
715 | seq_puts(seq, ",clear_cache"); | 716 | seq_puts(seq, ",clear_cache"); |
716 | if (btrfs_test_opt(root, USER_SUBVOL_RM_ALLOWED)) | 717 | if (btrfs_test_opt(root, USER_SUBVOL_RM_ALLOWED)) |
@@ -890,7 +891,6 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
890 | struct super_block *s; | 891 | struct super_block *s; |
891 | struct dentry *root; | 892 | struct dentry *root; |
892 | struct btrfs_fs_devices *fs_devices = NULL; | 893 | struct btrfs_fs_devices *fs_devices = NULL; |
893 | struct btrfs_root *tree_root = NULL; | ||
894 | struct btrfs_fs_info *fs_info = NULL; | 894 | struct btrfs_fs_info *fs_info = NULL; |
895 | fmode_t mode = FMODE_READ; | 895 | fmode_t mode = FMODE_READ; |
896 | char *subvol_name = NULL; | 896 | char *subvol_name = NULL; |
@@ -904,8 +904,10 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
904 | error = btrfs_parse_early_options(data, mode, fs_type, | 904 | error = btrfs_parse_early_options(data, mode, fs_type, |
905 | &subvol_name, &subvol_objectid, | 905 | &subvol_name, &subvol_objectid, |
906 | &subvol_rootid, &fs_devices); | 906 | &subvol_rootid, &fs_devices); |
907 | if (error) | 907 | if (error) { |
908 | kfree(subvol_name); | ||
908 | return ERR_PTR(error); | 909 | return ERR_PTR(error); |
910 | } | ||
909 | 911 | ||
910 | if (subvol_name) { | 912 | if (subvol_name) { |
911 | root = mount_subvol(subvol_name, flags, device_name, data); | 913 | root = mount_subvol(subvol_name, flags, device_name, data); |
@@ -917,15 +919,6 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
917 | if (error) | 919 | if (error) |
918 | return ERR_PTR(error); | 920 | return ERR_PTR(error); |
919 | 921 | ||
920 | error = btrfs_open_devices(fs_devices, mode, fs_type); | ||
921 | if (error) | ||
922 | return ERR_PTR(error); | ||
923 | |||
924 | if (!(flags & MS_RDONLY) && fs_devices->rw_devices == 0) { | ||
925 | error = -EACCES; | ||
926 | goto error_close_devices; | ||
927 | } | ||
928 | |||
929 | /* | 922 | /* |
930 | * Setup a dummy root and fs_info for test/set super. This is because | 923 | * Setup a dummy root and fs_info for test/set super. This is because |
931 | * we don't actually fill this stuff out until open_ctree, but we need | 924 | * we don't actually fill this stuff out until open_ctree, but we need |
@@ -933,24 +926,36 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
933 | * then open_ctree will properly initialize everything later. | 926 | * then open_ctree will properly initialize everything later. |
934 | */ | 927 | */ |
935 | fs_info = kzalloc(sizeof(struct btrfs_fs_info), GFP_NOFS); | 928 | fs_info = kzalloc(sizeof(struct btrfs_fs_info), GFP_NOFS); |
936 | tree_root = kzalloc(sizeof(struct btrfs_root), GFP_NOFS); | 929 | if (!fs_info) |
937 | if (!fs_info || !tree_root) { | 930 | return ERR_PTR(-ENOMEM); |
931 | |||
932 | fs_info->tree_root = kzalloc(sizeof(struct btrfs_root), GFP_NOFS); | ||
933 | if (!fs_info->tree_root) { | ||
938 | error = -ENOMEM; | 934 | error = -ENOMEM; |
939 | goto error_close_devices; | 935 | goto error_fs_info; |
940 | } | 936 | } |
941 | fs_info->tree_root = tree_root; | 937 | fs_info->tree_root->fs_info = fs_info; |
942 | fs_info->fs_devices = fs_devices; | 938 | fs_info->fs_devices = fs_devices; |
943 | tree_root->fs_info = fs_info; | ||
944 | 939 | ||
945 | fs_info->super_copy = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_NOFS); | 940 | fs_info->super_copy = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_NOFS); |
946 | fs_info->super_for_commit = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_NOFS); | 941 | fs_info->super_for_commit = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_NOFS); |
947 | if (!fs_info->super_copy || !fs_info->super_for_commit) { | 942 | if (!fs_info->super_copy || !fs_info->super_for_commit) { |
948 | error = -ENOMEM; | 943 | error = -ENOMEM; |
944 | goto error_fs_info; | ||
945 | } | ||
946 | |||
947 | error = btrfs_open_devices(fs_devices, mode, fs_type); | ||
948 | if (error) | ||
949 | goto error_fs_info; | ||
950 | |||
951 | if (!(flags & MS_RDONLY) && fs_devices->rw_devices == 0) { | ||
952 | error = -EACCES; | ||
949 | goto error_close_devices; | 953 | goto error_close_devices; |
950 | } | 954 | } |
951 | 955 | ||
952 | bdev = fs_devices->latest_bdev; | 956 | bdev = fs_devices->latest_bdev; |
953 | s = sget(fs_type, btrfs_test_super, btrfs_set_super, tree_root); | 957 | s = sget(fs_type, btrfs_test_super, btrfs_set_super, |
958 | fs_info->tree_root); | ||
954 | if (IS_ERR(s)) { | 959 | if (IS_ERR(s)) { |
955 | error = PTR_ERR(s); | 960 | error = PTR_ERR(s); |
956 | goto error_close_devices; | 961 | goto error_close_devices; |
@@ -959,12 +964,12 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
959 | if (s->s_root) { | 964 | if (s->s_root) { |
960 | if ((flags ^ s->s_flags) & MS_RDONLY) { | 965 | if ((flags ^ s->s_flags) & MS_RDONLY) { |
961 | deactivate_locked_super(s); | 966 | deactivate_locked_super(s); |
962 | return ERR_PTR(-EBUSY); | 967 | error = -EBUSY; |
968 | goto error_close_devices; | ||
963 | } | 969 | } |
964 | 970 | ||
965 | btrfs_close_devices(fs_devices); | 971 | btrfs_close_devices(fs_devices); |
966 | free_fs_info(fs_info); | 972 | free_fs_info(fs_info); |
967 | kfree(tree_root); | ||
968 | } else { | 973 | } else { |
969 | char b[BDEVNAME_SIZE]; | 974 | char b[BDEVNAME_SIZE]; |
970 | 975 | ||
@@ -991,8 +996,8 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
991 | 996 | ||
992 | error_close_devices: | 997 | error_close_devices: |
993 | btrfs_close_devices(fs_devices); | 998 | btrfs_close_devices(fs_devices); |
999 | error_fs_info: | ||
994 | free_fs_info(fs_info); | 1000 | free_fs_info(fs_info); |
995 | kfree(tree_root); | ||
996 | return ERR_PTR(error); | 1001 | return ERR_PTR(error); |
997 | } | 1002 | } |
998 | 1003 | ||