aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/super.c199
1 files changed, 135 insertions, 64 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 244fa46c50b8..934789f7fd33 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -40,6 +40,7 @@
40#include <linux/magic.h> 40#include <linux/magic.h>
41#include <linux/slab.h> 41#include <linux/slab.h>
42#include <linux/cleancache.h> 42#include <linux/cleancache.h>
43#include <linux/mnt_namespace.h>
43#include "compat.h" 44#include "compat.h"
44#include "delayed-inode.h" 45#include "delayed-inode.h"
45#include "ctree.h" 46#include "ctree.h"
@@ -58,6 +59,7 @@
58#include <trace/events/btrfs.h> 59#include <trace/events/btrfs.h>
59 60
60static const struct super_operations btrfs_super_ops; 61static const struct super_operations btrfs_super_ops;
62static struct file_system_type btrfs_fs_type;
61 63
62static const char *btrfs_decode_error(struct btrfs_fs_info *fs_info, int errno, 64static const char *btrfs_decode_error(struct btrfs_fs_info *fs_info, int errno,
63 char nbuf[16]) 65 char nbuf[16])
@@ -411,7 +413,7 @@ static int btrfs_parse_early_options(const char *options, fmode_t flags,
411 int intarg; 413 int intarg;
412 414
413 if (!options) 415 if (!options)
414 goto out; 416 return 0;
415 417
416 /* 418 /*
417 * strsep changes the string, duplicate it because parse_options 419 * strsep changes the string, duplicate it because parse_options
@@ -460,26 +462,15 @@ static int btrfs_parse_early_options(const char *options, fmode_t flags,
460 error = btrfs_scan_one_device(match_strdup(&args[0]), 462 error = btrfs_scan_one_device(match_strdup(&args[0]),
461 flags, holder, fs_devices); 463 flags, holder, fs_devices);
462 if (error) 464 if (error)
463 goto out_free_opts; 465 goto out;
464 break; 466 break;
465 default: 467 default:
466 break; 468 break;
467 } 469 }
468 } 470 }
469 471
470 out_free_opts: 472out:
471 kfree(orig); 473 kfree(orig);
472 out:
473 /*
474 * If no subvolume name is specified we use the default one. Allocate
475 * a copy of the string "." here so that code later in the
476 * mount path doesn't care if it's the default volume or another one.
477 */
478 if (!*subvol_name) {
479 *subvol_name = kstrdup(".", GFP_KERNEL);
480 if (!*subvol_name)
481 return -ENOMEM;
482 }
483 return error; 474 return error;
484} 475}
485 476
@@ -730,6 +721,118 @@ static int btrfs_set_super(struct super_block *s, void *data)
730 return set_anon_super(s, data); 721 return set_anon_super(s, data);
731} 722}
732 723
724/*
725 * This will strip out the subvol=%s argument for an argument string and add
726 * subvolid=0 to make sure we get the actual tree root for path walking to the
727 * subvol we want.
728 */
729static char *setup_root_args(char *args)
730{
731 unsigned copied = 0;
732 unsigned len = strlen(args) + 2;
733 char *pos;
734 char *ret;
735
736 /*
737 * We need the same args as before, but minus
738 *
739 * subvol=a
740 *
741 * and add
742 *
743 * subvolid=0
744 *
745 * which is a difference of 2 characters, so we allocate strlen(args) +
746 * 2 characters.
747 */
748 ret = kzalloc(len * sizeof(char), GFP_NOFS);
749 if (!ret)
750 return NULL;
751 pos = strstr(args, "subvol=");
752
753 /* This shouldn't happen, but just in case.. */
754 if (!pos) {
755 kfree(ret);
756 return NULL;
757 }
758
759 /*
760 * The subvol=<> arg is not at the front of the string, copy everybody
761 * up to that into ret.
762 */
763 if (pos != args) {
764 *pos = '\0';
765 strcpy(ret, args);
766 copied += strlen(args);
767 pos++;
768 }
769
770 strncpy(ret + copied, "subvolid=0", len - copied);
771
772 /* Length of subvolid=0 */
773 copied += 10;
774
775 /*
776 * If there is no , after the subvol= option then we know there's no
777 * other options and we can just return.
778 */
779 pos = strchr(pos, ',');
780 if (!pos)
781 return ret;
782
783 /* Copy the rest of the arguments into our buffer */
784 strncpy(ret + copied, pos, len - copied);
785 copied += strlen(pos);
786
787 return ret;
788}
789
790static struct dentry *mount_subvol(const char *subvol_name, int flags,
791 const char *device_name, char *data)
792{
793 struct super_block *s;
794 struct dentry *root;
795 struct vfsmount *mnt;
796 struct mnt_namespace *ns_private;
797 char *newargs;
798 struct path path;
799 int error;
800
801 newargs = setup_root_args(data);
802 if (!newargs)
803 return ERR_PTR(-ENOMEM);
804 mnt = vfs_kern_mount(&btrfs_fs_type, flags, device_name,
805 newargs);
806 kfree(newargs);
807 if (IS_ERR(mnt))
808 return ERR_CAST(mnt);
809
810 ns_private = create_mnt_ns(mnt);
811 if (IS_ERR(ns_private)) {
812 mntput(mnt);
813 return ERR_CAST(ns_private);
814 }
815
816 /*
817 * This will trigger the automount of the subvol so we can just
818 * drop the mnt we have here and return the dentry that we
819 * found.
820 */
821 error = vfs_path_lookup(mnt->mnt_root, mnt, subvol_name,
822 LOOKUP_FOLLOW, &path);
823 put_mnt_ns(ns_private);
824 if (error)
825 return ERR_PTR(error);
826
827 /* Get a ref to the sb and the dentry we found and return it */
828 s = path.mnt->mnt_sb;
829 atomic_inc(&s->s_active);
830 root = dget(path.dentry);
831 path_put(&path);
832 down_write(&s->s_umount);
833
834 return root;
835}
733 836
734/* 837/*
735 * Find a superblock for the given device / mount point. 838 * Find a superblock for the given device / mount point.
@@ -761,13 +864,19 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
761 if (error) 864 if (error)
762 return ERR_PTR(error); 865 return ERR_PTR(error);
763 866
867 if (subvol_name) {
868 root = mount_subvol(subvol_name, flags, device_name, data);
869 kfree(subvol_name);
870 return root;
871 }
872
764 error = btrfs_scan_one_device(device_name, mode, fs_type, &fs_devices); 873 error = btrfs_scan_one_device(device_name, mode, fs_type, &fs_devices);
765 if (error) 874 if (error)
766 goto error_free_subvol_name; 875 return ERR_PTR(error);
767 876
768 error = btrfs_open_devices(fs_devices, mode, fs_type); 877 error = btrfs_open_devices(fs_devices, mode, fs_type);
769 if (error) 878 if (error)
770 goto error_free_subvol_name; 879 return ERR_PTR(error);
771 880
772 if (!(flags & MS_RDONLY) && fs_devices->rw_devices == 0) { 881 if (!(flags & MS_RDONLY) && fs_devices->rw_devices == 0) {
773 error = -EACCES; 882 error = -EACCES;
@@ -792,14 +901,15 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
792 901
793 bdev = fs_devices->latest_bdev; 902 bdev = fs_devices->latest_bdev;
794 s = sget(fs_type, btrfs_test_super, btrfs_set_super, tree_root); 903 s = sget(fs_type, btrfs_test_super, btrfs_set_super, tree_root);
795 if (IS_ERR(s)) 904 if (IS_ERR(s)) {
796 goto error_s; 905 error = PTR_ERR(s);
906 goto error_close_devices;
907 }
797 908
798 if (s->s_root) { 909 if (s->s_root) {
799 if ((flags ^ s->s_flags) & MS_RDONLY) { 910 if ((flags ^ s->s_flags) & MS_RDONLY) {
800 deactivate_locked_super(s); 911 deactivate_locked_super(s);
801 error = -EBUSY; 912 return ERR_PTR(-EBUSY);
802 goto error_close_devices;
803 } 913 }
804 914
805 btrfs_close_devices(fs_devices); 915 btrfs_close_devices(fs_devices);
@@ -814,64 +924,25 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
814 flags & MS_SILENT ? 1 : 0); 924 flags & MS_SILENT ? 1 : 0);
815 if (error) { 925 if (error) {
816 deactivate_locked_super(s); 926 deactivate_locked_super(s);
817 goto error_free_subvol_name; 927 return ERR_PTR(error);
818 } 928 }
819 929
820 btrfs_sb(s)->fs_info->bdev_holder = fs_type; 930 btrfs_sb(s)->fs_info->bdev_holder = fs_type;
821 s->s_flags |= MS_ACTIVE; 931 s->s_flags |= MS_ACTIVE;
822 } 932 }
823 933
824 /* if they gave us a subvolume name bind mount into that */ 934 root = get_default_root(s, subvol_objectid);
825 if (strcmp(subvol_name, ".")) { 935 if (IS_ERR(root)) {
826 struct dentry *new_root; 936 deactivate_locked_super(s);
827 937 return root;
828 root = get_default_root(s, subvol_rootid);
829 if (IS_ERR(root)) {
830 error = PTR_ERR(root);
831 deactivate_locked_super(s);
832 goto error_free_subvol_name;
833 }
834
835 mutex_lock(&root->d_inode->i_mutex);
836 new_root = lookup_one_len(subvol_name, root,
837 strlen(subvol_name));
838 mutex_unlock(&root->d_inode->i_mutex);
839
840 if (IS_ERR(new_root)) {
841 dput(root);
842 deactivate_locked_super(s);
843 error = PTR_ERR(new_root);
844 goto error_free_subvol_name;
845 }
846 if (!new_root->d_inode) {
847 dput(root);
848 dput(new_root);
849 deactivate_locked_super(s);
850 error = -ENXIO;
851 goto error_free_subvol_name;
852 }
853 dput(root);
854 root = new_root;
855 } else {
856 root = get_default_root(s, subvol_objectid);
857 if (IS_ERR(root)) {
858 error = PTR_ERR(root);
859 deactivate_locked_super(s);
860 goto error_free_subvol_name;
861 }
862 } 938 }
863 939
864 kfree(subvol_name);
865 return root; 940 return root;
866 941
867error_s:
868 error = PTR_ERR(s);
869error_close_devices: 942error_close_devices:
870 btrfs_close_devices(fs_devices); 943 btrfs_close_devices(fs_devices);
871 kfree(fs_info); 944 kfree(fs_info);
872 kfree(tree_root); 945 kfree(tree_root);
873error_free_subvol_name:
874 kfree(subvol_name);
875 return ERR_PTR(error); 946 return ERR_PTR(error);
876} 947}
877 948