Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 86f0e067 authored by Christian Lamparter's avatar Christian Lamparter Committed by Greg Kroah-Hartman
Browse files

debugfs: introduce a public file_operations accessor



This patch introduces an accessor which can be used
by the users of debugfs (drivers, fs, ...) to get the
original file_operations struct. It also removes the
REAL_FOPS_DEREF macro in file.c and converts the code
to use the public version.

Previously, REAL_FOPS_DEREF was only available within
the file.c of debugfs. But having a public getter
available for debugfs users is important as some
drivers (carl9170 and b43) use the pointer of the
original file_operations in conjunction with container_of()
within their debugfs implementations.

Reviewed-by: default avatarNicolai Stange <nicstange@gmail.com>
Signed-off-by: default avatarChristian Lamparter <chunkeey@gmail.com>
Cc: stable <stable@vger.kernel.org> # 4.7+
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 2f5bb02f
Loading
Loading
Loading
Loading
+5 −8
Original line number Diff line number Diff line
@@ -97,9 +97,6 @@ EXPORT_SYMBOL_GPL(debugfs_use_file_finish);

#define F_DENTRY(filp) ((filp)->f_path.dentry)

#define REAL_FOPS_DEREF(dentry)					\
	((const struct file_operations *)(dentry)->d_fsdata)

static int open_proxy_open(struct inode *inode, struct file *filp)
{
	const struct dentry *dentry = F_DENTRY(filp);
@@ -112,7 +109,7 @@ static int open_proxy_open(struct inode *inode, struct file *filp)
		goto out;
	}

	real_fops = REAL_FOPS_DEREF(dentry);
	real_fops = debugfs_real_fops(filp);
	real_fops = fops_get(real_fops);
	if (!real_fops) {
		/* Huh? Module did not clean up after itself at exit? */
@@ -143,7 +140,7 @@ static ret_type full_proxy_ ## name(proto) \
{									\
	const struct dentry *dentry = F_DENTRY(filp);			\
	const struct file_operations *real_fops =			\
		REAL_FOPS_DEREF(dentry);				\
		debugfs_real_fops(filp);				\
	int srcu_idx;							\
	ret_type r;							\
									\
@@ -176,7 +173,7 @@ static unsigned int full_proxy_poll(struct file *filp,
				struct poll_table_struct *wait)
{
	const struct dentry *dentry = F_DENTRY(filp);
	const struct file_operations *real_fops = REAL_FOPS_DEREF(dentry);
	const struct file_operations *real_fops = debugfs_real_fops(filp);
	int srcu_idx;
	unsigned int r = 0;

@@ -193,7 +190,7 @@ static unsigned int full_proxy_poll(struct file *filp,
static int full_proxy_release(struct inode *inode, struct file *filp)
{
	const struct dentry *dentry = F_DENTRY(filp);
	const struct file_operations *real_fops = REAL_FOPS_DEREF(dentry);
	const struct file_operations *real_fops = debugfs_real_fops(filp);
	const struct file_operations *proxy_fops = filp->f_op;
	int r = 0;

@@ -241,7 +238,7 @@ static int full_proxy_open(struct inode *inode, struct file *filp)
		goto out;
	}

	real_fops = REAL_FOPS_DEREF(dentry);
	real_fops = debugfs_real_fops(filp);
	real_fops = fops_get(real_fops);
	if (!real_fops) {
		/* Huh? Module did not cleanup after itself at exit? */
+17 −0
Original line number Diff line number Diff line
@@ -45,6 +45,23 @@ extern struct dentry *arch_debugfs_dir;

extern struct srcu_struct debugfs_srcu;

/**
 * debugfs_real_fops - getter for the real file operation
 * @filp: a pointer to a struct file
 *
 * Must only be called under the protection established by
 * debugfs_use_file_start().
 */
static inline const struct file_operations *debugfs_real_fops(struct file *filp)
	__must_hold(&debugfs_srcu)
{
	/*
	 * Neither the pointer to the struct file_operations, nor its
	 * contents ever change -- srcu_dereference() is not needed here.
	 */
	return filp->f_path.dentry->d_fsdata;
}

#if defined(CONFIG_DEBUG_FS)

struct dentry *debugfs_create_file(const char *name, umode_t mode,