@@ -98,6 +98,7 @@ struct btrfs_fs_context {
9898 unsigned long mount_opt ;
9999 unsigned long compress_type :4 ;
100100 unsigned int compress_level ;
101+ refcount_t refs ;
101102};
102103
103104enum {
@@ -2797,6 +2798,180 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)
27972798 return 0 ;
27982799}
27992800
2801+ static int btrfs_fc_test_super (struct super_block * sb , struct fs_context * fc )
2802+ {
2803+ struct btrfs_fs_info * p = fc -> s_fs_info ;
2804+ struct btrfs_fs_info * fs_info = btrfs_sb (sb );
2805+
2806+ return fs_info -> fs_devices == p -> fs_devices ;
2807+ }
2808+
2809+ static int btrfs_get_tree_super (struct fs_context * fc )
2810+ {
2811+ struct btrfs_fs_info * fs_info = fc -> s_fs_info ;
2812+ struct btrfs_fs_context * ctx = fc -> fs_private ;
2813+ struct btrfs_fs_devices * fs_devices = NULL ;
2814+ struct block_device * bdev ;
2815+ struct btrfs_device * device ;
2816+ struct super_block * sb ;
2817+ blk_mode_t mode = sb_open_mode (fc -> sb_flags );
2818+ int ret ;
2819+
2820+ btrfs_ctx_to_info (fs_info , ctx );
2821+ mutex_lock (& uuid_mutex );
2822+
2823+ /*
2824+ * With 'true' passed to btrfs_scan_one_device() (mount time) we expect
2825+ * either a valid device or an error.
2826+ */
2827+ device = btrfs_scan_one_device (fc -> source , mode , true);
2828+ ASSERT (device != NULL );
2829+ if (IS_ERR (device )) {
2830+ mutex_unlock (& uuid_mutex );
2831+ return PTR_ERR (device );
2832+ }
2833+
2834+ fs_devices = device -> fs_devices ;
2835+ fs_info -> fs_devices = fs_devices ;
2836+
2837+ ret = btrfs_open_devices (fs_devices , mode , & btrfs_fs_type );
2838+ mutex_unlock (& uuid_mutex );
2839+ if (ret )
2840+ return ret ;
2841+
2842+ if (!(fc -> sb_flags & SB_RDONLY ) && fs_devices -> rw_devices == 0 ) {
2843+ ret = - EACCES ;
2844+ goto error ;
2845+ }
2846+
2847+ bdev = fs_devices -> latest_dev -> bdev ;
2848+
2849+ /*
2850+ * From now on the error handling is not straightforward.
2851+ *
2852+ * If successful, this will transfer the fs_info into the super block,
2853+ * and fc->s_fs_info will be NULL. However if there's an existing
2854+ * super, we'll still have fc->s_fs_info populated. If we error
2855+ * completely out it'll be cleaned up when we drop the fs_context,
2856+ * otherwise it's tied to the lifetime of the super_block.
2857+ */
2858+ sb = sget_fc (fc , btrfs_fc_test_super , set_anon_super_fc );
2859+ if (IS_ERR (sb )) {
2860+ ret = PTR_ERR (sb );
2861+ goto error ;
2862+ }
2863+
2864+ if (sb -> s_root ) {
2865+ btrfs_close_devices (fs_devices );
2866+ if ((fc -> sb_flags ^ sb -> s_flags ) & SB_RDONLY )
2867+ ret = - EBUSY ;
2868+ } else {
2869+ snprintf (sb -> s_id , sizeof (sb -> s_id ), "%pg" , bdev );
2870+ shrinker_debugfs_rename (sb -> s_shrink , "sb-btrfs:%s" , sb -> s_id );
2871+ btrfs_sb (sb )-> bdev_holder = & btrfs_fs_type ;
2872+ ret = btrfs_fill_super (sb , fs_devices , NULL );
2873+ }
2874+
2875+ if (ret ) {
2876+ deactivate_locked_super (sb );
2877+ return ret ;
2878+ }
2879+
2880+ fc -> root = dget (sb -> s_root );
2881+ return 0 ;
2882+
2883+ error :
2884+ btrfs_close_devices (fs_devices );
2885+ return ret ;
2886+ }
2887+
2888+ static int btrfs_get_tree_subvol (struct fs_context * fc )
2889+ {
2890+ struct btrfs_fs_info * fs_info = NULL ;
2891+ struct btrfs_fs_context * ctx = fc -> fs_private ;
2892+ struct fs_context * dup_fc ;
2893+ struct dentry * dentry ;
2894+ struct vfsmount * mnt ;
2895+
2896+ /*
2897+ * Setup a dummy root and fs_info for test/set super. This is because
2898+ * we don't actually fill this stuff out until open_ctree, but we need
2899+ * then open_ctree will properly initialize the file system specific
2900+ * settings later. btrfs_init_fs_info initializes the static elements
2901+ * of the fs_info (locks and such) to make cleanup easier if we find a
2902+ * superblock with our given fs_devices later on at sget() time.
2903+ */
2904+ fs_info = kvzalloc (sizeof (struct btrfs_fs_info ), GFP_KERNEL );
2905+ if (!fs_info )
2906+ return - ENOMEM ;
2907+
2908+ fs_info -> super_copy = kzalloc (BTRFS_SUPER_INFO_SIZE , GFP_KERNEL );
2909+ fs_info -> super_for_commit = kzalloc (BTRFS_SUPER_INFO_SIZE , GFP_KERNEL );
2910+ if (!fs_info -> super_copy || !fs_info -> super_for_commit ) {
2911+ btrfs_free_fs_info (fs_info );
2912+ return - ENOMEM ;
2913+ }
2914+ btrfs_init_fs_info (fs_info );
2915+
2916+ dup_fc = vfs_dup_fs_context (fc );
2917+ if (IS_ERR (dup_fc )) {
2918+ btrfs_free_fs_info (fs_info );
2919+ return PTR_ERR (dup_fc );
2920+ }
2921+
2922+ /*
2923+ * When we do the sget_fc this gets transferred to the sb, so we only
2924+ * need to set it on the dup_fc as this is what creates the super block.
2925+ */
2926+ dup_fc -> s_fs_info = fs_info ;
2927+
2928+ /*
2929+ * We'll do the security settings in our btrfs_get_tree_super() mount
2930+ * loop, they were duplicated into dup_fc, we can drop the originals
2931+ * here.
2932+ */
2933+ security_free_mnt_opts (& fc -> security );
2934+ fc -> security = NULL ;
2935+
2936+ mnt = fc_mount (dup_fc );
2937+ put_fs_context (dup_fc );
2938+ if (IS_ERR (mnt ))
2939+ return PTR_ERR (mnt );
2940+
2941+ /*
2942+ * This free's ->subvol_name, because if it isn't set we have to
2943+ * allocate a buffer to hold the subvol_name, so we just drop our
2944+ * reference to it here.
2945+ */
2946+ dentry = mount_subvol (ctx -> subvol_name , ctx -> subvol_objectid , mnt );
2947+ ctx -> subvol_name = NULL ;
2948+ if (IS_ERR (dentry ))
2949+ return PTR_ERR (dentry );
2950+
2951+ fc -> root = dentry ;
2952+ return 0 ;
2953+ }
2954+
2955+ static int btrfs_get_tree (struct fs_context * fc )
2956+ {
2957+ /*
2958+ * Since we use mount_subtree to mount the default/specified subvol, we
2959+ * have to do mounts in two steps.
2960+ *
2961+ * First pass through we call btrfs_get_tree_subvol(), this is just a
2962+ * wrapper around fc_mount() to call back into here again, and this time
2963+ * we'll call btrfs_get_tree_super(). This will do the open_ctree() and
2964+ * everything to open the devices and file system. Then we return back
2965+ * with a fully constructed vfsmount in btrfs_get_tree_subvol(), and
2966+ * from there we can do our mount_subvol() call, which will lookup
2967+ * whichever subvol we're mounting and setup this fc with the
2968+ * appropriate dentry for the subvol.
2969+ */
2970+ if (fc -> s_fs_info )
2971+ return btrfs_get_tree_super (fc );
2972+ return btrfs_get_tree_subvol (fc );
2973+ }
2974+
28002975static void btrfs_kill_super (struct super_block * sb )
28012976{
28022977 struct btrfs_fs_info * fs_info = btrfs_sb (sb );
@@ -2807,17 +2982,41 @@ static void btrfs_kill_super(struct super_block *sb)
28072982static void btrfs_free_fs_context (struct fs_context * fc )
28082983{
28092984 struct btrfs_fs_context * ctx = fc -> fs_private ;
2985+ struct btrfs_fs_info * fs_info = fc -> s_fs_info ;
28102986
2811- if (!ctx )
2812- return ;
2987+ if (fs_info )
2988+ btrfs_free_fs_info (fs_info );
2989+
2990+ if (ctx && refcount_dec_and_test (& ctx -> refs )) {
2991+ kfree (ctx -> subvol_name );
2992+ kfree (ctx );
2993+ }
2994+ }
28132995
2814- kfree (ctx -> subvol_name );
2815- kfree (ctx );
2996+ static int btrfs_dup_fs_context (struct fs_context * fc , struct fs_context * src_fc )
2997+ {
2998+ struct btrfs_fs_context * ctx = src_fc -> fs_private ;
2999+
3000+ /*
3001+ * Give a ref to our ctx to this dup, as we want to keep it around for
3002+ * our original fc so we can have the subvolume name or objectid.
3003+ *
3004+ * We unset ->source in the original fc because the dup needs it for
3005+ * mounting, and then once we free the dup it'll free ->source, so we
3006+ * need to make sure we're only pointing to it in one fc.
3007+ */
3008+ refcount_inc (& ctx -> refs );
3009+ fc -> fs_private = ctx ;
3010+ fc -> source = src_fc -> source ;
3011+ src_fc -> source = NULL ;
3012+ return 0 ;
28163013}
28173014
28183015static const struct fs_context_operations btrfs_fs_context_ops = {
28193016 .parse_param = btrfs_parse_param ,
28203017 .reconfigure = btrfs_reconfigure ,
3018+ .get_tree = btrfs_get_tree ,
3019+ .dup = btrfs_dup_fs_context ,
28213020 .free = btrfs_free_fs_context ,
28223021};
28233022
@@ -2829,6 +3028,7 @@ static int __maybe_unused btrfs_init_fs_context(struct fs_context *fc)
28293028 if (!ctx )
28303029 return - ENOMEM ;
28313030
3031+ refcount_set (& ctx -> refs , 1 );
28323032 fc -> fs_private = ctx ;
28333033 fc -> ops = & btrfs_fs_context_ops ;
28343034
0 commit comments