1818#include <linux/module.h>
1919#include <linux/mutex.h>
2020#include <linux/mount.h>
21- #include <linux/parser .h>
21+ #include <linux/fs_parser .h>
2222#include <linux/radix-tree.h>
2323#include <linux/sched.h>
2424#include <linux/seq_file.h>
@@ -48,26 +48,30 @@ static dev_t binderfs_dev;
4848static DEFINE_MUTEX (binderfs_minors_mutex );
4949static DEFINE_IDA (binderfs_minors );
5050
51- enum {
51+ enum binderfs_param {
5252 Opt_max ,
5353 Opt_stats_mode ,
54- Opt_err
5554};
5655
5756enum binderfs_stats_mode {
58- STATS_NONE ,
59- STATS_GLOBAL ,
57+ binderfs_stats_mode_unset ,
58+ binderfs_stats_mode_global ,
6059};
6160
62- static const match_table_t tokens = {
63- { Opt_max , "max=%d" },
64- { Opt_stats_mode , "stats=%s" },
65- { Opt_err , NULL }
61+ static const struct constant_table binderfs_param_stats [] = {
62+ { "global" , binderfs_stats_mode_global },
63+ {}
6664};
6765
68- static inline struct binderfs_info * BINDERFS_I (const struct inode * inode )
66+ const struct fs_parameter_spec binderfs_fs_parameters [] = {
67+ fsparam_u32 ("max" , Opt_max ),
68+ fsparam_enum ("stats" , Opt_stats_mode , binderfs_param_stats ),
69+ {}
70+ };
71+
72+ static inline struct binderfs_info * BINDERFS_SB (const struct super_block * sb )
6973{
70- return inode -> i_sb -> s_fs_info ;
74+ return sb -> s_fs_info ;
7175}
7276
7377bool is_binderfs_device (const struct inode * inode )
@@ -246,7 +250,7 @@ static long binder_ctl_ioctl(struct file *file, unsigned int cmd,
246250static void binderfs_evict_inode (struct inode * inode )
247251{
248252 struct binder_device * device = inode -> i_private ;
249- struct binderfs_info * info = BINDERFS_I (inode );
253+ struct binderfs_info * info = BINDERFS_SB (inode -> i_sb );
250254
251255 clear_inode (inode );
252256
@@ -264,97 +268,84 @@ static void binderfs_evict_inode(struct inode *inode)
264268 }
265269}
266270
267- /**
268- * binderfs_parse_mount_opts - parse binderfs mount options
269- * @data: options to set (can be NULL in which case defaults are used)
270- */
271- static int binderfs_parse_mount_opts (char * data ,
272- struct binderfs_mount_opts * opts )
271+ static int binderfs_fs_context_parse_param (struct fs_context * fc ,
272+ struct fs_parameter * param )
273273{
274- char * p , * stats ;
275- opts -> max = BINDERFS_MAX_MINOR ;
276- opts -> stats_mode = STATS_NONE ;
277-
278- while ((p = strsep (& data , "," )) != NULL ) {
279- substring_t args [MAX_OPT_ARGS ];
280- int token ;
281- int max_devices ;
282-
283- if (!* p )
284- continue ;
285-
286- token = match_token (p , tokens , args );
287- switch (token ) {
288- case Opt_max :
289- if (match_int (& args [0 ], & max_devices ) ||
290- (max_devices < 0 ||
291- (max_devices > BINDERFS_MAX_MINOR )))
292- return - EINVAL ;
293-
294- opts -> max = max_devices ;
295- break ;
296- case Opt_stats_mode :
297- if (!capable (CAP_SYS_ADMIN ))
298- return - EINVAL ;
274+ int opt ;
275+ struct binderfs_mount_opts * ctx = fc -> fs_private ;
276+ struct fs_parse_result result ;
299277
300- stats = match_strdup ( & args [ 0 ] );
301- if (! stats )
302- return - ENOMEM ;
278+ opt = fs_parse ( fc , binderfs_fs_parameters , param , & result );
279+ if (opt < 0 )
280+ return opt ;
303281
304- if ( strcmp ( stats , "global" ) != 0 ) {
305- kfree ( stats );
306- return - EINVAL ;
307- }
282+ switch ( opt ) {
283+ case Opt_max :
284+ if ( result . uint_32 > BINDERFS_MAX_MINOR )
285+ return invalfc ( fc , "Bad value for '%s'" , param -> key );
308286
309- opts -> stats_mode = STATS_GLOBAL ;
310- kfree (stats );
311- break ;
312- default :
313- pr_err ("Invalid mount options\n" );
314- return - EINVAL ;
315- }
287+ ctx -> max = result .uint_32 ;
288+ break ;
289+ case Opt_stats_mode :
290+ if (!capable (CAP_SYS_ADMIN ))
291+ return - EPERM ;
292+
293+ ctx -> stats_mode = result .uint_32 ;
294+ break ;
295+ default :
296+ return invalfc (fc , "Unsupported parameter '%s'" , param -> key );
316297 }
317298
318299 return 0 ;
319300}
320301
321- static int binderfs_remount (struct super_block * sb , int * flags , char * data )
302+ static int binderfs_fs_context_reconfigure (struct fs_context * fc )
322303{
323- int prev_stats_mode , ret ;
324- struct binderfs_info * info = sb -> s_fs_info ;
304+ struct binderfs_mount_opts * ctx = fc -> fs_private ;
305+ struct binderfs_info * info = BINDERFS_SB ( fc -> root -> d_sb ) ;
325306
326- prev_stats_mode = info -> mount_opts .stats_mode ;
327- ret = binderfs_parse_mount_opts (data , & info -> mount_opts );
328- if (ret )
329- return ret ;
330-
331- if (prev_stats_mode != info -> mount_opts .stats_mode ) {
332- pr_err ("Binderfs stats mode cannot be changed during a remount\n" );
333- info -> mount_opts .stats_mode = prev_stats_mode ;
334- return - EINVAL ;
335- }
307+ if (info -> mount_opts .stats_mode != ctx -> stats_mode )
308+ return invalfc (fc , "Binderfs stats mode cannot be changed during a remount" );
336309
310+ info -> mount_opts .stats_mode = ctx -> stats_mode ;
311+ info -> mount_opts .max = ctx -> max ;
337312 return 0 ;
338313}
339314
340- static int binderfs_show_mount_opts (struct seq_file * seq , struct dentry * root )
315+ static int binderfs_show_options (struct seq_file * seq , struct dentry * root )
341316{
342- struct binderfs_info * info ;
317+ struct binderfs_info * info = BINDERFS_SB ( root -> d_sb ) ;
343318
344- info = root -> d_sb -> s_fs_info ;
345319 if (info -> mount_opts .max <= BINDERFS_MAX_MINOR )
346320 seq_printf (seq , ",max=%d" , info -> mount_opts .max );
347- if (info -> mount_opts .stats_mode == STATS_GLOBAL )
321+
322+ switch (info -> mount_opts .stats_mode ) {
323+ case binderfs_stats_mode_unset :
324+ break ;
325+ case binderfs_stats_mode_global :
348326 seq_printf (seq , ",stats=global" );
327+ break ;
328+ }
349329
350330 return 0 ;
351331}
352332
333+ static void binderfs_put_super (struct super_block * sb )
334+ {
335+ struct binderfs_info * info = sb -> s_fs_info ;
336+
337+ if (info && info -> ipc_ns )
338+ put_ipc_ns (info -> ipc_ns );
339+
340+ kfree (info );
341+ sb -> s_fs_info = NULL ;
342+ }
343+
353344static const struct super_operations binderfs_super_ops = {
354345 .evict_inode = binderfs_evict_inode ,
355- .remount_fs = binderfs_remount ,
356- .show_options = binderfs_show_mount_opts ,
346+ .show_options = binderfs_show_options ,
357347 .statfs = simple_statfs ,
348+ .put_super = binderfs_put_super ,
358349};
359350
360351static inline bool is_binderfs_control_device (const struct dentry * dentry )
@@ -652,10 +643,11 @@ static int init_binder_logs(struct super_block *sb)
652643 return ret ;
653644}
654645
655- static int binderfs_fill_super (struct super_block * sb , void * data , int silent )
646+ static int binderfs_fill_super (struct super_block * sb , struct fs_context * fc )
656647{
657648 int ret ;
658649 struct binderfs_info * info ;
650+ struct binderfs_mount_opts * ctx = fc -> fs_private ;
659651 struct inode * inode = NULL ;
660652 struct binderfs_device device_info = { 0 };
661653 const char * name ;
@@ -688,16 +680,14 @@ static int binderfs_fill_super(struct super_block *sb, void *data, int silent)
688680
689681 info -> ipc_ns = get_ipc_ns (current -> nsproxy -> ipc_ns );
690682
691- ret = binderfs_parse_mount_opts (data , & info -> mount_opts );
692- if (ret )
693- return ret ;
694-
695683 info -> root_gid = make_kgid (sb -> s_user_ns , 0 );
696684 if (!gid_valid (info -> root_gid ))
697685 info -> root_gid = GLOBAL_ROOT_GID ;
698686 info -> root_uid = make_kuid (sb -> s_user_ns , 0 );
699687 if (!uid_valid (info -> root_uid ))
700688 info -> root_uid = GLOBAL_ROOT_UID ;
689+ info -> mount_opts .max = ctx -> max ;
690+ info -> mount_opts .stats_mode = ctx -> stats_mode ;
701691
702692 inode = new_inode (sb );
703693 if (!inode )
@@ -729,36 +719,54 @@ static int binderfs_fill_super(struct super_block *sb, void *data, int silent)
729719 name ++ ;
730720 }
731721
732- if (info -> mount_opts .stats_mode == STATS_GLOBAL )
722+ if (info -> mount_opts .stats_mode == binderfs_stats_mode_global )
733723 return init_binder_logs (sb );
734724
735725 return 0 ;
736726}
737727
738- static struct dentry * binderfs_mount (struct file_system_type * fs_type ,
739- int flags , const char * dev_name ,
740- void * data )
728+ static int binderfs_fs_context_get_tree (struct fs_context * fc )
741729{
742- return mount_nodev ( fs_type , flags , data , binderfs_fill_super );
730+ return get_tree_nodev ( fc , binderfs_fill_super );
743731}
744732
745- static void binderfs_kill_super (struct super_block * sb )
733+ static void binderfs_fs_context_free (struct fs_context * fc )
746734{
747- struct binderfs_info * info = sb -> s_fs_info ;
735+ struct binderfs_mount_opts * ctx = fc -> fs_private ;
748736
749- kill_litter_super (sb );
737+ kfree (ctx );
738+ }
750739
751- if (info && info -> ipc_ns )
752- put_ipc_ns (info -> ipc_ns );
740+ static const struct fs_context_operations binderfs_fs_context_ops = {
741+ .free = binderfs_fs_context_free ,
742+ .get_tree = binderfs_fs_context_get_tree ,
743+ .parse_param = binderfs_fs_context_parse_param ,
744+ .reconfigure = binderfs_fs_context_reconfigure ,
745+ };
753746
754- kfree (info );
747+ static int binderfs_init_fs_context (struct fs_context * fc )
748+ {
749+ struct binderfs_mount_opts * ctx = fc -> fs_private ;
750+
751+ ctx = kzalloc (sizeof (struct binderfs_mount_opts ), GFP_KERNEL );
752+ if (!ctx )
753+ return - ENOMEM ;
754+
755+ ctx -> max = BINDERFS_MAX_MINOR ;
756+ ctx -> stats_mode = binderfs_stats_mode_unset ;
757+
758+ fc -> fs_private = ctx ;
759+ fc -> ops = & binderfs_fs_context_ops ;
760+
761+ return 0 ;
755762}
756763
757764static struct file_system_type binder_fs_type = {
758- .name = "binder" ,
759- .mount = binderfs_mount ,
760- .kill_sb = binderfs_kill_super ,
761- .fs_flags = FS_USERNS_MOUNT ,
765+ .name = "binder" ,
766+ .init_fs_context = binderfs_init_fs_context ,
767+ .parameters = binderfs_fs_parameters ,
768+ .kill_sb = kill_litter_super ,
769+ .fs_flags = FS_USERNS_MOUNT ,
762770};
763771
764772int __init init_binderfs (void )
0 commit comments