diff options
Diffstat (limited to 'fs/btrfs/super.c')
-rw-r--r-- | fs/btrfs/super.c | 47 |
1 files changed, 25 insertions, 22 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index dcd5aef6b614..629281c65ff5 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -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: |
@@ -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,28 +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 | if (!fs_info) { | 929 | if (!fs_info) |
937 | error = -ENOMEM; | 930 | return ERR_PTR(-ENOMEM); |
938 | goto error_close_devices; | 931 | |
939 | } | 932 | fs_info->tree_root = kzalloc(sizeof(struct btrfs_root), GFP_NOFS); |
940 | tree_root = kzalloc(sizeof(struct btrfs_root), GFP_NOFS); | 933 | if (!fs_info->tree_root) { |
941 | if (!tree_root) { | ||
942 | error = -ENOMEM; | 934 | error = -ENOMEM; |
943 | goto error_close_devices; | 935 | goto error_fs_info; |
944 | } | 936 | } |
945 | fs_info->tree_root = tree_root; | 937 | fs_info->tree_root->fs_info = fs_info; |
946 | fs_info->fs_devices = fs_devices; | 938 | fs_info->fs_devices = fs_devices; |
947 | tree_root->fs_info = fs_info; | ||
948 | 939 | ||
949 | fs_info->super_copy = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_NOFS); | 940 | fs_info->super_copy = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_NOFS); |
950 | 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); |
951 | if (!fs_info->super_copy || !fs_info->super_for_commit) { | 942 | if (!fs_info->super_copy || !fs_info->super_for_commit) { |
952 | 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; | ||
953 | goto error_close_devices; | 953 | goto error_close_devices; |
954 | } | 954 | } |
955 | 955 | ||
956 | bdev = fs_devices->latest_bdev; | 956 | bdev = fs_devices->latest_bdev; |
957 | 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); | ||
958 | if (IS_ERR(s)) { | 959 | if (IS_ERR(s)) { |
959 | error = PTR_ERR(s); | 960 | error = PTR_ERR(s); |
960 | goto error_close_devices; | 961 | goto error_close_devices; |
@@ -963,7 +964,8 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
963 | if (s->s_root) { | 964 | if (s->s_root) { |
964 | if ((flags ^ s->s_flags) & MS_RDONLY) { | 965 | if ((flags ^ s->s_flags) & MS_RDONLY) { |
965 | deactivate_locked_super(s); | 966 | deactivate_locked_super(s); |
966 | return ERR_PTR(-EBUSY); | 967 | error = -EBUSY; |
968 | goto error_close_devices; | ||
967 | } | 969 | } |
968 | 970 | ||
969 | btrfs_close_devices(fs_devices); | 971 | btrfs_close_devices(fs_devices); |
@@ -994,6 +996,7 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
994 | 996 | ||
995 | error_close_devices: | 997 | error_close_devices: |
996 | btrfs_close_devices(fs_devices); | 998 | btrfs_close_devices(fs_devices); |
999 | error_fs_info: | ||
997 | free_fs_info(fs_info); | 1000 | free_fs_info(fs_info); |
998 | return ERR_PTR(error); | 1001 | return ERR_PTR(error); |
999 | } | 1002 | } |