diff options
Diffstat (limited to 'fs/btrfs/super.c')
| -rw-r--r-- | fs/btrfs/super.c | 61 |
1 files changed, 50 insertions, 11 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 2edfc039f098..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); |
| @@ -644,6 +658,7 @@ static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
| 644 | { | 658 | { |
| 645 | struct btrfs_root *root = btrfs_sb(vfs->mnt_sb); | 659 | struct btrfs_root *root = btrfs_sb(vfs->mnt_sb); |
| 646 | struct btrfs_fs_info *info = root->fs_info; | 660 | struct btrfs_fs_info *info = root->fs_info; |
| 661 | char *compress_type; | ||
| 647 | 662 | ||
| 648 | if (btrfs_test_opt(root, DEGRADED)) | 663 | if (btrfs_test_opt(root, DEGRADED)) |
| 649 | seq_puts(seq, ",degraded"); | 664 | seq_puts(seq, ",degraded"); |
| @@ -662,8 +677,16 @@ static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
| 662 | if (info->thread_pool_size != min_t(unsigned long, | 677 | if (info->thread_pool_size != min_t(unsigned long, |
| 663 | num_online_cpus() + 2, 8)) | 678 | num_online_cpus() + 2, 8)) |
| 664 | seq_printf(seq, ",thread_pool=%d", info->thread_pool_size); | 679 | seq_printf(seq, ",thread_pool=%d", info->thread_pool_size); |
| 665 | if (btrfs_test_opt(root, COMPRESS)) | 680 | if (btrfs_test_opt(root, COMPRESS)) { |
| 666 | seq_puts(seq, ",compress"); | 681 | if (info->compress_type == BTRFS_COMPRESS_ZLIB) |
| 682 | compress_type = "zlib"; | ||
| 683 | else | ||
| 684 | compress_type = "lzo"; | ||
| 685 | if (btrfs_test_opt(root, FORCE_COMPRESS)) | ||
| 686 | seq_printf(seq, ",compress-force=%s", compress_type); | ||
| 687 | else | ||
| 688 | seq_printf(seq, ",compress=%s", compress_type); | ||
| 689 | } | ||
| 667 | if (btrfs_test_opt(root, NOSSD)) | 690 | if (btrfs_test_opt(root, NOSSD)) |
| 668 | seq_puts(seq, ",nossd"); | 691 | seq_puts(seq, ",nossd"); |
| 669 | if (btrfs_test_opt(root, SSD_SPREAD)) | 692 | if (btrfs_test_opt(root, SSD_SPREAD)) |
| @@ -678,6 +701,12 @@ static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
| 678 | seq_puts(seq, ",discard"); | 701 | seq_puts(seq, ",discard"); |
| 679 | if (!(root->fs_info->sb->s_flags & MS_POSIXACL)) | 702 | if (!(root->fs_info->sb->s_flags & MS_POSIXACL)) |
| 680 | seq_puts(seq, ",noacl"); | 703 | seq_puts(seq, ",noacl"); |
| 704 | if (btrfs_test_opt(root, SPACE_CACHE)) | ||
| 705 | seq_puts(seq, ",space_cache"); | ||
| 706 | if (btrfs_test_opt(root, CLEAR_CACHE)) | ||
| 707 | seq_puts(seq, ",clear_cache"); | ||
| 708 | if (btrfs_test_opt(root, USER_SUBVOL_RM_ALLOWED)) | ||
| 709 | seq_puts(seq, ",user_subvol_rm_allowed"); | ||
| 681 | return 0; | 710 | return 0; |
| 682 | } | 711 | } |
| 683 | 712 | ||
| @@ -721,6 +750,7 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
| 721 | fmode_t mode = FMODE_READ; | 750 | fmode_t mode = FMODE_READ; |
| 722 | char *subvol_name = NULL; | 751 | char *subvol_name = NULL; |
| 723 | u64 subvol_objectid = 0; | 752 | u64 subvol_objectid = 0; |
| 753 | u64 subvol_rootid = 0; | ||
| 724 | int error = 0; | 754 | int error = 0; |
| 725 | 755 | ||
| 726 | if (!(flags & MS_RDONLY)) | 756 | if (!(flags & MS_RDONLY)) |
| @@ -728,7 +758,7 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
| 728 | 758 | ||
| 729 | error = btrfs_parse_early_options(data, mode, fs_type, | 759 | error = btrfs_parse_early_options(data, mode, fs_type, |
| 730 | &subvol_name, &subvol_objectid, | 760 | &subvol_name, &subvol_objectid, |
| 731 | &fs_devices); | 761 | &subvol_rootid, &fs_devices); |
| 732 | if (error) | 762 | if (error) |
| 733 | return ERR_PTR(error); | 763 | return ERR_PTR(error); |
| 734 | 764 | ||
| @@ -792,15 +822,17 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
| 792 | s->s_flags |= MS_ACTIVE; | 822 | s->s_flags |= MS_ACTIVE; |
| 793 | } | 823 | } |
| 794 | 824 | ||
| 795 | root = get_default_root(s, subvol_objectid); | ||
| 796 | if (IS_ERR(root)) { | ||
| 797 | error = PTR_ERR(root); | ||
| 798 | deactivate_locked_super(s); | ||
| 799 | goto error_free_subvol_name; | ||
| 800 | } | ||
| 801 | /* if they gave us a subvolume name bind mount into that */ | 825 | /* if they gave us a subvolume name bind mount into that */ |
| 802 | if (strcmp(subvol_name, ".")) { | 826 | if (strcmp(subvol_name, ".")) { |
| 803 | 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 | |||
| 804 | mutex_lock(&root->d_inode->i_mutex); | 836 | mutex_lock(&root->d_inode->i_mutex); |
| 805 | new_root = lookup_one_len(subvol_name, root, | 837 | new_root = lookup_one_len(subvol_name, root, |
| 806 | strlen(subvol_name)); | 838 | strlen(subvol_name)); |
| @@ -821,6 +853,13 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
| 821 | } | 853 | } |
| 822 | dput(root); | 854 | dput(root); |
| 823 | 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 | } | ||
| 824 | } | 863 | } |
| 825 | 864 | ||
| 826 | kfree(subvol_name); | 865 | kfree(subvol_name); |
