diff options
Diffstat (limited to 'fs/btrfs/super.c')
-rw-r--r-- | fs/btrfs/super.c | 66 |
1 files changed, 55 insertions, 11 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index d39a9895d932..0ac712efcdf2 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -52,6 +52,9 @@ | |||
52 | #include "export.h" | 52 | #include "export.h" |
53 | #include "compression.h" | 53 | #include "compression.h" |
54 | 54 | ||
55 | #define CREATE_TRACE_POINTS | ||
56 | #include <trace/events/btrfs.h> | ||
57 | |||
55 | static const struct super_operations btrfs_super_ops; | 58 | static const struct super_operations btrfs_super_ops; |
56 | 59 | ||
57 | static const char *btrfs_decode_error(struct btrfs_fs_info *fs_info, int errno, | 60 | static const char *btrfs_decode_error(struct btrfs_fs_info *fs_info, int errno, |
@@ -156,7 +159,7 @@ enum { | |||
156 | Opt_compress_type, Opt_compress_force, Opt_compress_force_type, | 159 | Opt_compress_type, Opt_compress_force, Opt_compress_force_type, |
157 | Opt_notreelog, Opt_ratio, Opt_flushoncommit, Opt_discard, | 160 | Opt_notreelog, Opt_ratio, Opt_flushoncommit, Opt_discard, |
158 | Opt_space_cache, Opt_clear_cache, Opt_user_subvol_rm_allowed, | 161 | Opt_space_cache, Opt_clear_cache, Opt_user_subvol_rm_allowed, |
159 | Opt_enospc_debug, Opt_err, | 162 | Opt_enospc_debug, Opt_subvolrootid, Opt_err, |
160 | }; | 163 | }; |
161 | 164 | ||
162 | static match_table_t tokens = { | 165 | static match_table_t tokens = { |
@@ -186,6 +189,7 @@ static match_table_t tokens = { | |||
186 | {Opt_clear_cache, "clear_cache"}, | 189 | {Opt_clear_cache, "clear_cache"}, |
187 | {Opt_user_subvol_rm_allowed, "user_subvol_rm_allowed"}, | 190 | {Opt_user_subvol_rm_allowed, "user_subvol_rm_allowed"}, |
188 | {Opt_enospc_debug, "enospc_debug"}, | 191 | {Opt_enospc_debug, "enospc_debug"}, |
192 | {Opt_subvolrootid, "subvolrootid=%d"}, | ||
189 | {Opt_err, NULL}, | 193 | {Opt_err, NULL}, |
190 | }; | 194 | }; |
191 | 195 | ||
@@ -229,6 +233,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) | |||
229 | break; | 233 | break; |
230 | case Opt_subvol: | 234 | case Opt_subvol: |
231 | case Opt_subvolid: | 235 | case Opt_subvolid: |
236 | case Opt_subvolrootid: | ||
232 | case Opt_device: | 237 | case Opt_device: |
233 | /* | 238 | /* |
234 | * These are parsed by btrfs_parse_early_options | 239 | * These are parsed by btrfs_parse_early_options |
@@ -385,7 +390,7 @@ out: | |||
385 | */ | 390 | */ |
386 | 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, |
387 | void *holder, char **subvol_name, u64 *subvol_objectid, | 392 | void *holder, char **subvol_name, u64 *subvol_objectid, |
388 | struct btrfs_fs_devices **fs_devices) | 393 | u64 *subvol_rootid, struct btrfs_fs_devices **fs_devices) |
389 | { | 394 | { |
390 | substring_t args[MAX_OPT_ARGS]; | 395 | substring_t args[MAX_OPT_ARGS]; |
391 | char *opts, *orig, *p; | 396 | char *opts, *orig, *p; |
@@ -426,6 +431,18 @@ static int btrfs_parse_early_options(const char *options, fmode_t flags, | |||
426 | *subvol_objectid = intarg; | 431 | *subvol_objectid = intarg; |
427 | } | 432 | } |
428 | 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; | ||
429 | case Opt_device: | 446 | case Opt_device: |
430 | error = btrfs_scan_one_device(match_strdup(&args[0]), | 447 | error = btrfs_scan_one_device(match_strdup(&args[0]), |
431 | flags, holder, fs_devices); | 448 | flags, holder, fs_devices); |
@@ -620,6 +637,8 @@ int btrfs_sync_fs(struct super_block *sb, int wait) | |||
620 | struct btrfs_root *root = btrfs_sb(sb); | 637 | struct btrfs_root *root = btrfs_sb(sb); |
621 | int ret; | 638 | int ret; |
622 | 639 | ||
640 | trace_btrfs_sync_fs(wait); | ||
641 | |||
623 | if (!wait) { | 642 | if (!wait) { |
624 | filemap_flush(root->fs_info->btree_inode->i_mapping); | 643 | filemap_flush(root->fs_info->btree_inode->i_mapping); |
625 | return 0; | 644 | return 0; |
@@ -639,6 +658,7 @@ static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
639 | { | 658 | { |
640 | struct btrfs_root *root = btrfs_sb(vfs->mnt_sb); | 659 | struct btrfs_root *root = btrfs_sb(vfs->mnt_sb); |
641 | struct btrfs_fs_info *info = root->fs_info; | 660 | struct btrfs_fs_info *info = root->fs_info; |
661 | char *compress_type; | ||
642 | 662 | ||
643 | if (btrfs_test_opt(root, DEGRADED)) | 663 | if (btrfs_test_opt(root, DEGRADED)) |
644 | seq_puts(seq, ",degraded"); | 664 | seq_puts(seq, ",degraded"); |
@@ -657,8 +677,16 @@ static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
657 | if (info->thread_pool_size != min_t(unsigned long, | 677 | if (info->thread_pool_size != min_t(unsigned long, |
658 | num_online_cpus() + 2, 8)) | 678 | num_online_cpus() + 2, 8)) |
659 | seq_printf(seq, ",thread_pool=%d", info->thread_pool_size); | 679 | seq_printf(seq, ",thread_pool=%d", info->thread_pool_size); |
660 | if (btrfs_test_opt(root, COMPRESS)) | 680 | if (btrfs_test_opt(root, COMPRESS)) { |
661 | 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 | } | ||
662 | if (btrfs_test_opt(root, NOSSD)) | 690 | if (btrfs_test_opt(root, NOSSD)) |
663 | seq_puts(seq, ",nossd"); | 691 | seq_puts(seq, ",nossd"); |
664 | if (btrfs_test_opt(root, SSD_SPREAD)) | 692 | if (btrfs_test_opt(root, SSD_SPREAD)) |
@@ -673,6 +701,12 @@ static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
673 | seq_puts(seq, ",discard"); | 701 | seq_puts(seq, ",discard"); |
674 | if (!(root->fs_info->sb->s_flags & MS_POSIXACL)) | 702 | if (!(root->fs_info->sb->s_flags & MS_POSIXACL)) |
675 | 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"); | ||
676 | return 0; | 710 | return 0; |
677 | } | 711 | } |
678 | 712 | ||
@@ -716,6 +750,7 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
716 | fmode_t mode = FMODE_READ; | 750 | fmode_t mode = FMODE_READ; |
717 | char *subvol_name = NULL; | 751 | char *subvol_name = NULL; |
718 | u64 subvol_objectid = 0; | 752 | u64 subvol_objectid = 0; |
753 | u64 subvol_rootid = 0; | ||
719 | int error = 0; | 754 | int error = 0; |
720 | 755 | ||
721 | if (!(flags & MS_RDONLY)) | 756 | if (!(flags & MS_RDONLY)) |
@@ -723,7 +758,7 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
723 | 758 | ||
724 | error = btrfs_parse_early_options(data, mode, fs_type, | 759 | error = btrfs_parse_early_options(data, mode, fs_type, |
725 | &subvol_name, &subvol_objectid, | 760 | &subvol_name, &subvol_objectid, |
726 | &fs_devices); | 761 | &subvol_rootid, &fs_devices); |
727 | if (error) | 762 | if (error) |
728 | return ERR_PTR(error); | 763 | return ERR_PTR(error); |
729 | 764 | ||
@@ -787,15 +822,17 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
787 | s->s_flags |= MS_ACTIVE; | 822 | s->s_flags |= MS_ACTIVE; |
788 | } | 823 | } |
789 | 824 | ||
790 | root = get_default_root(s, subvol_objectid); | ||
791 | if (IS_ERR(root)) { | ||
792 | error = PTR_ERR(root); | ||
793 | deactivate_locked_super(s); | ||
794 | goto error_free_subvol_name; | ||
795 | } | ||
796 | /* if they gave us a subvolume name bind mount into that */ | 825 | /* if they gave us a subvolume name bind mount into that */ |
797 | if (strcmp(subvol_name, ".")) { | 826 | if (strcmp(subvol_name, ".")) { |
798 | 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 | |||
799 | mutex_lock(&root->d_inode->i_mutex); | 836 | mutex_lock(&root->d_inode->i_mutex); |
800 | new_root = lookup_one_len(subvol_name, root, | 837 | new_root = lookup_one_len(subvol_name, root, |
801 | strlen(subvol_name)); | 838 | strlen(subvol_name)); |
@@ -816,6 +853,13 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
816 | } | 853 | } |
817 | dput(root); | 854 | dput(root); |
818 | 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 | } | ||
819 | } | 863 | } |
820 | 864 | ||
821 | kfree(subvol_name); | 865 | kfree(subvol_name); |