Skip to content

Commit 78ff640

Browse files
dhowellsbrauner
authored andcommitted
vfs: Convert tracefs to use the new mount API
Convert the tracefs filesystem to the new internal mount API as the old one will be obsoleted and removed. This allows greater flexibility in communication of mount parameters between userspace, the VFS and the filesystem. See Documentation/filesystems/mount_api.txt for more information. Signed-off-by: David Howells <dhowells@redhat.com> Co-developed-by: Eric Sandeen <sandeen@redhat.com> Signed-off-by: Eric Sandeen <sandeen@redhat.com> [sandeen: forward port to modern kernel, fix remounting] Link: https://lore.kernel.org/r/536e99d3-345c-448b-adee-a21389d7ab4b@redhat.com cc: Steven Rostedt <rostedt@goodmis.org> cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Christian Brauner <brauner@kernel.org>
1 parent a20971c commit 78ff640

File tree

1 file changed

+91
-105
lines changed

1 file changed

+91
-105
lines changed

fs/tracefs/inode.c

Lines changed: 91 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@
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

311294
static 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

354333
static 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

447432
static 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
};
453439
MODULE_ALIAS_FS("tracefs");

0 commit comments

Comments
 (0)