diff options
Diffstat (limited to 'fs/btrfs/super.c')
| -rw-r--r-- | fs/btrfs/super.c | 42 |
1 files changed, 33 insertions, 9 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 58e7de9cc90c..0ac712efcdf2 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
| @@ -159,7 +159,7 @@ enum { | |||
| 159 | Opt_compress_type, Opt_compress_force, Opt_compress_force_type, | 159 | Opt_compress_type, Opt_compress_force, Opt_compress_force_type, |
| 160 | Opt_notreelog, Opt_ratio, Opt_flushoncommit, Opt_discard, | 160 | Opt_notreelog, Opt_ratio, Opt_flushoncommit, Opt_discard, |
| 161 | Opt_space_cache, Opt_clear_cache, Opt_user_subvol_rm_allowed, | 161 | Opt_space_cache, Opt_clear_cache, Opt_user_subvol_rm_allowed, |
| 162 | Opt_enospc_debug, Opt_err, | 162 | Opt_enospc_debug, Opt_subvolrootid, Opt_err, |
| 163 | }; | 163 | }; |
| 164 | 164 | ||
| 165 | static match_table_t tokens = { | 165 | static match_table_t tokens = { |
| @@ -189,6 +189,7 @@ static match_table_t tokens = { | |||
| 189 | {Opt_clear_cache, "clear_cache"}, | 189 | {Opt_clear_cache, "clear_cache"}, |
| 190 | {Opt_user_subvol_rm_allowed, "user_subvol_rm_allowed"}, | 190 | {Opt_user_subvol_rm_allowed, "user_subvol_rm_allowed"}, |
| 191 | {Opt_enospc_debug, "enospc_debug"}, | 191 | {Opt_enospc_debug, "enospc_debug"}, |
| 192 | {Opt_subvolrootid, "subvolrootid=%d"}, | ||
| 192 | {Opt_err, NULL}, | 193 | {Opt_err, NULL}, |
| 193 | }; | 194 | }; |
| 194 | 195 | ||
| @@ -232,6 +233,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) | |||
| 232 | break; | 233 | break; |
| 233 | case Opt_subvol: | 234 | case Opt_subvol: |
| 234 | case Opt_subvolid: | 235 | case Opt_subvolid: |
| 236 | case Opt_subvolrootid: | ||
| 235 | case Opt_device: | 237 | case Opt_device: |
| 236 | /* | 238 | /* |
| 237 | * These are parsed by btrfs_parse_early_options | 239 | * These are parsed by btrfs_parse_early_options |
| @@ -388,7 +390,7 @@ out: | |||
| 388 | */ | 390 | */ |
| 389 | static int btrfs_parse_early_options(const char *options, fmode_t flags, | 391 | static int btrfs_parse_early_options(const char *options, fmode_t flags, |
| 390 | void *holder, char **subvol_name, u64 *subvol_objectid, | 392 | void *holder, char **subvol_name, u64 *subvol_objectid, |
| 391 | struct btrfs_fs_devices **fs_devices) | 393 | u64 *subvol_rootid, struct btrfs_fs_devices **fs_devices) |
| 392 | { | 394 | { |
| 393 | substring_t args[MAX_OPT_ARGS]; | 395 | substring_t args[MAX_OPT_ARGS]; |
| 394 | char *opts, *orig, *p; | 396 | char *opts, *orig, *p; |
| @@ -429,6 +431,18 @@ static int btrfs_parse_early_options(const char *options, fmode_t flags, | |||
| 429 | *subvol_objectid = intarg; | 431 | *subvol_objectid = intarg; |
| 430 | } | 432 | } |
| 431 | break; | 433 | break; |
| 434 | case Opt_subvolrootid: | ||
| 435 | intarg = 0; | ||
| 436 | error = match_int(&args[0], &intarg); | ||
| 437 | if (!error) { | ||
| 438 | /* we want the original fs_tree */ | ||
| 439 | if (!intarg) | ||
| 440 | *subvol_rootid = | ||
| 441 | BTRFS_FS_TREE_OBJECTID; | ||
| 442 | else | ||
| 443 | *subvol_rootid = intarg; | ||
| 444 | } | ||
| 445 | break; | ||
| 432 | case Opt_device: | 446 | case Opt_device: |
| 433 | error = btrfs_scan_one_device(match_strdup(&args[0]), | 447 | error = btrfs_scan_one_device(match_strdup(&args[0]), |
| 434 | flags, holder, fs_devices); | 448 | flags, holder, fs_devices); |
| @@ -736,6 +750,7 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
| 736 | fmode_t mode = FMODE_READ; | 750 | fmode_t mode = FMODE_READ; |
| 737 | char *subvol_name = NULL; | 751 | char *subvol_name = NULL; |
| 738 | u64 subvol_objectid = 0; | 752 | u64 subvol_objectid = 0; |
| 753 | u64 subvol_rootid = 0; | ||
| 739 | int error = 0; | 754 | int error = 0; |
| 740 | 755 | ||
| 741 | if (!(flags & MS_RDONLY)) | 756 | if (!(flags & MS_RDONLY)) |
| @@ -743,7 +758,7 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
| 743 | 758 | ||
| 744 | error = btrfs_parse_early_options(data, mode, fs_type, | 759 | error = btrfs_parse_early_options(data, mode, fs_type, |
| 745 | &subvol_name, &subvol_objectid, | 760 | &subvol_name, &subvol_objectid, |
| 746 | &fs_devices); | 761 | &subvol_rootid, &fs_devices); |
| 747 | if (error) | 762 | if (error) |
| 748 | return ERR_PTR(error); | 763 | return ERR_PTR(error); |
| 749 | 764 | ||
| @@ -807,15 +822,17 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
| 807 | s->s_flags |= MS_ACTIVE; | 822 | s->s_flags |= MS_ACTIVE; |
| 808 | } | 823 | } |
| 809 | 824 | ||
| 810 | root = get_default_root(s, subvol_objectid); | ||
| 811 | if (IS_ERR(root)) { | ||
| 812 | error = PTR_ERR(root); | ||
| 813 | deactivate_locked_super(s); | ||
| 814 | goto error_free_subvol_name; | ||
| 815 | } | ||
| 816 | /* if they gave us a subvolume name bind mount into that */ | 825 | /* if they gave us a subvolume name bind mount into that */ |
| 817 | if (strcmp(subvol_name, ".")) { | 826 | if (strcmp(subvol_name, ".")) { |
| 818 | struct dentry *new_root; | 827 | struct dentry *new_root; |
| 828 | |||
| 829 | root = get_default_root(s, subvol_rootid); | ||
| 830 | if (IS_ERR(root)) { | ||
| 831 | error = PTR_ERR(root); | ||
| 832 | deactivate_locked_super(s); | ||
| 833 | goto error_free_subvol_name; | ||
| 834 | } | ||
| 835 | |||
| 819 | mutex_lock(&root->d_inode->i_mutex); | 836 | mutex_lock(&root->d_inode->i_mutex); |
| 820 | new_root = lookup_one_len(subvol_name, root, | 837 | new_root = lookup_one_len(subvol_name, root, |
| 821 | strlen(subvol_name)); | 838 | strlen(subvol_name)); |
| @@ -836,6 +853,13 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
| 836 | } | 853 | } |
| 837 | dput(root); | 854 | dput(root); |
| 838 | root = new_root; | 855 | root = new_root; |
| 856 | } else { | ||
| 857 | root = get_default_root(s, subvol_objectid); | ||
| 858 | if (IS_ERR(root)) { | ||
| 859 | error = PTR_ERR(root); | ||
| 860 | deactivate_locked_super(s); | ||
| 861 | goto error_free_subvol_name; | ||
| 862 | } | ||
| 839 | } | 863 | } |
| 840 | 864 | ||
| 841 | kfree(subvol_name); | 865 | kfree(subvol_name); |
