162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *  inode.c - part of debugfs, a tiny little debug file system
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci *  Copyright (C) 2004,2019 Greg Kroah-Hartman <greg@kroah.com>
662306a36Sopenharmony_ci *  Copyright (C) 2004 IBM Inc.
762306a36Sopenharmony_ci *  Copyright (C) 2019 Linux Foundation <gregkh@linuxfoundation.org>
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci *  debugfs is for people to use instead of /proc or /sys.
1062306a36Sopenharmony_ci *  See ./Documentation/core-api/kernel-api.rst for more details.
1162306a36Sopenharmony_ci */
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#define pr_fmt(fmt)	"debugfs: " fmt
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#include <linux/module.h>
1662306a36Sopenharmony_ci#include <linux/fs.h>
1762306a36Sopenharmony_ci#include <linux/mount.h>
1862306a36Sopenharmony_ci#include <linux/pagemap.h>
1962306a36Sopenharmony_ci#include <linux/init.h>
2062306a36Sopenharmony_ci#include <linux/kobject.h>
2162306a36Sopenharmony_ci#include <linux/namei.h>
2262306a36Sopenharmony_ci#include <linux/debugfs.h>
2362306a36Sopenharmony_ci#include <linux/fsnotify.h>
2462306a36Sopenharmony_ci#include <linux/string.h>
2562306a36Sopenharmony_ci#include <linux/seq_file.h>
2662306a36Sopenharmony_ci#include <linux/parser.h>
2762306a36Sopenharmony_ci#include <linux/magic.h>
2862306a36Sopenharmony_ci#include <linux/slab.h>
2962306a36Sopenharmony_ci#include <linux/security.h>
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci#include "internal.h"
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci#define DEBUGFS_DEFAULT_MODE	0700
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_cistatic struct vfsmount *debugfs_mount;
3662306a36Sopenharmony_cistatic int debugfs_mount_count;
3762306a36Sopenharmony_cistatic bool debugfs_registered;
3862306a36Sopenharmony_cistatic unsigned int debugfs_allow __ro_after_init = DEFAULT_DEBUGFS_ALLOW_BITS;
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci/*
4162306a36Sopenharmony_ci * Don't allow access attributes to be changed whilst the kernel is locked down
4262306a36Sopenharmony_ci * so that we can use the file mode as part of a heuristic to determine whether
4362306a36Sopenharmony_ci * to lock down individual files.
4462306a36Sopenharmony_ci */
4562306a36Sopenharmony_cistatic int debugfs_setattr(struct mnt_idmap *idmap,
4662306a36Sopenharmony_ci			   struct dentry *dentry, struct iattr *ia)
4762306a36Sopenharmony_ci{
4862306a36Sopenharmony_ci	int ret;
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	if (ia->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)) {
5162306a36Sopenharmony_ci		ret = security_locked_down(LOCKDOWN_DEBUGFS);
5262306a36Sopenharmony_ci		if (ret)
5362306a36Sopenharmony_ci			return ret;
5462306a36Sopenharmony_ci	}
5562306a36Sopenharmony_ci	return simple_setattr(&nop_mnt_idmap, dentry, ia);
5662306a36Sopenharmony_ci}
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_cistatic const struct inode_operations debugfs_file_inode_operations = {
5962306a36Sopenharmony_ci	.setattr	= debugfs_setattr,
6062306a36Sopenharmony_ci};
6162306a36Sopenharmony_cistatic const struct inode_operations debugfs_dir_inode_operations = {
6262306a36Sopenharmony_ci	.lookup		= simple_lookup,
6362306a36Sopenharmony_ci	.setattr	= debugfs_setattr,
6462306a36Sopenharmony_ci};
6562306a36Sopenharmony_cistatic const struct inode_operations debugfs_symlink_inode_operations = {
6662306a36Sopenharmony_ci	.get_link	= simple_get_link,
6762306a36Sopenharmony_ci	.setattr	= debugfs_setattr,
6862306a36Sopenharmony_ci};
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_cistatic struct inode *debugfs_get_inode(struct super_block *sb)
7162306a36Sopenharmony_ci{
7262306a36Sopenharmony_ci	struct inode *inode = new_inode(sb);
7362306a36Sopenharmony_ci	if (inode) {
7462306a36Sopenharmony_ci		inode->i_ino = get_next_ino();
7562306a36Sopenharmony_ci		inode->i_atime = inode->i_mtime = inode_set_ctime_current(inode);
7662306a36Sopenharmony_ci	}
7762306a36Sopenharmony_ci	return inode;
7862306a36Sopenharmony_ci}
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_cistruct debugfs_mount_opts {
8162306a36Sopenharmony_ci	kuid_t uid;
8262306a36Sopenharmony_ci	kgid_t gid;
8362306a36Sopenharmony_ci	umode_t mode;
8462306a36Sopenharmony_ci	/* Opt_* bitfield. */
8562306a36Sopenharmony_ci	unsigned int opts;
8662306a36Sopenharmony_ci};
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_cienum {
8962306a36Sopenharmony_ci	Opt_uid,
9062306a36Sopenharmony_ci	Opt_gid,
9162306a36Sopenharmony_ci	Opt_mode,
9262306a36Sopenharmony_ci	Opt_err
9362306a36Sopenharmony_ci};
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_cistatic const match_table_t tokens = {
9662306a36Sopenharmony_ci	{Opt_uid, "uid=%u"},
9762306a36Sopenharmony_ci	{Opt_gid, "gid=%u"},
9862306a36Sopenharmony_ci	{Opt_mode, "mode=%o"},
9962306a36Sopenharmony_ci	{Opt_err, NULL}
10062306a36Sopenharmony_ci};
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_cistruct debugfs_fs_info {
10362306a36Sopenharmony_ci	struct debugfs_mount_opts mount_opts;
10462306a36Sopenharmony_ci};
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_cistatic int debugfs_parse_options(char *data, struct debugfs_mount_opts *opts)
10762306a36Sopenharmony_ci{
10862306a36Sopenharmony_ci	substring_t args[MAX_OPT_ARGS];
10962306a36Sopenharmony_ci	int option;
11062306a36Sopenharmony_ci	int token;
11162306a36Sopenharmony_ci	kuid_t uid;
11262306a36Sopenharmony_ci	kgid_t gid;
11362306a36Sopenharmony_ci	char *p;
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci	opts->opts = 0;
11662306a36Sopenharmony_ci	opts->mode = DEBUGFS_DEFAULT_MODE;
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	while ((p = strsep(&data, ",")) != NULL) {
11962306a36Sopenharmony_ci		if (!*p)
12062306a36Sopenharmony_ci			continue;
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci		token = match_token(p, tokens, args);
12362306a36Sopenharmony_ci		switch (token) {
12462306a36Sopenharmony_ci		case Opt_uid:
12562306a36Sopenharmony_ci			if (match_int(&args[0], &option))
12662306a36Sopenharmony_ci				return -EINVAL;
12762306a36Sopenharmony_ci			uid = make_kuid(current_user_ns(), option);
12862306a36Sopenharmony_ci			if (!uid_valid(uid))
12962306a36Sopenharmony_ci				return -EINVAL;
13062306a36Sopenharmony_ci			opts->uid = uid;
13162306a36Sopenharmony_ci			break;
13262306a36Sopenharmony_ci		case Opt_gid:
13362306a36Sopenharmony_ci			if (match_int(&args[0], &option))
13462306a36Sopenharmony_ci				return -EINVAL;
13562306a36Sopenharmony_ci			gid = make_kgid(current_user_ns(), option);
13662306a36Sopenharmony_ci			if (!gid_valid(gid))
13762306a36Sopenharmony_ci				return -EINVAL;
13862306a36Sopenharmony_ci			opts->gid = gid;
13962306a36Sopenharmony_ci			break;
14062306a36Sopenharmony_ci		case Opt_mode:
14162306a36Sopenharmony_ci			if (match_octal(&args[0], &option))
14262306a36Sopenharmony_ci				return -EINVAL;
14362306a36Sopenharmony_ci			opts->mode = option & S_IALLUGO;
14462306a36Sopenharmony_ci			break;
14562306a36Sopenharmony_ci		/*
14662306a36Sopenharmony_ci		 * We might like to report bad mount options here;
14762306a36Sopenharmony_ci		 * but traditionally debugfs has ignored all mount options
14862306a36Sopenharmony_ci		 */
14962306a36Sopenharmony_ci		}
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci		opts->opts |= BIT(token);
15262306a36Sopenharmony_ci	}
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci	return 0;
15562306a36Sopenharmony_ci}
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_cistatic void _debugfs_apply_options(struct super_block *sb, bool remount)
15862306a36Sopenharmony_ci{
15962306a36Sopenharmony_ci	struct debugfs_fs_info *fsi = sb->s_fs_info;
16062306a36Sopenharmony_ci	struct inode *inode = d_inode(sb->s_root);
16162306a36Sopenharmony_ci	struct debugfs_mount_opts *opts = &fsi->mount_opts;
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci	/*
16462306a36Sopenharmony_ci	 * On remount, only reset mode/uid/gid if they were provided as mount
16562306a36Sopenharmony_ci	 * options.
16662306a36Sopenharmony_ci	 */
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	if (!remount || opts->opts & BIT(Opt_mode)) {
16962306a36Sopenharmony_ci		inode->i_mode &= ~S_IALLUGO;
17062306a36Sopenharmony_ci		inode->i_mode |= opts->mode;
17162306a36Sopenharmony_ci	}
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci	if (!remount || opts->opts & BIT(Opt_uid))
17462306a36Sopenharmony_ci		inode->i_uid = opts->uid;
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	if (!remount || opts->opts & BIT(Opt_gid))
17762306a36Sopenharmony_ci		inode->i_gid = opts->gid;
17862306a36Sopenharmony_ci}
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_cistatic void debugfs_apply_options(struct super_block *sb)
18162306a36Sopenharmony_ci{
18262306a36Sopenharmony_ci	_debugfs_apply_options(sb, false);
18362306a36Sopenharmony_ci}
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_cistatic void debugfs_apply_options_remount(struct super_block *sb)
18662306a36Sopenharmony_ci{
18762306a36Sopenharmony_ci	_debugfs_apply_options(sb, true);
18862306a36Sopenharmony_ci}
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_cistatic int debugfs_remount(struct super_block *sb, int *flags, char *data)
19162306a36Sopenharmony_ci{
19262306a36Sopenharmony_ci	int err;
19362306a36Sopenharmony_ci	struct debugfs_fs_info *fsi = sb->s_fs_info;
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci	sync_filesystem(sb);
19662306a36Sopenharmony_ci	err = debugfs_parse_options(data, &fsi->mount_opts);
19762306a36Sopenharmony_ci	if (err)
19862306a36Sopenharmony_ci		goto fail;
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	debugfs_apply_options_remount(sb);
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_cifail:
20362306a36Sopenharmony_ci	return err;
20462306a36Sopenharmony_ci}
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_cistatic int debugfs_show_options(struct seq_file *m, struct dentry *root)
20762306a36Sopenharmony_ci{
20862306a36Sopenharmony_ci	struct debugfs_fs_info *fsi = root->d_sb->s_fs_info;
20962306a36Sopenharmony_ci	struct debugfs_mount_opts *opts = &fsi->mount_opts;
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci	if (!uid_eq(opts->uid, GLOBAL_ROOT_UID))
21262306a36Sopenharmony_ci		seq_printf(m, ",uid=%u",
21362306a36Sopenharmony_ci			   from_kuid_munged(&init_user_ns, opts->uid));
21462306a36Sopenharmony_ci	if (!gid_eq(opts->gid, GLOBAL_ROOT_GID))
21562306a36Sopenharmony_ci		seq_printf(m, ",gid=%u",
21662306a36Sopenharmony_ci			   from_kgid_munged(&init_user_ns, opts->gid));
21762306a36Sopenharmony_ci	if (opts->mode != DEBUGFS_DEFAULT_MODE)
21862306a36Sopenharmony_ci		seq_printf(m, ",mode=%o", opts->mode);
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci	return 0;
22162306a36Sopenharmony_ci}
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_cistatic void debugfs_free_inode(struct inode *inode)
22462306a36Sopenharmony_ci{
22562306a36Sopenharmony_ci	if (S_ISLNK(inode->i_mode))
22662306a36Sopenharmony_ci		kfree(inode->i_link);
22762306a36Sopenharmony_ci	free_inode_nonrcu(inode);
22862306a36Sopenharmony_ci}
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_cistatic const struct super_operations debugfs_super_operations = {
23162306a36Sopenharmony_ci	.statfs		= simple_statfs,
23262306a36Sopenharmony_ci	.remount_fs	= debugfs_remount,
23362306a36Sopenharmony_ci	.show_options	= debugfs_show_options,
23462306a36Sopenharmony_ci	.free_inode	= debugfs_free_inode,
23562306a36Sopenharmony_ci};
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_cistatic void debugfs_release_dentry(struct dentry *dentry)
23862306a36Sopenharmony_ci{
23962306a36Sopenharmony_ci	struct debugfs_fsdata *fsd = dentry->d_fsdata;
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci	if ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)
24262306a36Sopenharmony_ci		return;
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	kfree(fsd);
24562306a36Sopenharmony_ci}
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_cistatic struct vfsmount *debugfs_automount(struct path *path)
24862306a36Sopenharmony_ci{
24962306a36Sopenharmony_ci	struct debugfs_fsdata *fsd = path->dentry->d_fsdata;
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci	return fsd->automount(path->dentry, d_inode(path->dentry)->i_private);
25262306a36Sopenharmony_ci}
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_cistatic const struct dentry_operations debugfs_dops = {
25562306a36Sopenharmony_ci	.d_delete = always_delete_dentry,
25662306a36Sopenharmony_ci	.d_release = debugfs_release_dentry,
25762306a36Sopenharmony_ci	.d_automount = debugfs_automount,
25862306a36Sopenharmony_ci};
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_cistatic int debug_fill_super(struct super_block *sb, void *data, int silent)
26162306a36Sopenharmony_ci{
26262306a36Sopenharmony_ci	static const struct tree_descr debug_files[] = {{""}};
26362306a36Sopenharmony_ci	struct debugfs_fs_info *fsi;
26462306a36Sopenharmony_ci	int err;
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci	fsi = kzalloc(sizeof(struct debugfs_fs_info), GFP_KERNEL);
26762306a36Sopenharmony_ci	sb->s_fs_info = fsi;
26862306a36Sopenharmony_ci	if (!fsi) {
26962306a36Sopenharmony_ci		err = -ENOMEM;
27062306a36Sopenharmony_ci		goto fail;
27162306a36Sopenharmony_ci	}
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci	err = debugfs_parse_options(data, &fsi->mount_opts);
27462306a36Sopenharmony_ci	if (err)
27562306a36Sopenharmony_ci		goto fail;
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci	err  =  simple_fill_super(sb, DEBUGFS_MAGIC, debug_files);
27862306a36Sopenharmony_ci	if (err)
27962306a36Sopenharmony_ci		goto fail;
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci	sb->s_op = &debugfs_super_operations;
28262306a36Sopenharmony_ci	sb->s_d_op = &debugfs_dops;
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	debugfs_apply_options(sb);
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci	return 0;
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_cifail:
28962306a36Sopenharmony_ci	kfree(fsi);
29062306a36Sopenharmony_ci	sb->s_fs_info = NULL;
29162306a36Sopenharmony_ci	return err;
29262306a36Sopenharmony_ci}
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_cistatic struct dentry *debug_mount(struct file_system_type *fs_type,
29562306a36Sopenharmony_ci			int flags, const char *dev_name,
29662306a36Sopenharmony_ci			void *data)
29762306a36Sopenharmony_ci{
29862306a36Sopenharmony_ci	if (!(debugfs_allow & DEBUGFS_ALLOW_API))
29962306a36Sopenharmony_ci		return ERR_PTR(-EPERM);
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ci	return mount_single(fs_type, flags, data, debug_fill_super);
30262306a36Sopenharmony_ci}
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_cistatic struct file_system_type debug_fs_type = {
30562306a36Sopenharmony_ci	.owner =	THIS_MODULE,
30662306a36Sopenharmony_ci	.name =		"debugfs",
30762306a36Sopenharmony_ci	.mount =	debug_mount,
30862306a36Sopenharmony_ci	.kill_sb =	kill_litter_super,
30962306a36Sopenharmony_ci};
31062306a36Sopenharmony_ciMODULE_ALIAS_FS("debugfs");
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci/**
31362306a36Sopenharmony_ci * debugfs_lookup() - look up an existing debugfs file
31462306a36Sopenharmony_ci * @name: a pointer to a string containing the name of the file to look up.
31562306a36Sopenharmony_ci * @parent: a pointer to the parent dentry of the file.
31662306a36Sopenharmony_ci *
31762306a36Sopenharmony_ci * This function will return a pointer to a dentry if it succeeds.  If the file
31862306a36Sopenharmony_ci * doesn't exist or an error occurs, %NULL will be returned.  The returned
31962306a36Sopenharmony_ci * dentry must be passed to dput() when it is no longer needed.
32062306a36Sopenharmony_ci *
32162306a36Sopenharmony_ci * If debugfs is not enabled in the kernel, the value -%ENODEV will be
32262306a36Sopenharmony_ci * returned.
32362306a36Sopenharmony_ci */
32462306a36Sopenharmony_cistruct dentry *debugfs_lookup(const char *name, struct dentry *parent)
32562306a36Sopenharmony_ci{
32662306a36Sopenharmony_ci	struct dentry *dentry;
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci	if (!debugfs_initialized() || IS_ERR_OR_NULL(name) || IS_ERR(parent))
32962306a36Sopenharmony_ci		return NULL;
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci	if (!parent)
33262306a36Sopenharmony_ci		parent = debugfs_mount->mnt_root;
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	dentry = lookup_positive_unlocked(name, parent, strlen(name));
33562306a36Sopenharmony_ci	if (IS_ERR(dentry))
33662306a36Sopenharmony_ci		return NULL;
33762306a36Sopenharmony_ci	return dentry;
33862306a36Sopenharmony_ci}
33962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(debugfs_lookup);
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_cistatic struct dentry *start_creating(const char *name, struct dentry *parent)
34262306a36Sopenharmony_ci{
34362306a36Sopenharmony_ci	struct dentry *dentry;
34462306a36Sopenharmony_ci	int error;
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ci	if (!(debugfs_allow & DEBUGFS_ALLOW_API))
34762306a36Sopenharmony_ci		return ERR_PTR(-EPERM);
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci	if (!debugfs_initialized())
35062306a36Sopenharmony_ci		return ERR_PTR(-ENOENT);
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci	pr_debug("creating file '%s'\n", name);
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci	if (IS_ERR(parent))
35562306a36Sopenharmony_ci		return parent;
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci	error = simple_pin_fs(&debug_fs_type, &debugfs_mount,
35862306a36Sopenharmony_ci			      &debugfs_mount_count);
35962306a36Sopenharmony_ci	if (error) {
36062306a36Sopenharmony_ci		pr_err("Unable to pin filesystem for file '%s'\n", name);
36162306a36Sopenharmony_ci		return ERR_PTR(error);
36262306a36Sopenharmony_ci	}
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci	/* If the parent is not specified, we create it in the root.
36562306a36Sopenharmony_ci	 * We need the root dentry to do this, which is in the super
36662306a36Sopenharmony_ci	 * block. A pointer to that is in the struct vfsmount that we
36762306a36Sopenharmony_ci	 * have around.
36862306a36Sopenharmony_ci	 */
36962306a36Sopenharmony_ci	if (!parent)
37062306a36Sopenharmony_ci		parent = debugfs_mount->mnt_root;
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_ci	inode_lock(d_inode(parent));
37362306a36Sopenharmony_ci	if (unlikely(IS_DEADDIR(d_inode(parent))))
37462306a36Sopenharmony_ci		dentry = ERR_PTR(-ENOENT);
37562306a36Sopenharmony_ci	else
37662306a36Sopenharmony_ci		dentry = lookup_one_len(name, parent, strlen(name));
37762306a36Sopenharmony_ci	if (!IS_ERR(dentry) && d_really_is_positive(dentry)) {
37862306a36Sopenharmony_ci		if (d_is_dir(dentry))
37962306a36Sopenharmony_ci			pr_err("Directory '%s' with parent '%s' already present!\n",
38062306a36Sopenharmony_ci			       name, parent->d_name.name);
38162306a36Sopenharmony_ci		else
38262306a36Sopenharmony_ci			pr_err("File '%s' in directory '%s' already present!\n",
38362306a36Sopenharmony_ci			       name, parent->d_name.name);
38462306a36Sopenharmony_ci		dput(dentry);
38562306a36Sopenharmony_ci		dentry = ERR_PTR(-EEXIST);
38662306a36Sopenharmony_ci	}
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_ci	if (IS_ERR(dentry)) {
38962306a36Sopenharmony_ci		inode_unlock(d_inode(parent));
39062306a36Sopenharmony_ci		simple_release_fs(&debugfs_mount, &debugfs_mount_count);
39162306a36Sopenharmony_ci	}
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci	return dentry;
39462306a36Sopenharmony_ci}
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_cistatic struct dentry *failed_creating(struct dentry *dentry)
39762306a36Sopenharmony_ci{
39862306a36Sopenharmony_ci	inode_unlock(d_inode(dentry->d_parent));
39962306a36Sopenharmony_ci	dput(dentry);
40062306a36Sopenharmony_ci	simple_release_fs(&debugfs_mount, &debugfs_mount_count);
40162306a36Sopenharmony_ci	return ERR_PTR(-ENOMEM);
40262306a36Sopenharmony_ci}
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_cistatic struct dentry *end_creating(struct dentry *dentry)
40562306a36Sopenharmony_ci{
40662306a36Sopenharmony_ci	inode_unlock(d_inode(dentry->d_parent));
40762306a36Sopenharmony_ci	return dentry;
40862306a36Sopenharmony_ci}
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_cistatic struct dentry *__debugfs_create_file(const char *name, umode_t mode,
41162306a36Sopenharmony_ci				struct dentry *parent, void *data,
41262306a36Sopenharmony_ci				const struct file_operations *proxy_fops,
41362306a36Sopenharmony_ci				const struct file_operations *real_fops)
41462306a36Sopenharmony_ci{
41562306a36Sopenharmony_ci	struct dentry *dentry;
41662306a36Sopenharmony_ci	struct inode *inode;
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci	if (!(mode & S_IFMT))
41962306a36Sopenharmony_ci		mode |= S_IFREG;
42062306a36Sopenharmony_ci	BUG_ON(!S_ISREG(mode));
42162306a36Sopenharmony_ci	dentry = start_creating(name, parent);
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci	if (IS_ERR(dentry))
42462306a36Sopenharmony_ci		return dentry;
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci	if (!(debugfs_allow & DEBUGFS_ALLOW_API)) {
42762306a36Sopenharmony_ci		failed_creating(dentry);
42862306a36Sopenharmony_ci		return ERR_PTR(-EPERM);
42962306a36Sopenharmony_ci	}
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	inode = debugfs_get_inode(dentry->d_sb);
43262306a36Sopenharmony_ci	if (unlikely(!inode)) {
43362306a36Sopenharmony_ci		pr_err("out of free dentries, can not create file '%s'\n",
43462306a36Sopenharmony_ci		       name);
43562306a36Sopenharmony_ci		return failed_creating(dentry);
43662306a36Sopenharmony_ci	}
43762306a36Sopenharmony_ci
43862306a36Sopenharmony_ci	inode->i_mode = mode;
43962306a36Sopenharmony_ci	inode->i_private = data;
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ci	inode->i_op = &debugfs_file_inode_operations;
44262306a36Sopenharmony_ci	inode->i_fop = proxy_fops;
44362306a36Sopenharmony_ci	dentry->d_fsdata = (void *)((unsigned long)real_fops |
44462306a36Sopenharmony_ci				DEBUGFS_FSDATA_IS_REAL_FOPS_BIT);
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_ci	d_instantiate(dentry, inode);
44762306a36Sopenharmony_ci	fsnotify_create(d_inode(dentry->d_parent), dentry);
44862306a36Sopenharmony_ci	return end_creating(dentry);
44962306a36Sopenharmony_ci}
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ci/**
45262306a36Sopenharmony_ci * debugfs_create_file - create a file in the debugfs filesystem
45362306a36Sopenharmony_ci * @name: a pointer to a string containing the name of the file to create.
45462306a36Sopenharmony_ci * @mode: the permission that the file should have.
45562306a36Sopenharmony_ci * @parent: a pointer to the parent dentry for this file.  This should be a
45662306a36Sopenharmony_ci *          directory dentry if set.  If this parameter is NULL, then the
45762306a36Sopenharmony_ci *          file will be created in the root of the debugfs filesystem.
45862306a36Sopenharmony_ci * @data: a pointer to something that the caller will want to get to later
45962306a36Sopenharmony_ci *        on.  The inode.i_private pointer will point to this value on
46062306a36Sopenharmony_ci *        the open() call.
46162306a36Sopenharmony_ci * @fops: a pointer to a struct file_operations that should be used for
46262306a36Sopenharmony_ci *        this file.
46362306a36Sopenharmony_ci *
46462306a36Sopenharmony_ci * This is the basic "create a file" function for debugfs.  It allows for a
46562306a36Sopenharmony_ci * wide range of flexibility in creating a file, or a directory (if you want
46662306a36Sopenharmony_ci * to create a directory, the debugfs_create_dir() function is
46762306a36Sopenharmony_ci * recommended to be used instead.)
46862306a36Sopenharmony_ci *
46962306a36Sopenharmony_ci * This function will return a pointer to a dentry if it succeeds.  This
47062306a36Sopenharmony_ci * pointer must be passed to the debugfs_remove() function when the file is
47162306a36Sopenharmony_ci * to be removed (no automatic cleanup happens if your module is unloaded,
47262306a36Sopenharmony_ci * you are responsible here.)  If an error occurs, ERR_PTR(-ERROR) will be
47362306a36Sopenharmony_ci * returned.
47462306a36Sopenharmony_ci *
47562306a36Sopenharmony_ci * If debugfs is not enabled in the kernel, the value -%ENODEV will be
47662306a36Sopenharmony_ci * returned.
47762306a36Sopenharmony_ci *
47862306a36Sopenharmony_ci * NOTE: it's expected that most callers should _ignore_ the errors returned
47962306a36Sopenharmony_ci * by this function. Other debugfs functions handle the fact that the "dentry"
48062306a36Sopenharmony_ci * passed to them could be an error and they don't crash in that case.
48162306a36Sopenharmony_ci * Drivers should generally work fine even if debugfs fails to init anyway.
48262306a36Sopenharmony_ci */
48362306a36Sopenharmony_cistruct dentry *debugfs_create_file(const char *name, umode_t mode,
48462306a36Sopenharmony_ci				   struct dentry *parent, void *data,
48562306a36Sopenharmony_ci				   const struct file_operations *fops)
48662306a36Sopenharmony_ci{
48762306a36Sopenharmony_ci
48862306a36Sopenharmony_ci	return __debugfs_create_file(name, mode, parent, data,
48962306a36Sopenharmony_ci				fops ? &debugfs_full_proxy_file_operations :
49062306a36Sopenharmony_ci					&debugfs_noop_file_operations,
49162306a36Sopenharmony_ci				fops);
49262306a36Sopenharmony_ci}
49362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(debugfs_create_file);
49462306a36Sopenharmony_ci
49562306a36Sopenharmony_ci/**
49662306a36Sopenharmony_ci * debugfs_create_file_unsafe - create a file in the debugfs filesystem
49762306a36Sopenharmony_ci * @name: a pointer to a string containing the name of the file to create.
49862306a36Sopenharmony_ci * @mode: the permission that the file should have.
49962306a36Sopenharmony_ci * @parent: a pointer to the parent dentry for this file.  This should be a
50062306a36Sopenharmony_ci *          directory dentry if set.  If this parameter is NULL, then the
50162306a36Sopenharmony_ci *          file will be created in the root of the debugfs filesystem.
50262306a36Sopenharmony_ci * @data: a pointer to something that the caller will want to get to later
50362306a36Sopenharmony_ci *        on.  The inode.i_private pointer will point to this value on
50462306a36Sopenharmony_ci *        the open() call.
50562306a36Sopenharmony_ci * @fops: a pointer to a struct file_operations that should be used for
50662306a36Sopenharmony_ci *        this file.
50762306a36Sopenharmony_ci *
50862306a36Sopenharmony_ci * debugfs_create_file_unsafe() is completely analogous to
50962306a36Sopenharmony_ci * debugfs_create_file(), the only difference being that the fops
51062306a36Sopenharmony_ci * handed it will not get protected against file removals by the
51162306a36Sopenharmony_ci * debugfs core.
51262306a36Sopenharmony_ci *
51362306a36Sopenharmony_ci * It is your responsibility to protect your struct file_operation
51462306a36Sopenharmony_ci * methods against file removals by means of debugfs_file_get()
51562306a36Sopenharmony_ci * and debugfs_file_put(). ->open() is still protected by
51662306a36Sopenharmony_ci * debugfs though.
51762306a36Sopenharmony_ci *
51862306a36Sopenharmony_ci * Any struct file_operations defined by means of
51962306a36Sopenharmony_ci * DEFINE_DEBUGFS_ATTRIBUTE() is protected against file removals and
52062306a36Sopenharmony_ci * thus, may be used here.
52162306a36Sopenharmony_ci */
52262306a36Sopenharmony_cistruct dentry *debugfs_create_file_unsafe(const char *name, umode_t mode,
52362306a36Sopenharmony_ci				   struct dentry *parent, void *data,
52462306a36Sopenharmony_ci				   const struct file_operations *fops)
52562306a36Sopenharmony_ci{
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ci	return __debugfs_create_file(name, mode, parent, data,
52862306a36Sopenharmony_ci				fops ? &debugfs_open_proxy_file_operations :
52962306a36Sopenharmony_ci					&debugfs_noop_file_operations,
53062306a36Sopenharmony_ci				fops);
53162306a36Sopenharmony_ci}
53262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(debugfs_create_file_unsafe);
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_ci/**
53562306a36Sopenharmony_ci * debugfs_create_file_size - create a file in the debugfs filesystem
53662306a36Sopenharmony_ci * @name: a pointer to a string containing the name of the file to create.
53762306a36Sopenharmony_ci * @mode: the permission that the file should have.
53862306a36Sopenharmony_ci * @parent: a pointer to the parent dentry for this file.  This should be a
53962306a36Sopenharmony_ci *          directory dentry if set.  If this parameter is NULL, then the
54062306a36Sopenharmony_ci *          file will be created in the root of the debugfs filesystem.
54162306a36Sopenharmony_ci * @data: a pointer to something that the caller will want to get to later
54262306a36Sopenharmony_ci *        on.  The inode.i_private pointer will point to this value on
54362306a36Sopenharmony_ci *        the open() call.
54462306a36Sopenharmony_ci * @fops: a pointer to a struct file_operations that should be used for
54562306a36Sopenharmony_ci *        this file.
54662306a36Sopenharmony_ci * @file_size: initial file size
54762306a36Sopenharmony_ci *
54862306a36Sopenharmony_ci * This is the basic "create a file" function for debugfs.  It allows for a
54962306a36Sopenharmony_ci * wide range of flexibility in creating a file, or a directory (if you want
55062306a36Sopenharmony_ci * to create a directory, the debugfs_create_dir() function is
55162306a36Sopenharmony_ci * recommended to be used instead.)
55262306a36Sopenharmony_ci */
55362306a36Sopenharmony_civoid debugfs_create_file_size(const char *name, umode_t mode,
55462306a36Sopenharmony_ci			      struct dentry *parent, void *data,
55562306a36Sopenharmony_ci			      const struct file_operations *fops,
55662306a36Sopenharmony_ci			      loff_t file_size)
55762306a36Sopenharmony_ci{
55862306a36Sopenharmony_ci	struct dentry *de = debugfs_create_file(name, mode, parent, data, fops);
55962306a36Sopenharmony_ci
56062306a36Sopenharmony_ci	if (!IS_ERR(de))
56162306a36Sopenharmony_ci		d_inode(de)->i_size = file_size;
56262306a36Sopenharmony_ci}
56362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(debugfs_create_file_size);
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_ci/**
56662306a36Sopenharmony_ci * debugfs_create_dir - create a directory in the debugfs filesystem
56762306a36Sopenharmony_ci * @name: a pointer to a string containing the name of the directory to
56862306a36Sopenharmony_ci *        create.
56962306a36Sopenharmony_ci * @parent: a pointer to the parent dentry for this file.  This should be a
57062306a36Sopenharmony_ci *          directory dentry if set.  If this parameter is NULL, then the
57162306a36Sopenharmony_ci *          directory will be created in the root of the debugfs filesystem.
57262306a36Sopenharmony_ci *
57362306a36Sopenharmony_ci * This function creates a directory in debugfs with the given name.
57462306a36Sopenharmony_ci *
57562306a36Sopenharmony_ci * This function will return a pointer to a dentry if it succeeds.  This
57662306a36Sopenharmony_ci * pointer must be passed to the debugfs_remove() function when the file is
57762306a36Sopenharmony_ci * to be removed (no automatic cleanup happens if your module is unloaded,
57862306a36Sopenharmony_ci * you are responsible here.)  If an error occurs, ERR_PTR(-ERROR) will be
57962306a36Sopenharmony_ci * returned.
58062306a36Sopenharmony_ci *
58162306a36Sopenharmony_ci * If debugfs is not enabled in the kernel, the value -%ENODEV will be
58262306a36Sopenharmony_ci * returned.
58362306a36Sopenharmony_ci *
58462306a36Sopenharmony_ci * NOTE: it's expected that most callers should _ignore_ the errors returned
58562306a36Sopenharmony_ci * by this function. Other debugfs functions handle the fact that the "dentry"
58662306a36Sopenharmony_ci * passed to them could be an error and they don't crash in that case.
58762306a36Sopenharmony_ci * Drivers should generally work fine even if debugfs fails to init anyway.
58862306a36Sopenharmony_ci */
58962306a36Sopenharmony_cistruct dentry *debugfs_create_dir(const char *name, struct dentry *parent)
59062306a36Sopenharmony_ci{
59162306a36Sopenharmony_ci	struct dentry *dentry = start_creating(name, parent);
59262306a36Sopenharmony_ci	struct inode *inode;
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_ci	if (IS_ERR(dentry))
59562306a36Sopenharmony_ci		return dentry;
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci	if (!(debugfs_allow & DEBUGFS_ALLOW_API)) {
59862306a36Sopenharmony_ci		failed_creating(dentry);
59962306a36Sopenharmony_ci		return ERR_PTR(-EPERM);
60062306a36Sopenharmony_ci	}
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_ci	inode = debugfs_get_inode(dentry->d_sb);
60362306a36Sopenharmony_ci	if (unlikely(!inode)) {
60462306a36Sopenharmony_ci		pr_err("out of free dentries, can not create directory '%s'\n",
60562306a36Sopenharmony_ci		       name);
60662306a36Sopenharmony_ci		return failed_creating(dentry);
60762306a36Sopenharmony_ci	}
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_ci	inode->i_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
61062306a36Sopenharmony_ci	inode->i_op = &debugfs_dir_inode_operations;
61162306a36Sopenharmony_ci	inode->i_fop = &simple_dir_operations;
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_ci	/* directory inodes start off with i_nlink == 2 (for "." entry) */
61462306a36Sopenharmony_ci	inc_nlink(inode);
61562306a36Sopenharmony_ci	d_instantiate(dentry, inode);
61662306a36Sopenharmony_ci	inc_nlink(d_inode(dentry->d_parent));
61762306a36Sopenharmony_ci	fsnotify_mkdir(d_inode(dentry->d_parent), dentry);
61862306a36Sopenharmony_ci	return end_creating(dentry);
61962306a36Sopenharmony_ci}
62062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(debugfs_create_dir);
62162306a36Sopenharmony_ci
62262306a36Sopenharmony_ci/**
62362306a36Sopenharmony_ci * debugfs_create_automount - create automount point in the debugfs filesystem
62462306a36Sopenharmony_ci * @name: a pointer to a string containing the name of the file to create.
62562306a36Sopenharmony_ci * @parent: a pointer to the parent dentry for this file.  This should be a
62662306a36Sopenharmony_ci *          directory dentry if set.  If this parameter is NULL, then the
62762306a36Sopenharmony_ci *          file will be created in the root of the debugfs filesystem.
62862306a36Sopenharmony_ci * @f: function to be called when pathname resolution steps on that one.
62962306a36Sopenharmony_ci * @data: opaque argument to pass to f().
63062306a36Sopenharmony_ci *
63162306a36Sopenharmony_ci * @f should return what ->d_automount() would.
63262306a36Sopenharmony_ci */
63362306a36Sopenharmony_cistruct dentry *debugfs_create_automount(const char *name,
63462306a36Sopenharmony_ci					struct dentry *parent,
63562306a36Sopenharmony_ci					debugfs_automount_t f,
63662306a36Sopenharmony_ci					void *data)
63762306a36Sopenharmony_ci{
63862306a36Sopenharmony_ci	struct dentry *dentry = start_creating(name, parent);
63962306a36Sopenharmony_ci	struct debugfs_fsdata *fsd;
64062306a36Sopenharmony_ci	struct inode *inode;
64162306a36Sopenharmony_ci
64262306a36Sopenharmony_ci	if (IS_ERR(dentry))
64362306a36Sopenharmony_ci		return dentry;
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_ci	fsd = kzalloc(sizeof(*fsd), GFP_KERNEL);
64662306a36Sopenharmony_ci	if (!fsd) {
64762306a36Sopenharmony_ci		failed_creating(dentry);
64862306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
64962306a36Sopenharmony_ci	}
65062306a36Sopenharmony_ci
65162306a36Sopenharmony_ci	fsd->automount = f;
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_ci	if (!(debugfs_allow & DEBUGFS_ALLOW_API)) {
65462306a36Sopenharmony_ci		failed_creating(dentry);
65562306a36Sopenharmony_ci		kfree(fsd);
65662306a36Sopenharmony_ci		return ERR_PTR(-EPERM);
65762306a36Sopenharmony_ci	}
65862306a36Sopenharmony_ci
65962306a36Sopenharmony_ci	inode = debugfs_get_inode(dentry->d_sb);
66062306a36Sopenharmony_ci	if (unlikely(!inode)) {
66162306a36Sopenharmony_ci		pr_err("out of free dentries, can not create automount '%s'\n",
66262306a36Sopenharmony_ci		       name);
66362306a36Sopenharmony_ci		kfree(fsd);
66462306a36Sopenharmony_ci		return failed_creating(dentry);
66562306a36Sopenharmony_ci	}
66662306a36Sopenharmony_ci
66762306a36Sopenharmony_ci	make_empty_dir_inode(inode);
66862306a36Sopenharmony_ci	inode->i_flags |= S_AUTOMOUNT;
66962306a36Sopenharmony_ci	inode->i_private = data;
67062306a36Sopenharmony_ci	dentry->d_fsdata = fsd;
67162306a36Sopenharmony_ci	/* directory inodes start off with i_nlink == 2 (for "." entry) */
67262306a36Sopenharmony_ci	inc_nlink(inode);
67362306a36Sopenharmony_ci	d_instantiate(dentry, inode);
67462306a36Sopenharmony_ci	inc_nlink(d_inode(dentry->d_parent));
67562306a36Sopenharmony_ci	fsnotify_mkdir(d_inode(dentry->d_parent), dentry);
67662306a36Sopenharmony_ci	return end_creating(dentry);
67762306a36Sopenharmony_ci}
67862306a36Sopenharmony_ciEXPORT_SYMBOL(debugfs_create_automount);
67962306a36Sopenharmony_ci
68062306a36Sopenharmony_ci/**
68162306a36Sopenharmony_ci * debugfs_create_symlink- create a symbolic link in the debugfs filesystem
68262306a36Sopenharmony_ci * @name: a pointer to a string containing the name of the symbolic link to
68362306a36Sopenharmony_ci *        create.
68462306a36Sopenharmony_ci * @parent: a pointer to the parent dentry for this symbolic link.  This
68562306a36Sopenharmony_ci *          should be a directory dentry if set.  If this parameter is NULL,
68662306a36Sopenharmony_ci *          then the symbolic link will be created in the root of the debugfs
68762306a36Sopenharmony_ci *          filesystem.
68862306a36Sopenharmony_ci * @target: a pointer to a string containing the path to the target of the
68962306a36Sopenharmony_ci *          symbolic link.
69062306a36Sopenharmony_ci *
69162306a36Sopenharmony_ci * This function creates a symbolic link with the given name in debugfs that
69262306a36Sopenharmony_ci * links to the given target path.
69362306a36Sopenharmony_ci *
69462306a36Sopenharmony_ci * This function will return a pointer to a dentry if it succeeds.  This
69562306a36Sopenharmony_ci * pointer must be passed to the debugfs_remove() function when the symbolic
69662306a36Sopenharmony_ci * link is to be removed (no automatic cleanup happens if your module is
69762306a36Sopenharmony_ci * unloaded, you are responsible here.)  If an error occurs, ERR_PTR(-ERROR)
69862306a36Sopenharmony_ci * will be returned.
69962306a36Sopenharmony_ci *
70062306a36Sopenharmony_ci * If debugfs is not enabled in the kernel, the value -%ENODEV will be
70162306a36Sopenharmony_ci * returned.
70262306a36Sopenharmony_ci */
70362306a36Sopenharmony_cistruct dentry *debugfs_create_symlink(const char *name, struct dentry *parent,
70462306a36Sopenharmony_ci				      const char *target)
70562306a36Sopenharmony_ci{
70662306a36Sopenharmony_ci	struct dentry *dentry;
70762306a36Sopenharmony_ci	struct inode *inode;
70862306a36Sopenharmony_ci	char *link = kstrdup(target, GFP_KERNEL);
70962306a36Sopenharmony_ci	if (!link)
71062306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
71162306a36Sopenharmony_ci
71262306a36Sopenharmony_ci	dentry = start_creating(name, parent);
71362306a36Sopenharmony_ci	if (IS_ERR(dentry)) {
71462306a36Sopenharmony_ci		kfree(link);
71562306a36Sopenharmony_ci		return dentry;
71662306a36Sopenharmony_ci	}
71762306a36Sopenharmony_ci
71862306a36Sopenharmony_ci	inode = debugfs_get_inode(dentry->d_sb);
71962306a36Sopenharmony_ci	if (unlikely(!inode)) {
72062306a36Sopenharmony_ci		pr_err("out of free dentries, can not create symlink '%s'\n",
72162306a36Sopenharmony_ci		       name);
72262306a36Sopenharmony_ci		kfree(link);
72362306a36Sopenharmony_ci		return failed_creating(dentry);
72462306a36Sopenharmony_ci	}
72562306a36Sopenharmony_ci	inode->i_mode = S_IFLNK | S_IRWXUGO;
72662306a36Sopenharmony_ci	inode->i_op = &debugfs_symlink_inode_operations;
72762306a36Sopenharmony_ci	inode->i_link = link;
72862306a36Sopenharmony_ci	d_instantiate(dentry, inode);
72962306a36Sopenharmony_ci	return end_creating(dentry);
73062306a36Sopenharmony_ci}
73162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(debugfs_create_symlink);
73262306a36Sopenharmony_ci
73362306a36Sopenharmony_cistatic void __debugfs_file_removed(struct dentry *dentry)
73462306a36Sopenharmony_ci{
73562306a36Sopenharmony_ci	struct debugfs_fsdata *fsd;
73662306a36Sopenharmony_ci
73762306a36Sopenharmony_ci	/*
73862306a36Sopenharmony_ci	 * Paired with the closing smp_mb() implied by a successful
73962306a36Sopenharmony_ci	 * cmpxchg() in debugfs_file_get(): either
74062306a36Sopenharmony_ci	 * debugfs_file_get() must see a dead dentry or we must see a
74162306a36Sopenharmony_ci	 * debugfs_fsdata instance at ->d_fsdata here (or both).
74262306a36Sopenharmony_ci	 */
74362306a36Sopenharmony_ci	smp_mb();
74462306a36Sopenharmony_ci	fsd = READ_ONCE(dentry->d_fsdata);
74562306a36Sopenharmony_ci	if ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)
74662306a36Sopenharmony_ci		return;
74762306a36Sopenharmony_ci	if (!refcount_dec_and_test(&fsd->active_users))
74862306a36Sopenharmony_ci		wait_for_completion(&fsd->active_users_drained);
74962306a36Sopenharmony_ci}
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_cistatic void remove_one(struct dentry *victim)
75262306a36Sopenharmony_ci{
75362306a36Sopenharmony_ci        if (d_is_reg(victim))
75462306a36Sopenharmony_ci		__debugfs_file_removed(victim);
75562306a36Sopenharmony_ci	simple_release_fs(&debugfs_mount, &debugfs_mount_count);
75662306a36Sopenharmony_ci}
75762306a36Sopenharmony_ci
75862306a36Sopenharmony_ci/**
75962306a36Sopenharmony_ci * debugfs_remove - recursively removes a directory
76062306a36Sopenharmony_ci * @dentry: a pointer to a the dentry of the directory to be removed.  If this
76162306a36Sopenharmony_ci *          parameter is NULL or an error value, nothing will be done.
76262306a36Sopenharmony_ci *
76362306a36Sopenharmony_ci * This function recursively removes a directory tree in debugfs that
76462306a36Sopenharmony_ci * was previously created with a call to another debugfs function
76562306a36Sopenharmony_ci * (like debugfs_create_file() or variants thereof.)
76662306a36Sopenharmony_ci *
76762306a36Sopenharmony_ci * This function is required to be called in order for the file to be
76862306a36Sopenharmony_ci * removed, no automatic cleanup of files will happen when a module is
76962306a36Sopenharmony_ci * removed, you are responsible here.
77062306a36Sopenharmony_ci */
77162306a36Sopenharmony_civoid debugfs_remove(struct dentry *dentry)
77262306a36Sopenharmony_ci{
77362306a36Sopenharmony_ci	if (IS_ERR_OR_NULL(dentry))
77462306a36Sopenharmony_ci		return;
77562306a36Sopenharmony_ci
77662306a36Sopenharmony_ci	simple_pin_fs(&debug_fs_type, &debugfs_mount, &debugfs_mount_count);
77762306a36Sopenharmony_ci	simple_recursive_removal(dentry, remove_one);
77862306a36Sopenharmony_ci	simple_release_fs(&debugfs_mount, &debugfs_mount_count);
77962306a36Sopenharmony_ci}
78062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(debugfs_remove);
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_ci/**
78362306a36Sopenharmony_ci * debugfs_lookup_and_remove - lookup a directory or file and recursively remove it
78462306a36Sopenharmony_ci * @name: a pointer to a string containing the name of the item to look up.
78562306a36Sopenharmony_ci * @parent: a pointer to the parent dentry of the item.
78662306a36Sopenharmony_ci *
78762306a36Sopenharmony_ci * This is the equlivant of doing something like
78862306a36Sopenharmony_ci * debugfs_remove(debugfs_lookup(..)) but with the proper reference counting
78962306a36Sopenharmony_ci * handled for the directory being looked up.
79062306a36Sopenharmony_ci */
79162306a36Sopenharmony_civoid debugfs_lookup_and_remove(const char *name, struct dentry *parent)
79262306a36Sopenharmony_ci{
79362306a36Sopenharmony_ci	struct dentry *dentry;
79462306a36Sopenharmony_ci
79562306a36Sopenharmony_ci	dentry = debugfs_lookup(name, parent);
79662306a36Sopenharmony_ci	if (!dentry)
79762306a36Sopenharmony_ci		return;
79862306a36Sopenharmony_ci
79962306a36Sopenharmony_ci	debugfs_remove(dentry);
80062306a36Sopenharmony_ci	dput(dentry);
80162306a36Sopenharmony_ci}
80262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(debugfs_lookup_and_remove);
80362306a36Sopenharmony_ci
80462306a36Sopenharmony_ci/**
80562306a36Sopenharmony_ci * debugfs_rename - rename a file/directory in the debugfs filesystem
80662306a36Sopenharmony_ci * @old_dir: a pointer to the parent dentry for the renamed object. This
80762306a36Sopenharmony_ci *          should be a directory dentry.
80862306a36Sopenharmony_ci * @old_dentry: dentry of an object to be renamed.
80962306a36Sopenharmony_ci * @new_dir: a pointer to the parent dentry where the object should be
81062306a36Sopenharmony_ci *          moved. This should be a directory dentry.
81162306a36Sopenharmony_ci * @new_name: a pointer to a string containing the target name.
81262306a36Sopenharmony_ci *
81362306a36Sopenharmony_ci * This function renames a file/directory in debugfs.  The target must not
81462306a36Sopenharmony_ci * exist for rename to succeed.
81562306a36Sopenharmony_ci *
81662306a36Sopenharmony_ci * This function will return a pointer to old_dentry (which is updated to
81762306a36Sopenharmony_ci * reflect renaming) if it succeeds. If an error occurs, ERR_PTR(-ERROR)
81862306a36Sopenharmony_ci * will be returned.
81962306a36Sopenharmony_ci *
82062306a36Sopenharmony_ci * If debugfs is not enabled in the kernel, the value -%ENODEV will be
82162306a36Sopenharmony_ci * returned.
82262306a36Sopenharmony_ci */
82362306a36Sopenharmony_cistruct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
82462306a36Sopenharmony_ci		struct dentry *new_dir, const char *new_name)
82562306a36Sopenharmony_ci{
82662306a36Sopenharmony_ci	int error;
82762306a36Sopenharmony_ci	struct dentry *dentry = NULL, *trap;
82862306a36Sopenharmony_ci	struct name_snapshot old_name;
82962306a36Sopenharmony_ci
83062306a36Sopenharmony_ci	if (IS_ERR(old_dir))
83162306a36Sopenharmony_ci		return old_dir;
83262306a36Sopenharmony_ci	if (IS_ERR(new_dir))
83362306a36Sopenharmony_ci		return new_dir;
83462306a36Sopenharmony_ci	if (IS_ERR_OR_NULL(old_dentry))
83562306a36Sopenharmony_ci		return old_dentry;
83662306a36Sopenharmony_ci
83762306a36Sopenharmony_ci	trap = lock_rename(new_dir, old_dir);
83862306a36Sopenharmony_ci	/* Source or destination directories don't exist? */
83962306a36Sopenharmony_ci	if (d_really_is_negative(old_dir) || d_really_is_negative(new_dir))
84062306a36Sopenharmony_ci		goto exit;
84162306a36Sopenharmony_ci	/* Source does not exist, cyclic rename, or mountpoint? */
84262306a36Sopenharmony_ci	if (d_really_is_negative(old_dentry) || old_dentry == trap ||
84362306a36Sopenharmony_ci	    d_mountpoint(old_dentry))
84462306a36Sopenharmony_ci		goto exit;
84562306a36Sopenharmony_ci	dentry = lookup_one_len(new_name, new_dir, strlen(new_name));
84662306a36Sopenharmony_ci	/* Lookup failed, cyclic rename or target exists? */
84762306a36Sopenharmony_ci	if (IS_ERR(dentry) || dentry == trap || d_really_is_positive(dentry))
84862306a36Sopenharmony_ci		goto exit;
84962306a36Sopenharmony_ci
85062306a36Sopenharmony_ci	take_dentry_name_snapshot(&old_name, old_dentry);
85162306a36Sopenharmony_ci
85262306a36Sopenharmony_ci	error = simple_rename(&nop_mnt_idmap, d_inode(old_dir), old_dentry,
85362306a36Sopenharmony_ci			      d_inode(new_dir), dentry, 0);
85462306a36Sopenharmony_ci	if (error) {
85562306a36Sopenharmony_ci		release_dentry_name_snapshot(&old_name);
85662306a36Sopenharmony_ci		goto exit;
85762306a36Sopenharmony_ci	}
85862306a36Sopenharmony_ci	d_move(old_dentry, dentry);
85962306a36Sopenharmony_ci	fsnotify_move(d_inode(old_dir), d_inode(new_dir), &old_name.name,
86062306a36Sopenharmony_ci		d_is_dir(old_dentry),
86162306a36Sopenharmony_ci		NULL, old_dentry);
86262306a36Sopenharmony_ci	release_dentry_name_snapshot(&old_name);
86362306a36Sopenharmony_ci	unlock_rename(new_dir, old_dir);
86462306a36Sopenharmony_ci	dput(dentry);
86562306a36Sopenharmony_ci	return old_dentry;
86662306a36Sopenharmony_ciexit:
86762306a36Sopenharmony_ci	if (dentry && !IS_ERR(dentry))
86862306a36Sopenharmony_ci		dput(dentry);
86962306a36Sopenharmony_ci	unlock_rename(new_dir, old_dir);
87062306a36Sopenharmony_ci	if (IS_ERR(dentry))
87162306a36Sopenharmony_ci		return dentry;
87262306a36Sopenharmony_ci	return ERR_PTR(-EINVAL);
87362306a36Sopenharmony_ci}
87462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(debugfs_rename);
87562306a36Sopenharmony_ci
87662306a36Sopenharmony_ci/**
87762306a36Sopenharmony_ci * debugfs_initialized - Tells whether debugfs has been registered
87862306a36Sopenharmony_ci */
87962306a36Sopenharmony_cibool debugfs_initialized(void)
88062306a36Sopenharmony_ci{
88162306a36Sopenharmony_ci	return debugfs_registered;
88262306a36Sopenharmony_ci}
88362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(debugfs_initialized);
88462306a36Sopenharmony_ci
88562306a36Sopenharmony_cistatic int __init debugfs_kernel(char *str)
88662306a36Sopenharmony_ci{
88762306a36Sopenharmony_ci	if (str) {
88862306a36Sopenharmony_ci		if (!strcmp(str, "on"))
88962306a36Sopenharmony_ci			debugfs_allow = DEBUGFS_ALLOW_API | DEBUGFS_ALLOW_MOUNT;
89062306a36Sopenharmony_ci		else if (!strcmp(str, "no-mount"))
89162306a36Sopenharmony_ci			debugfs_allow = DEBUGFS_ALLOW_API;
89262306a36Sopenharmony_ci		else if (!strcmp(str, "off"))
89362306a36Sopenharmony_ci			debugfs_allow = 0;
89462306a36Sopenharmony_ci	}
89562306a36Sopenharmony_ci
89662306a36Sopenharmony_ci	return 0;
89762306a36Sopenharmony_ci}
89862306a36Sopenharmony_ciearly_param("debugfs", debugfs_kernel);
89962306a36Sopenharmony_cistatic int __init debugfs_init(void)
90062306a36Sopenharmony_ci{
90162306a36Sopenharmony_ci	int retval;
90262306a36Sopenharmony_ci
90362306a36Sopenharmony_ci	if (!(debugfs_allow & DEBUGFS_ALLOW_MOUNT))
90462306a36Sopenharmony_ci		return -EPERM;
90562306a36Sopenharmony_ci
90662306a36Sopenharmony_ci	retval = sysfs_create_mount_point(kernel_kobj, "debug");
90762306a36Sopenharmony_ci	if (retval)
90862306a36Sopenharmony_ci		return retval;
90962306a36Sopenharmony_ci
91062306a36Sopenharmony_ci	retval = register_filesystem(&debug_fs_type);
91162306a36Sopenharmony_ci	if (retval)
91262306a36Sopenharmony_ci		sysfs_remove_mount_point(kernel_kobj, "debug");
91362306a36Sopenharmony_ci	else
91462306a36Sopenharmony_ci		debugfs_registered = true;
91562306a36Sopenharmony_ci
91662306a36Sopenharmony_ci	return retval;
91762306a36Sopenharmony_ci}
91862306a36Sopenharmony_cicore_initcall(debugfs_init);
919