@@ -98,6 +98,7 @@ struct btrfs_fs_context {
98
98
unsigned long mount_opt ;
99
99
unsigned long compress_type :4 ;
100
100
unsigned int compress_level ;
101
+ refcount_t refs ;
101
102
};
102
103
103
104
enum {
@@ -2797,6 +2798,180 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)
2797
2798
return 0 ;
2798
2799
}
2799
2800
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
+
2800
2975
static void btrfs_kill_super (struct super_block * sb )
2801
2976
{
2802
2977
struct btrfs_fs_info * fs_info = btrfs_sb (sb );
@@ -2807,17 +2982,41 @@ static void btrfs_kill_super(struct super_block *sb)
2807
2982
static void btrfs_free_fs_context (struct fs_context * fc )
2808
2983
{
2809
2984
struct btrfs_fs_context * ctx = fc -> fs_private ;
2985
+ struct btrfs_fs_info * fs_info = fc -> s_fs_info ;
2810
2986
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
+ }
2813
2995
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 ;
2816
3013
}
2817
3014
2818
3015
static const struct fs_context_operations btrfs_fs_context_ops = {
2819
3016
.parse_param = btrfs_parse_param ,
2820
3017
.reconfigure = btrfs_reconfigure ,
3018
+ .get_tree = btrfs_get_tree ,
3019
+ .dup = btrfs_dup_fs_context ,
2821
3020
.free = btrfs_free_fs_context ,
2822
3021
};
2823
3022
@@ -2829,6 +3028,7 @@ static int __maybe_unused btrfs_init_fs_context(struct fs_context *fc)
2829
3028
if (!ctx )
2830
3029
return - ENOMEM ;
2831
3030
3031
+ refcount_set (& ctx -> refs , 1 );
2832
3032
fc -> fs_private = ctx ;
2833
3033
fc -> ops = & btrfs_fs_context_ops ;
2834
3034
0 commit comments