11
11
12
12
#include <linux/module.h>
13
13
#include <linux/fs.h>
14
- #include <linux/mount.h>
14
+ #include <linux/fs_context.h>
15
+ #include <linux/fs_parser.h>
15
16
#include <linux/kobject.h>
16
17
#include <linux/namei.h>
17
18
#include <linux/tracefs.h>
18
19
#include <linux/fsnotify.h>
19
20
#include <linux/security.h>
20
21
#include <linux/seq_file.h>
21
- #include <linux/parser.h>
22
22
#include <linux/magic.h>
23
23
#include <linux/slab.h>
24
24
#include "internal.h"
@@ -231,7 +231,7 @@ struct inode *tracefs_get_inode(struct super_block *sb)
231
231
return inode ;
232
232
}
233
233
234
- struct tracefs_mount_opts {
234
+ struct tracefs_fs_info {
235
235
kuid_t uid ;
236
236
kgid_t gid ;
237
237
umode_t mode ;
@@ -243,127 +243,105 @@ enum {
243
243
Opt_uid ,
244
244
Opt_gid ,
245
245
Opt_mode ,
246
- Opt_err
247
246
};
248
247
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
+ {}
254
253
};
255
254
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 )
261
256
{
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 ;
265
259
kuid_t uid ;
266
260
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
+ */
306
287
}
307
288
289
+ opts -> opts |= BIT (opt );
290
+
308
291
return 0 ;
309
292
}
310
293
311
294
static int tracefs_apply_options (struct super_block * sb , bool remount )
312
295
{
313
296
struct tracefs_fs_info * fsi = sb -> s_fs_info ;
314
297
struct inode * inode = d_inode (sb -> s_root );
315
- struct tracefs_mount_opts * opts = & fsi -> mount_opts ;
316
298
umode_t tmp_mode ;
317
299
318
300
/*
319
301
* On remount, only reset mode/uid/gid if they were provided as mount
320
302
* options.
321
303
*/
322
304
323
- if (!remount || opts -> opts & BIT (Opt_mode )) {
305
+ if (!remount || fsi -> opts & BIT (Opt_mode )) {
324
306
tmp_mode = READ_ONCE (inode -> i_mode ) & ~S_IALLUGO ;
325
- tmp_mode |= opts -> mode ;
307
+ tmp_mode |= fsi -> mode ;
326
308
WRITE_ONCE (inode -> i_mode , tmp_mode );
327
309
}
328
310
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 ;
331
313
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 ;
334
316
335
317
return 0 ;
336
318
}
337
319
338
- static int tracefs_remount (struct super_block * sb , int * flags , char * data )
320
+ static int tracefs_reconfigure (struct fs_context * fc )
339
321
{
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 ;
342
325
343
326
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 ;
347
329
348
- tracefs_apply_options (sb , true);
349
-
350
- fail :
351
- return err ;
330
+ return tracefs_apply_options (sb , true);
352
331
}
353
332
354
333
static int tracefs_show_options (struct seq_file * m , struct dentry * root )
355
334
{
356
335
struct tracefs_fs_info * fsi = root -> d_sb -> s_fs_info ;
357
- struct tracefs_mount_opts * opts = & fsi -> mount_opts ;
358
336
359
- if (!uid_eq (opts -> uid , GLOBAL_ROOT_UID ))
337
+ if (!uid_eq (fsi -> uid , GLOBAL_ROOT_UID ))
360
338
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 ))
363
341
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 );
367
345
368
346
return 0 ;
369
347
}
@@ -373,7 +351,6 @@ static const struct super_operations tracefs_super_operations = {
373
351
.free_inode = tracefs_free_inode ,
374
352
.drop_inode = generic_delete_inode ,
375
353
.statfs = simple_statfs ,
376
- .remount_fs = tracefs_remount ,
377
354
.show_options = tracefs_show_options ,
378
355
};
379
356
@@ -403,51 +380,60 @@ static const struct dentry_operations tracefs_dentry_operations = {
403
380
.d_release = tracefs_d_release ,
404
381
};
405
382
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 )
407
384
{
408
385
static const struct tree_descr trace_files [] = {{"" }};
409
- struct tracefs_fs_info * fsi ;
410
386
int err ;
411
387
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 );
424
389
if (err )
425
- goto fail ;
390
+ return err ;
426
391
427
392
sb -> s_op = & tracefs_super_operations ;
428
393
sb -> s_d_op = & tracefs_dentry_operations ;
429
394
430
395
tracefs_apply_options (sb , false);
431
396
432
397
return 0 ;
398
+ }
433
399
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 );
438
403
}
439
404
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 )
443
406
{
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 ;
445
430
}
446
431
447
432
static struct file_system_type trace_fs_type = {
448
433
.owner = THIS_MODULE ,
449
434
.name = "tracefs" ,
450
- .mount = trace_mount ,
435
+ .init_fs_context = tracefs_init_fs_context ,
436
+ .parameters = tracefs_param_specs ,
451
437
.kill_sb = kill_litter_super ,
452
438
};
453
439
MODULE_ALIAS_FS ("tracefs" );
0 commit comments