Skip to content

Commit

Permalink
debugfs: introduce a public file_operations accessor
Browse files Browse the repository at this point in the history
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: Nicolai Stange <nicstange@gmail.com>
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
Cc: stable <stable@vger.kernel.org> # 4.7+
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
chunkeey authored and gregkh committed Sep 21, 2016
1 parent 2f5bb02 commit 86f0e06
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 8 deletions.
13 changes: 5 additions & 8 deletions fs/debugfs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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? */
Expand Down Expand Up @@ -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; \
\
Expand Down Expand Up @@ -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;

Expand All @@ -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;

Expand Down Expand Up @@ -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? */
Expand Down
17 changes: 17 additions & 0 deletions include/linux/debugfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 86f0e06

Please sign in to comment.