1111
1212#include <linux/module.h>
1313#include <linux/fs.h>
14- #include <linux/mount.h>
14+ #include <linux/fs_context.h>
15+ #include <linux/fs_parser.h>
1516#include <linux/kobject.h>
1617#include <linux/namei.h>
1718#include <linux/tracefs.h>
1819#include <linux/fsnotify.h>
1920#include <linux/security.h>
2021#include <linux/seq_file.h>
21- #include <linux/parser.h>
2222#include <linux/magic.h>
2323#include <linux/slab.h>
2424#include "internal.h"
@@ -231,7 +231,7 @@ struct inode *tracefs_get_inode(struct super_block *sb)
231231 return inode ;
232232}
233233
234- struct tracefs_mount_opts {
234+ struct tracefs_fs_info {
235235 kuid_t uid ;
236236 kgid_t gid ;
237237 umode_t mode ;
@@ -243,127 +243,105 @@ enum {
243243 Opt_uid ,
244244 Opt_gid ,
245245 Opt_mode ,
246- Opt_err
247246};
248247
249- static const match_table_t tokens = {
250- { Opt_uid , "uid=%u" } ,
251- { Opt_gid , "gid=%u" } ,
252- { Opt_mode , "mode=%o" } ,
253- {Opt_err , NULL }
248+ static const struct fs_parameter_spec tracefs_param_specs [] = {
249+ fsparam_u32 ( "gid" , Opt_gid ) ,
250+ fsparam_u32oct ( "mode" , Opt_mode ) ,
251+ fsparam_u32 ( "uid" , Opt_uid ) ,
252+ {}
254253};
255254
256- struct tracefs_fs_info {
257- struct tracefs_mount_opts mount_opts ;
258- };
259-
260- static int tracefs_parse_options (char * data , struct tracefs_mount_opts * opts )
255+ static int tracefs_parse_param (struct fs_context * fc , struct fs_parameter * param )
261256{
262- substring_t args [MAX_OPT_ARGS ];
263- int option ;
264- int token ;
257+ struct tracefs_fs_info * opts = fc -> s_fs_info ;
258+ struct fs_parse_result result ;
265259 kuid_t uid ;
266260 kgid_t gid ;
267- char * p ;
268-
269- opts -> opts = 0 ;
270- opts -> mode = TRACEFS_DEFAULT_MODE ;
271-
272- while ((p = strsep (& data , "," )) != NULL ) {
273- if (!* p )
274- continue ;
275-
276- token = match_token (p , tokens , args );
277- switch (token ) {
278- case Opt_uid :
279- if (match_int (& args [0 ], & option ))
280- return - EINVAL ;
281- uid = make_kuid (current_user_ns (), option );
282- if (!uid_valid (uid ))
283- return - EINVAL ;
284- opts -> uid = uid ;
285- break ;
286- case Opt_gid :
287- if (match_int (& args [0 ], & option ))
288- return - EINVAL ;
289- gid = make_kgid (current_user_ns (), option );
290- if (!gid_valid (gid ))
291- return - EINVAL ;
292- opts -> gid = gid ;
293- break ;
294- case Opt_mode :
295- if (match_octal (& args [0 ], & option ))
296- return - EINVAL ;
297- opts -> mode = option & S_IALLUGO ;
298- break ;
299- /*
300- * We might like to report bad mount options here;
301- * but traditionally tracefs has ignored all mount options
302- */
303- }
304-
305- opts -> opts |= BIT (token );
261+ int opt ;
262+
263+ opt = fs_parse (fc , tracefs_param_specs , param , & result );
264+ if (opt < 0 )
265+ return opt ;
266+
267+ switch (opt ) {
268+ case Opt_uid :
269+ uid = make_kuid (current_user_ns (), result .uint_32 );
270+ if (!uid_valid (uid ))
271+ return invalf (fc , "Unknown uid" );
272+ opts -> uid = uid ;
273+ break ;
274+ case Opt_gid :
275+ gid = make_kgid (current_user_ns (), result .uint_32 );
276+ if (!gid_valid (gid ))
277+ return invalf (fc , "Unknown gid" );
278+ opts -> gid = gid ;
279+ break ;
280+ case Opt_mode :
281+ opts -> mode = result .uint_32 & S_IALLUGO ;
282+ break ;
283+ /*
284+ * We might like to report bad mount options here;
285+ * but traditionally tracefs has ignored all mount options
286+ */
306287 }
307288
289+ opts -> opts |= BIT (opt );
290+
308291 return 0 ;
309292}
310293
311294static int tracefs_apply_options (struct super_block * sb , bool remount )
312295{
313296 struct tracefs_fs_info * fsi = sb -> s_fs_info ;
314297 struct inode * inode = d_inode (sb -> s_root );
315- struct tracefs_mount_opts * opts = & fsi -> mount_opts ;
316298 umode_t tmp_mode ;
317299
318300 /*
319301 * On remount, only reset mode/uid/gid if they were provided as mount
320302 * options.
321303 */
322304
323- if (!remount || opts -> opts & BIT (Opt_mode )) {
305+ if (!remount || fsi -> opts & BIT (Opt_mode )) {
324306 tmp_mode = READ_ONCE (inode -> i_mode ) & ~S_IALLUGO ;
325- tmp_mode |= opts -> mode ;
307+ tmp_mode |= fsi -> mode ;
326308 WRITE_ONCE (inode -> i_mode , tmp_mode );
327309 }
328310
329- if (!remount || opts -> opts & BIT (Opt_uid ))
330- inode -> i_uid = opts -> uid ;
311+ if (!remount || fsi -> opts & BIT (Opt_uid ))
312+ inode -> i_uid = fsi -> uid ;
331313
332- if (!remount || opts -> opts & BIT (Opt_gid ))
333- inode -> i_gid = opts -> gid ;
314+ if (!remount || fsi -> opts & BIT (Opt_gid ))
315+ inode -> i_gid = fsi -> gid ;
334316
335317 return 0 ;
336318}
337319
338- static int tracefs_remount (struct super_block * sb , int * flags , char * data )
320+ static int tracefs_reconfigure (struct fs_context * fc )
339321{
340- int err ;
341- struct tracefs_fs_info * fsi = sb -> s_fs_info ;
322+ struct super_block * sb = fc -> root -> d_sb ;
323+ struct tracefs_fs_info * sb_opts = sb -> s_fs_info ;
324+ struct tracefs_fs_info * new_opts = fc -> s_fs_info ;
342325
343326 sync_filesystem (sb );
344- err = tracefs_parse_options (data , & fsi -> mount_opts );
345- if (err )
346- goto fail ;
327+ /* structure copy of new mount options to sb */
328+ * sb_opts = * new_opts ;
347329
348- tracefs_apply_options (sb , true);
349-
350- fail :
351- return err ;
330+ return tracefs_apply_options (sb , true);
352331}
353332
354333static int tracefs_show_options (struct seq_file * m , struct dentry * root )
355334{
356335 struct tracefs_fs_info * fsi = root -> d_sb -> s_fs_info ;
357- struct tracefs_mount_opts * opts = & fsi -> mount_opts ;
358336
359- if (!uid_eq (opts -> uid , GLOBAL_ROOT_UID ))
337+ if (!uid_eq (fsi -> uid , GLOBAL_ROOT_UID ))
360338 seq_printf (m , ",uid=%u" ,
361- from_kuid_munged (& init_user_ns , opts -> uid ));
362- if (!gid_eq (opts -> gid , GLOBAL_ROOT_GID ))
339+ from_kuid_munged (& init_user_ns , fsi -> uid ));
340+ if (!gid_eq (fsi -> gid , GLOBAL_ROOT_GID ))
363341 seq_printf (m , ",gid=%u" ,
364- from_kgid_munged (& init_user_ns , opts -> gid ));
365- if (opts -> mode != TRACEFS_DEFAULT_MODE )
366- seq_printf (m , ",mode=%o" , opts -> mode );
342+ from_kgid_munged (& init_user_ns , fsi -> gid ));
343+ if (fsi -> mode != TRACEFS_DEFAULT_MODE )
344+ seq_printf (m , ",mode=%o" , fsi -> mode );
367345
368346 return 0 ;
369347}
@@ -373,7 +351,6 @@ static const struct super_operations tracefs_super_operations = {
373351 .free_inode = tracefs_free_inode ,
374352 .drop_inode = generic_delete_inode ,
375353 .statfs = simple_statfs ,
376- .remount_fs = tracefs_remount ,
377354 .show_options = tracefs_show_options ,
378355};
379356
@@ -403,51 +380,60 @@ static const struct dentry_operations tracefs_dentry_operations = {
403380 .d_release = tracefs_d_release ,
404381};
405382
406- static int trace_fill_super (struct super_block * sb , void * data , int silent )
383+ static int tracefs_fill_super (struct super_block * sb , struct fs_context * fc )
407384{
408385 static const struct tree_descr trace_files [] = {{"" }};
409- struct tracefs_fs_info * fsi ;
410386 int err ;
411387
412- fsi = kzalloc (sizeof (struct tracefs_fs_info ), GFP_KERNEL );
413- sb -> s_fs_info = fsi ;
414- if (!fsi ) {
415- err = - ENOMEM ;
416- goto fail ;
417- }
418-
419- err = tracefs_parse_options (data , & fsi -> mount_opts );
420- if (err )
421- goto fail ;
422-
423- err = simple_fill_super (sb , TRACEFS_MAGIC , trace_files );
388+ err = simple_fill_super (sb , TRACEFS_MAGIC , trace_files );
424389 if (err )
425- goto fail ;
390+ return err ;
426391
427392 sb -> s_op = & tracefs_super_operations ;
428393 sb -> s_d_op = & tracefs_dentry_operations ;
429394
430395 tracefs_apply_options (sb , false);
431396
432397 return 0 ;
398+ }
433399
434- fail :
435- kfree (fsi );
436- sb -> s_fs_info = NULL ;
437- return err ;
400+ static int tracefs_get_tree (struct fs_context * fc )
401+ {
402+ return get_tree_single (fc , tracefs_fill_super );
438403}
439404
440- static struct dentry * trace_mount (struct file_system_type * fs_type ,
441- int flags , const char * dev_name ,
442- void * data )
405+ static void tracefs_free_fc (struct fs_context * fc )
443406{
444- return mount_single (fs_type , flags , data , trace_fill_super );
407+ kfree (fc -> s_fs_info );
408+ }
409+
410+ static const struct fs_context_operations tracefs_context_ops = {
411+ .free = tracefs_free_fc ,
412+ .parse_param = tracefs_parse_param ,
413+ .get_tree = tracefs_get_tree ,
414+ .reconfigure = tracefs_reconfigure ,
415+ };
416+
417+ static int tracefs_init_fs_context (struct fs_context * fc )
418+ {
419+ struct tracefs_fs_info * fsi ;
420+
421+ fsi = kzalloc (sizeof (struct tracefs_fs_info ), GFP_KERNEL );
422+ if (!fsi )
423+ return - ENOMEM ;
424+
425+ fsi -> mode = TRACEFS_DEFAULT_MODE ;
426+
427+ fc -> s_fs_info = fsi ;
428+ fc -> ops = & tracefs_context_ops ;
429+ return 0 ;
445430}
446431
447432static struct file_system_type trace_fs_type = {
448433 .owner = THIS_MODULE ,
449434 .name = "tracefs" ,
450- .mount = trace_mount ,
435+ .init_fs_context = tracefs_init_fs_context ,
436+ .parameters = tracefs_param_specs ,
451437 .kill_sb = kill_litter_super ,
452438};
453439MODULE_ALIAS_FS ("tracefs" );
0 commit comments