* [PATCHES][RFC][CFT] debugfs cleanups
@ 2024-12-29 8:09 Al Viro
2024-12-29 8:12 ` [PATCH 01/20] debugfs: fix missing mutex_destroy() in short_fops case Al Viro
` (2 more replies)
0 siblings, 3 replies; 53+ messages in thread
From: Al Viro @ 2024-12-29 8:09 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
Debugfs has several unpleasant problems, all with the same root
cause - use of bare struct inode. Most of the filesystems embed struct
inode into fs-specific objects used to store whatever extra state is
needed for that filesystem. struct inode itself has one opaque pointer
(->i_private), and for simple cases that's enough; unfortunately,
debugfs case is not that simple.
A debugfs file needs to carry at least the following:
* which driver-supplied callbacks should be used by read/write/etc.
* which driver-supplied object should they act upon, if driver has
several objects of the same kind (a very common situation)
What's more, since driver may remove the underlying object, we
need some exclusion between the methods and removal; that is to say, for
anything opened we need to keep track of the number of threads currently
in driver-supplied callbacks and we need some way for removal to make
sure that no further callbacks will be attempted and to wait for the
one in progress to finish.
Worse yet, if we have several similar files for access to
different fields of the same driver's object, we need either a separate
set of callbacks for each field, or some way for a callback to tell
which field it's being used for.
Result is kludges galore. The pointer to driver's object is
stored in inode->i_private. The pointer to use-tracking state (struct
debugfs_fsdata) is stored in dentry->d_fsdata... and we have run out
of opaque fields.
The pointer to driver-supplied callback table has nowhere to go -
we can't store it in ->i_fop (that points to debugfs wrappers that would
handle use counts and call the real driver-supplied callbacks). OK, that
can be kludged around - we allocate debugfs_fsdata on the first use,
and we can keep that pointer in it afterwards. So we have it stashed
into ->d_fsdata until that point and move it over into debugfs_fsdata
afterwards. Since pointers are aligned, we can use the lowest bit to
tell one from another.
That has grown even nastier when an option to use a trimmed-down
variant of method table had been added (for most of those files we only
need read/write/lseek). Now we have 3 states - ->d_fsdata pointing to
struct debugfs_fsdata, ->d_fsdata used to stash a pointer to full struct
file_operations and ->d_fsdata used to stash a pointer to trimmed-down
variant. Not to worry - all those pointers are at least 32bit-aligned,
so we can use the lower couple of bits to tell one state from another
(00, 01 and 11 resp.)
It's still not the end, though - some drivers have fuckloads of
files for each underlying object, and while debugfs has an unsanitary
degree of fondness for templates, apparently there are some limits.
That gets kludged over in two fairly disgusting ways. For one thing,
we already store a reference to driver-supplied file_operations, so
we can always have several (dozens of) identical copies of that thing
and have callback ask debugfs to give it the pointer. Voila - we can
tell whether we are trying to read driver_object->plonk or driver_object->puke
by checking which copy does that point to. Another kludge is to look
at dentry name - compare it with a bunch of strings until we find the
one we want.
All of that could be avoided if we augmented debugfs inodes with
a couple of pointers - no more stashing crap in ->d_fsdata, etc.
And it's really not hard to do. The series below attempts to untangle
that mess; it can be found in
git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs.git #work.debugfs
It's very lightly tested; review and more testing would be
very welcome.
Shortlog:
Al Viro (20):
debugfs: fix missing mutex_destroy() in short_fops case
debugfs: separate cache for debugfs inodes
debugfs: move ->automount into debugfs_inode_info
debugfs: get rid of dynamically allocation proxy_ops
debugfs: don't mess with bits in ->d_fsdata
debugfs: allow to store an additional opaque pointer at file creation
carl9170: stop embedding file_operations into their objects
b43: stop embedding struct file_operations into their objects
b43legacy: make use of debugfs_get_aux()
netdevsim: don't embed file_operations into your structs
mediatek: stop messing with ->d_iname
[not even compile-tested] greybus/camera - stop messing with ->d_iname
mtu3: don't mess wiht ->d_iname
xhci: don't mess with ->d_iname
qat: don't mess with ->d_name
sof-client-ipc-flood-test: don't mess with ->d_name
slub: don't mess with ->d_name
arm_scmi: don't mess with ->d_parent->d_name
octeontx2: don't mess with ->d_parent or ->d_parent->d_name
saner replacement for debugfs_rename()
Diffstat:
Documentation/filesystems/debugfs.rst | 12 +-
.../crypto/intel/qat/qat_common/adf_tl_debugfs.c | 36 +---
drivers/firmware/arm_scmi/raw_mode.c | 12 +-
drivers/net/bonding/bond_debugfs.c | 9 +-
drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c | 19 +-
.../ethernet/marvell/octeontx2/af/rvu_debugfs.c | 76 +++-----
drivers/net/ethernet/marvell/skge.c | 5 +-
drivers/net/ethernet/marvell/sky2.c | 5 +-
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 6 +-
drivers/net/netdevsim/hwstats.c | 29 ++-
drivers/net/wireless/ath/carl9170/debug.c | 28 ++-
drivers/net/wireless/broadcom/b43/debugfs.c | 27 ++-
drivers/net/wireless/broadcom/b43legacy/debugfs.c | 26 ++-
drivers/opp/debugfs.c | 10 +-
drivers/phy/mediatek/phy-mtk-tphy.c | 40 +---
drivers/staging/greybus/camera.c | 17 +-
drivers/usb/host/xhci-debugfs.c | 25 +--
drivers/usb/mtu3/mtu3_debugfs.c | 40 +---
fs/debugfs/file.c | 167 ++++++++--------
fs/debugfs/inode.c | 213 ++++++++++-----------
fs/debugfs/internal.h | 55 +++---
include/linux/debugfs.h | 34 +++-
mm/shrinker_debug.c | 16 +-
mm/slub.c | 13 +-
net/hsr/hsr_debugfs.c | 9 +-
net/mac80211/debugfs_netdev.c | 11 +-
net/wireless/core.c | 5 +-
sound/soc/sof/sof-client-ipc-flood-test.c | 39 ++--
28 files changed, 399 insertions(+), 585 deletions(-)
Patches' overview:
01/20) debugfs: fix missing mutex_destroy() in short_fops case
-stable fodder, in one place the logics for "what does ->d_fsdata
contain for this one" got confused.
Meat of the series:
02/20) debugfs: separate cache for debugfs inodes
Embed them into container (struct debugfs_inode_info, with nothing
else in it at the moment), set the cache up, etc.
Just the infrastructure changes letting us augment debugfs inodes
here; adding stuff will come at the next step.
03/20) debugfs: move ->automount into debugfs_inode_info
... and don't bother with debugfs_fsdata for those. Life's
simpler that way...
04/20) debugfs: get rid of dynamically allocation proxy_ops
All it takes is having full_proxy_open() collect the information
about available methods and store it in debugfs_fsdata.
Wrappers are called only after full_proxy_open() has succeeded
calling debugfs_get_file(), so they are guaranteed to have ->d_fsdata
already pointing to debugfs_fsdata.
As the result, they can check if method is absent and bugger off
early, without any atomic operations, etc. - same effect as what we'd
have from NULL method. Which makes the entire proxy_fops contents
unconditional, making it completely pointless - we can just put those
methods (unconditionally) into debugfs_full_proxy_file_operations and
forget about dynamic allocation, replace_fops, etc.
05/20) debugfs: don't mess with bits in ->d_fsdata
The reason we need that crap is the dual use ->d_fsdata has there -
it's both holding a debugfs_fsdata reference after the first
debugfs_file_get() (actually, after the call of proxy ->open())
*and* it serves as a place to stash a reference to real file_operations
from object creation to the first open. Oh, and it's triple use,
actually - that stashed reference might be to debugfs_short_fops.
Bugger that for a game of solidiers - just put the operations
reference into debugfs-private augmentation of inode. And split
debugfs_full_file_operations into full and short cases, so that
debugfs_get_file() could tell one from another.
Voila - ->d_fsdata holds NULL until the first (successful)
debugfs_get_file() and a reference to struct debugfs_fsdata afterwards.
06/20) debugfs: allow to store an additional opaque pointer at file creation
Set by debugfs_create_file_aux(name, mode, parent, data, aux, fops).
Plain debugfs_create_file() has it set to NULL.
Accessed by debugfs_get_aux(file).
Convenience macros for numeric opaque data - debugfs_create_file_aux_num
and debugfs_get_aux_num, resp.
Now we can trim the crap from drivers:
A bunch "let's make a bunch of identical copies of struct file_operations
and use debugfs_real_fops() to tell which field are we asked to operate upon":
07/20) carl9170: stop embedding file_operations into their objects
08/20) b43: stop embedding struct file_operations into their objects
09/20) b43legacy: make use of debugfs_get_aux()
10/20) netdevsim: don't embed file_operations into your structs
BTW, that crack about several dozens? Literal truth - carl9170 has forty
three such identical copies. Hidden by creative uses of preprocessor...
A bunch of "let's play with dentry name" case:
11/20) mediatek: stop messing with ->d_iname
12/20) [not even compile-tested] greybus/camera - stop messing with ->d_iname
depends on BROKEN, so...
13/20) mtu3: don't mess wiht ->d_iname
14/20) xhci: don't mess with ->d_iname
15/20) qat: don't mess with ->d_name
16/20) sof-client-ipc-flood-test: don't mess with ->d_name
17/20) slub: don't mess with ->d_name
Even nastier - these look at the name of parent directory instead.
18/20) arm_scmi: don't mess with ->d_parent->d_name
19/20) octeontx2: don't mess with ->d_parent or ->d_parent->d_name
The last commit is pretty much independent from the rest of series:
20/20) saner replacement for debugfs_rename()
Existing primitive has several problems:
1) calling conventions are clumsy - it returns a dentry reference
that is either identical to its second argument or is an ERR_PTR(-E...);
in both cases no refcount changes happen. Inconvenient for users and
bug-prone; it would be better to have it return 0 on success and -E... on
failure.
2) it allows cross-directory moves; however, no such caller have
ever materialized and considering the way debugfs is used, it's unlikely
to happen in the future. What's more, any such caller would have fun
issues to deal with wrt interplay with recursive removal. It also makes
the calling conventions clumsier...
3) tautological rename fails; the callers have no race-free way
to deal with that.
4) new name must have been formed by the caller; quite a few
callers have it done by sprintf/kasprintf/etc., ending up with considerable
boilerplate.
Proposed replacement: int debugfs_change_name(dentry, fmt, ...).
All callers convert to that easily, and it's simpler internally.
IMO debugfs_rename() should go; if we ever get a real-world use
case for cross-directory moves in debugfs, we can always look into
the right way to handle that.
^ permalink raw reply [flat|nested] 53+ messages in thread
* [PATCH 01/20] debugfs: fix missing mutex_destroy() in short_fops case
2024-12-29 8:09 [PATCHES][RFC][CFT] debugfs cleanups Al Viro
@ 2024-12-29 8:12 ` Al Viro
2024-12-29 8:12 ` [PATCH 02/20] debugfs: separate cache for debugfs inodes Al Viro
` (19 more replies)
2024-12-29 20:58 ` [PATCHES][RFC][CFT] debugfs cleanups Al Viro
2025-01-12 8:05 ` [PATCHES v2][RFC][CFT] " Al Viro
2 siblings, 20 replies; 53+ messages in thread
From: Al Viro @ 2024-12-29 8:12 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
we need that in ->real_fops == NULL, ->short_fops != NULL case
Fixes: 8dc6d81c6b2a "debugfs: add small file operations for most files"
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/debugfs/inode.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index 38a9c7eb97e6..c99a0599c811 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -229,7 +229,7 @@ static void debugfs_release_dentry(struct dentry *dentry)
return;
/* check it wasn't a dir (no fsdata) or automount (no real_fops) */
- if (fsd && fsd->real_fops) {
+ if (fsd && (fsd->real_fops || fsd->short_fops)) {
WARN_ON(!list_empty(&fsd->cancellations));
mutex_destroy(&fsd->cancellations_mtx);
}
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH 02/20] debugfs: separate cache for debugfs inodes
2024-12-29 8:12 ` [PATCH 01/20] debugfs: fix missing mutex_destroy() in short_fops case Al Viro
@ 2024-12-29 8:12 ` Al Viro
2024-12-29 8:12 ` [PATCH 03/20] debugfs: move ->automount into debugfs_inode_info Al Viro
` (18 subsequent siblings)
19 siblings, 0 replies; 53+ messages in thread
From: Al Viro @ 2024-12-29 8:12 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
Embed them into container (struct debugfs_inode_info, with nothing
else in it at the moment), set the cache up, etc.
Just the infrastructure changes letting us augment debugfs inodes
here; adding stuff will come at the next step.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/debugfs/inode.c | 40 ++++++++++++++++++++++++++++++++++------
fs/debugfs/internal.h | 9 +++++++++
2 files changed, 43 insertions(+), 6 deletions(-)
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index c99a0599c811..6194c1cd87b9 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -208,16 +208,34 @@ static int debugfs_show_options(struct seq_file *m, struct dentry *root)
return 0;
}
+static struct kmem_cache *debugfs_inode_cachep __ro_after_init;
+
+static void init_once(void *foo)
+{
+ struct debugfs_inode_info *info = foo;
+ inode_init_once(&info->vfs_inode);
+}
+
+static struct inode *debugfs_alloc_inode(struct super_block *sb)
+{
+ struct debugfs_inode_info *info;
+ info = alloc_inode_sb(sb, debugfs_inode_cachep, GFP_KERNEL);
+ if (!info)
+ return NULL;
+ return &info->vfs_inode;
+}
+
static void debugfs_free_inode(struct inode *inode)
{
if (S_ISLNK(inode->i_mode))
kfree(inode->i_link);
- free_inode_nonrcu(inode);
+ kmem_cache_free(debugfs_inode_cachep, DEBUGFS_I(inode));
}
static const struct super_operations debugfs_super_operations = {
.statfs = simple_statfs,
.show_options = debugfs_show_options,
+ .alloc_inode = debugfs_alloc_inode,
.free_inode = debugfs_free_inode,
};
@@ -942,12 +960,22 @@ static int __init debugfs_init(void)
if (retval)
return retval;
- retval = register_filesystem(&debug_fs_type);
- if (retval)
+ debugfs_inode_cachep = kmem_cache_create("debugfs_inode_cache",
+ sizeof(struct debugfs_inode_info), 0,
+ SLAB_RECLAIM_ACCOUNT | SLAB_ACCOUNT,
+ init_once);
+ if (debugfs_inode_cachep == NULL) {
sysfs_remove_mount_point(kernel_kobj, "debug");
- else
- debugfs_registered = true;
+ return -ENOMEM;
+ }
- return retval;
+ retval = register_filesystem(&debug_fs_type);
+ if (retval) { // Really not going to happen
+ sysfs_remove_mount_point(kernel_kobj, "debug");
+ kmem_cache_destroy(debugfs_inode_cachep);
+ return retval;
+ }
+ debugfs_registered = true;
+ return 0;
}
core_initcall(debugfs_init);
diff --git a/fs/debugfs/internal.h b/fs/debugfs/internal.h
index a3edfa4f0d8e..0926d865cd81 100644
--- a/fs/debugfs/internal.h
+++ b/fs/debugfs/internal.h
@@ -11,6 +11,15 @@
struct file_operations;
+struct debugfs_inode_info {
+ struct inode vfs_inode;
+};
+
+static inline struct debugfs_inode_info *DEBUGFS_I(struct inode *inode)
+{
+ return container_of(inode, struct debugfs_inode_info, vfs_inode);
+}
+
/* declared over in file.c */
extern const struct file_operations debugfs_noop_file_operations;
extern const struct file_operations debugfs_open_proxy_file_operations;
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH 03/20] debugfs: move ->automount into debugfs_inode_info
2024-12-29 8:12 ` [PATCH 01/20] debugfs: fix missing mutex_destroy() in short_fops case Al Viro
2024-12-29 8:12 ` [PATCH 02/20] debugfs: separate cache for debugfs inodes Al Viro
@ 2024-12-29 8:12 ` Al Viro
2024-12-29 8:12 ` [PATCH 04/20] debugfs: get rid of dynamically allocation proxy_ops Al Viro
` (17 subsequent siblings)
19 siblings, 0 replies; 53+ messages in thread
From: Al Viro @ 2024-12-29 8:12 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
... and don't bother with debugfs_fsdata for those. Life's
simpler that way...
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/debugfs/inode.c | 21 +++++----------------
fs/debugfs/internal.h | 19 +++++++++----------
2 files changed, 14 insertions(+), 26 deletions(-)
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index 6194c1cd87b9..82155dc0bff3 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -246,8 +246,8 @@ static void debugfs_release_dentry(struct dentry *dentry)
if ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)
return;
- /* check it wasn't a dir (no fsdata) or automount (no real_fops) */
- if (fsd && (fsd->real_fops || fsd->short_fops)) {
+ /* check it wasn't a dir or automount (no fsdata) */
+ if (fsd) {
WARN_ON(!list_empty(&fsd->cancellations));
mutex_destroy(&fsd->cancellations_mtx);
}
@@ -257,9 +257,9 @@ static void debugfs_release_dentry(struct dentry *dentry)
static struct vfsmount *debugfs_automount(struct path *path)
{
- struct debugfs_fsdata *fsd = path->dentry->d_fsdata;
+ struct inode *inode = path->dentry->d_inode;
- return fsd->automount(path->dentry, d_inode(path->dentry)->i_private);
+ return DEBUGFS_I(inode)->automount(path->dentry, inode->i_private);
}
static const struct dentry_operations debugfs_dops = {
@@ -645,23 +645,13 @@ struct dentry *debugfs_create_automount(const char *name,
void *data)
{
struct dentry *dentry = start_creating(name, parent);
- struct debugfs_fsdata *fsd;
struct inode *inode;
if (IS_ERR(dentry))
return dentry;
- fsd = kzalloc(sizeof(*fsd), GFP_KERNEL);
- if (!fsd) {
- failed_creating(dentry);
- return ERR_PTR(-ENOMEM);
- }
-
- fsd->automount = f;
-
if (!(debugfs_allow & DEBUGFS_ALLOW_API)) {
failed_creating(dentry);
- kfree(fsd);
return ERR_PTR(-EPERM);
}
@@ -669,14 +659,13 @@ struct dentry *debugfs_create_automount(const char *name,
if (unlikely(!inode)) {
pr_err("out of free dentries, can not create automount '%s'\n",
name);
- kfree(fsd);
return failed_creating(dentry);
}
make_empty_dir_inode(inode);
inode->i_flags |= S_AUTOMOUNT;
inode->i_private = data;
- dentry->d_fsdata = fsd;
+ DEBUGFS_I(inode)->automount = f;
/* directory inodes start off with i_nlink == 2 (for "." entry) */
inc_nlink(inode);
d_instantiate(dentry, inode);
diff --git a/fs/debugfs/internal.h b/fs/debugfs/internal.h
index 0926d865cd81..a0d9eb3fa67d 100644
--- a/fs/debugfs/internal.h
+++ b/fs/debugfs/internal.h
@@ -13,6 +13,9 @@ struct file_operations;
struct debugfs_inode_info {
struct inode vfs_inode;
+ union {
+ debugfs_automount_t automount;
+ };
};
static inline struct debugfs_inode_info *DEBUGFS_I(struct inode *inode)
@@ -28,17 +31,13 @@ extern const struct file_operations debugfs_full_proxy_file_operations;
struct debugfs_fsdata {
const struct file_operations *real_fops;
const struct debugfs_short_fops *short_fops;
- union {
- /* automount_fn is used when real_fops is NULL */
- debugfs_automount_t automount;
- struct {
- refcount_t active_users;
- struct completion active_users_drained;
+ struct {
+ refcount_t active_users;
+ struct completion active_users_drained;
- /* protect cancellations */
- struct mutex cancellations_mtx;
- struct list_head cancellations;
- };
+ /* protect cancellations */
+ struct mutex cancellations_mtx;
+ struct list_head cancellations;
};
};
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH 04/20] debugfs: get rid of dynamically allocation proxy_ops
2024-12-29 8:12 ` [PATCH 01/20] debugfs: fix missing mutex_destroy() in short_fops case Al Viro
2024-12-29 8:12 ` [PATCH 02/20] debugfs: separate cache for debugfs inodes Al Viro
2024-12-29 8:12 ` [PATCH 03/20] debugfs: move ->automount into debugfs_inode_info Al Viro
@ 2024-12-29 8:12 ` Al Viro
2024-12-29 8:12 ` [PATCH 05/20] debugfs: don't mess with bits in ->d_fsdata Al Viro
` (16 subsequent siblings)
19 siblings, 0 replies; 53+ messages in thread
From: Al Viro @ 2024-12-29 8:12 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
All it takes is having full_proxy_open() collect the information
about available methods and store it in debugfs_fsdata.
Wrappers are called only after full_proxy_open() has succeeded
calling debugfs_get_file(), so they are guaranteed to have
->d_fsdata already pointing to debugfs_fsdata.
As the result, they can check if method is absent and bugger off
early, without any atomic operations, etc. - same effect as what
we'd have from NULL method. Which makes the entire proxy_fops
contents unconditional, making it completely pointless - we can
just put those methods (unconditionally) into
debugfs_full_proxy_file_operations and forget about dynamic
allocation, replace_fops, etc.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/debugfs/file.c | 114 +++++++++++++++++++-----------------------
fs/debugfs/internal.h | 9 ++++
2 files changed, 60 insertions(+), 63 deletions(-)
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index 47dc96dfe386..71e359f5f587 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -96,19 +96,37 @@ int debugfs_file_get(struct dentry *dentry)
if (!((unsigned long)d_fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)) {
fsd = d_fsd;
} else {
- fsd = kmalloc(sizeof(*fsd), GFP_KERNEL);
+ fsd = kzalloc(sizeof(*fsd), GFP_KERNEL);
if (!fsd)
return -ENOMEM;
if ((unsigned long)d_fsd & DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT) {
- fsd->real_fops = NULL;
- fsd->short_fops = (void *)((unsigned long)d_fsd &
- ~(DEBUGFS_FSDATA_IS_REAL_FOPS_BIT |
- DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT));
+ const struct debugfs_short_fops *ops;
+ ops = (void *)((unsigned long)d_fsd &
+ ~(DEBUGFS_FSDATA_IS_REAL_FOPS_BIT |
+ DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT));
+ fsd->short_fops = ops;
+ if (ops->llseek)
+ fsd->methods |= HAS_LSEEK;
+ if (ops->read)
+ fsd->methods |= HAS_READ;
+ if (ops->write)
+ fsd->methods |= HAS_WRITE;
} else {
- fsd->real_fops = (void *)((unsigned long)d_fsd &
- ~DEBUGFS_FSDATA_IS_REAL_FOPS_BIT);
- fsd->short_fops = NULL;
+ const struct file_operations *ops;
+ ops = (void *)((unsigned long)d_fsd &
+ ~DEBUGFS_FSDATA_IS_REAL_FOPS_BIT);
+ fsd->real_fops = ops;
+ if (ops->llseek)
+ fsd->methods |= HAS_LSEEK;
+ if (ops->read)
+ fsd->methods |= HAS_READ;
+ if (ops->write)
+ fsd->methods |= HAS_WRITE;
+ if (ops->unlocked_ioctl)
+ fsd->methods |= HAS_IOCTL;
+ if (ops->poll)
+ fsd->methods |= HAS_POLL;
}
refcount_set(&fsd->active_users, 1);
init_completion(&fsd->active_users_drained);
@@ -309,13 +327,16 @@ const struct file_operations debugfs_open_proxy_file_operations = {
#define PROTO(args...) args
#define ARGS(args...) args
-#define FULL_PROXY_FUNC(name, ret_type, filp, proto, args) \
+#define FULL_PROXY_FUNC(name, ret_type, filp, proto, args, bit, ret) \
static ret_type full_proxy_ ## name(proto) \
{ \
- struct dentry *dentry = F_DENTRY(filp); \
+ struct dentry *dentry = F_DENTRY(filp); \
+ struct debugfs_fsdata *fsd = dentry->d_fsdata; \
const struct file_operations *real_fops; \
ret_type r; \
\
+ if (!(fsd->methods & bit)) \
+ return ret; \
r = debugfs_file_get(dentry); \
if (unlikely(r)) \
return r; \
@@ -325,17 +346,18 @@ static ret_type full_proxy_ ## name(proto) \
return r; \
}
-#define FULL_PROXY_FUNC_BOTH(name, ret_type, filp, proto, args) \
+#define FULL_PROXY_FUNC_BOTH(name, ret_type, filp, proto, args, bit, ret) \
static ret_type full_proxy_ ## name(proto) \
{ \
struct dentry *dentry = F_DENTRY(filp); \
- struct debugfs_fsdata *fsd; \
+ struct debugfs_fsdata *fsd = dentry->d_fsdata; \
ret_type r; \
\
+ if (!(fsd->methods & bit)) \
+ return ret; \
r = debugfs_file_get(dentry); \
if (unlikely(r)) \
return r; \
- fsd = dentry->d_fsdata; \
if (fsd->real_fops) \
r = fsd->real_fops->name(args); \
else \
@@ -346,29 +368,32 @@ static ret_type full_proxy_ ## name(proto) \
FULL_PROXY_FUNC_BOTH(llseek, loff_t, filp,
PROTO(struct file *filp, loff_t offset, int whence),
- ARGS(filp, offset, whence));
+ ARGS(filp, offset, whence), HAS_LSEEK, -ESPIPE);
FULL_PROXY_FUNC_BOTH(read, ssize_t, filp,
PROTO(struct file *filp, char __user *buf, size_t size,
loff_t *ppos),
- ARGS(filp, buf, size, ppos));
+ ARGS(filp, buf, size, ppos), HAS_READ, -EINVAL);
FULL_PROXY_FUNC_BOTH(write, ssize_t, filp,
PROTO(struct file *filp, const char __user *buf,
size_t size, loff_t *ppos),
- ARGS(filp, buf, size, ppos));
+ ARGS(filp, buf, size, ppos), HAS_WRITE, -EINVAL);
FULL_PROXY_FUNC(unlocked_ioctl, long, filp,
PROTO(struct file *filp, unsigned int cmd, unsigned long arg),
- ARGS(filp, cmd, arg));
+ ARGS(filp, cmd, arg), HAS_IOCTL, -ENOTTY);
static __poll_t full_proxy_poll(struct file *filp,
struct poll_table_struct *wait)
{
struct dentry *dentry = F_DENTRY(filp);
+ struct debugfs_fsdata *fsd = dentry->d_fsdata;
__poll_t r = 0;
const struct file_operations *real_fops;
+ if (!(fsd->methods & HAS_POLL))
+ return DEFAULT_POLLMASK;
if (debugfs_file_get(dentry))
return EPOLLHUP;
@@ -380,9 +405,7 @@ static __poll_t 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 = debugfs_real_fops(filp);
- const struct file_operations *proxy_fops = filp->f_op;
int r = 0;
/*
@@ -394,41 +417,14 @@ static int full_proxy_release(struct inode *inode, struct file *filp)
if (real_fops && real_fops->release)
r = real_fops->release(inode, filp);
- replace_fops(filp, d_inode(dentry)->i_fop);
- kfree(proxy_fops);
fops_put(real_fops);
return r;
}
-static void __full_proxy_fops_init(struct file_operations *proxy_fops,
- struct debugfs_fsdata *fsd)
-{
- proxy_fops->release = full_proxy_release;
-
- if ((fsd->real_fops && fsd->real_fops->llseek) ||
- (fsd->short_fops && fsd->short_fops->llseek))
- proxy_fops->llseek = full_proxy_llseek;
-
- if ((fsd->real_fops && fsd->real_fops->read) ||
- (fsd->short_fops && fsd->short_fops->read))
- proxy_fops->read = full_proxy_read;
-
- if ((fsd->real_fops && fsd->real_fops->write) ||
- (fsd->short_fops && fsd->short_fops->write))
- proxy_fops->write = full_proxy_write;
-
- if (fsd->real_fops && fsd->real_fops->poll)
- proxy_fops->poll = full_proxy_poll;
-
- if (fsd->real_fops && fsd->real_fops->unlocked_ioctl)
- proxy_fops->unlocked_ioctl = full_proxy_unlocked_ioctl;
-}
-
static int full_proxy_open(struct inode *inode, struct file *filp)
{
struct dentry *dentry = F_DENTRY(filp);
const struct file_operations *real_fops;
- struct file_operations *proxy_fops = NULL;
struct debugfs_fsdata *fsd;
int r;
@@ -458,34 +454,20 @@ static int full_proxy_open(struct inode *inode, struct file *filp)
goto out;
}
- proxy_fops = kzalloc(sizeof(*proxy_fops), GFP_KERNEL);
- if (!proxy_fops) {
- r = -ENOMEM;
- goto free_proxy;
- }
- __full_proxy_fops_init(proxy_fops, fsd);
- replace_fops(filp, proxy_fops);
-
if (!real_fops || real_fops->open) {
if (real_fops)
r = real_fops->open(inode, filp);
else
r = simple_open(inode, filp);
if (r) {
- replace_fops(filp, d_inode(dentry)->i_fop);
- goto free_proxy;
- } else if (filp->f_op != proxy_fops) {
+ fops_put(real_fops);
+ } else if (filp->f_op != &debugfs_full_proxy_file_operations) {
/* No protection against file removal anymore. */
WARN(1, "debugfs file owner replaced proxy fops: %pd",
dentry);
- goto free_proxy;
+ fops_put(real_fops);
}
}
-
- goto out;
-free_proxy:
- kfree(proxy_fops);
- fops_put(real_fops);
out:
debugfs_file_put(dentry);
return r;
@@ -493,6 +475,12 @@ static int full_proxy_open(struct inode *inode, struct file *filp)
const struct file_operations debugfs_full_proxy_file_operations = {
.open = full_proxy_open,
+ .release = full_proxy_release,
+ .llseek = full_proxy_llseek,
+ .read = full_proxy_read,
+ .write = full_proxy_write,
+ .poll = full_proxy_poll,
+ .unlocked_ioctl = full_proxy_unlocked_ioctl
};
ssize_t debugfs_attr_read(struct file *file, char __user *buf,
diff --git a/fs/debugfs/internal.h b/fs/debugfs/internal.h
index a0d9eb3fa67d..72f0034953b5 100644
--- a/fs/debugfs/internal.h
+++ b/fs/debugfs/internal.h
@@ -38,9 +38,18 @@ struct debugfs_fsdata {
/* protect cancellations */
struct mutex cancellations_mtx;
struct list_head cancellations;
+ unsigned int methods;
};
};
+enum {
+ HAS_READ = 1,
+ HAS_WRITE = 2,
+ HAS_LSEEK = 4,
+ HAS_POLL = 8,
+ HAS_IOCTL = 16
+};
+
/*
* A dentry's ->d_fsdata either points to the real fops or to a
* dynamically allocated debugfs_fsdata instance.
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH 05/20] debugfs: don't mess with bits in ->d_fsdata
2024-12-29 8:12 ` [PATCH 01/20] debugfs: fix missing mutex_destroy() in short_fops case Al Viro
` (2 preceding siblings ...)
2024-12-29 8:12 ` [PATCH 04/20] debugfs: get rid of dynamically allocation proxy_ops Al Viro
@ 2024-12-29 8:12 ` Al Viro
2024-12-29 8:12 ` [PATCH 06/20] debugfs: allow to store an additional opaque pointer at file creation Al Viro
` (15 subsequent siblings)
19 siblings, 0 replies; 53+ messages in thread
From: Al Viro @ 2024-12-29 8:12 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
The reason we need that crap is the dual use ->d_fsdata has there -
it's both holding a debugfs_fsdata reference after the first
debugfs_file_get() (actually, after the call of proxy ->open())
*and* it serves as a place to stash a reference to real file_operations
from object creation to the first open. Oh, and it's triple use,
actually - that stashed reference might be to debugfs_short_fops.
Bugger that for a game of solidiers - just put the operations
reference into debugfs-private augmentation of inode. And split
debugfs_full_file_operations into full and short cases, so that
debugfs_get_file() could tell one from another.
Voila - ->d_fsdata holds NULL until the first (successful) debugfs_get_file()
and a reference to struct debugfs_fsdata afterwards.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/debugfs/file.c | 61 ++++++++++++++++++++++++++-----------------
fs/debugfs/inode.c | 34 ++++++------------------
fs/debugfs/internal.h | 17 +++---------
3 files changed, 49 insertions(+), 63 deletions(-)
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index 71e359f5f587..cb65ebc1a992 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -51,7 +51,7 @@ const struct file_operations *debugfs_real_fops(const struct file *filp)
{
struct debugfs_fsdata *fsd = F_DENTRY(filp)->d_fsdata;
- if ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT) {
+ if (!fsd) {
/*
* Urgh, we've been called w/o a protecting
* debugfs_file_get().
@@ -93,19 +93,16 @@ int debugfs_file_get(struct dentry *dentry)
return -EINVAL;
d_fsd = READ_ONCE(dentry->d_fsdata);
- if (!((unsigned long)d_fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)) {
+ if (d_fsd) {
fsd = d_fsd;
} else {
+ struct inode *inode = dentry->d_inode;
fsd = kzalloc(sizeof(*fsd), GFP_KERNEL);
if (!fsd)
return -ENOMEM;
-
- if ((unsigned long)d_fsd & DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT) {
+ if (dentry->d_inode->i_fop == &debugfs_short_proxy_file_operations) {
const struct debugfs_short_fops *ops;
- ops = (void *)((unsigned long)d_fsd &
- ~(DEBUGFS_FSDATA_IS_REAL_FOPS_BIT |
- DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT));
- fsd->short_fops = ops;
+ ops = fsd->short_fops = DEBUGFS_I(inode)->short_fops;
if (ops->llseek)
fsd->methods |= HAS_LSEEK;
if (ops->read)
@@ -114,9 +111,7 @@ int debugfs_file_get(struct dentry *dentry)
fsd->methods |= HAS_WRITE;
} else {
const struct file_operations *ops;
- ops = (void *)((unsigned long)d_fsd &
- ~DEBUGFS_FSDATA_IS_REAL_FOPS_BIT);
- fsd->real_fops = ops;
+ ops = fsd->real_fops = DEBUGFS_I(inode)->real_fops;
if (ops->llseek)
fsd->methods |= HAS_LSEEK;
if (ops->read)
@@ -133,10 +128,11 @@ int debugfs_file_get(struct dentry *dentry)
INIT_LIST_HEAD(&fsd->cancellations);
mutex_init(&fsd->cancellations_mtx);
- if (cmpxchg(&dentry->d_fsdata, d_fsd, fsd) != d_fsd) {
+ d_fsd = cmpxchg(&dentry->d_fsdata, NULL, fsd);
+ if (d_fsd) {
mutex_destroy(&fsd->cancellations_mtx);
kfree(fsd);
- fsd = READ_ONCE(dentry->d_fsdata);
+ fsd = d_fsd;
}
}
@@ -213,8 +209,7 @@ void debugfs_enter_cancellation(struct file *file,
return;
fsd = READ_ONCE(dentry->d_fsdata);
- if (WARN_ON(!fsd ||
- ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)))
+ if (WARN_ON(!fsd))
return;
mutex_lock(&fsd->cancellations_mtx);
@@ -245,8 +240,7 @@ void debugfs_leave_cancellation(struct file *file,
return;
fsd = READ_ONCE(dentry->d_fsdata);
- if (WARN_ON(!fsd ||
- ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)))
+ if (WARN_ON(!fsd))
return;
mutex_lock(&fsd->cancellations_mtx);
@@ -414,7 +408,7 @@ static int full_proxy_release(struct inode *inode, struct file *filp)
* not to leak any resources. Releasers must not assume that
* ->i_private is still being meaningful here.
*/
- if (real_fops && real_fops->release)
+ if (real_fops->release)
r = real_fops->release(inode, filp);
fops_put(real_fops);
@@ -438,7 +432,7 @@ static int full_proxy_open(struct inode *inode, struct file *filp)
if (r)
goto out;
- if (real_fops && !fops_get(real_fops)) {
+ if (!fops_get(real_fops)) {
#ifdef CONFIG_MODULES
if (real_fops->owner &&
real_fops->owner->state == MODULE_STATE_GOING) {
@@ -454,11 +448,8 @@ static int full_proxy_open(struct inode *inode, struct file *filp)
goto out;
}
- if (!real_fops || real_fops->open) {
- if (real_fops)
- r = real_fops->open(inode, filp);
- else
- r = simple_open(inode, filp);
+ if (real_fops->open) {
+ r = real_fops->open(inode, filp);
if (r) {
fops_put(real_fops);
} else if (filp->f_op != &debugfs_full_proxy_file_operations) {
@@ -483,6 +474,28 @@ const struct file_operations debugfs_full_proxy_file_operations = {
.unlocked_ioctl = full_proxy_unlocked_ioctl
};
+static int short_proxy_open(struct inode *inode, struct file *filp)
+{
+ struct dentry *dentry = F_DENTRY(filp);
+ int r;
+
+ r = debugfs_file_get(dentry);
+ if (r)
+ return r == -EIO ? -ENOENT : r;
+ r = debugfs_locked_down(inode, filp, NULL);
+ if (!r)
+ r = simple_open(inode, filp);
+ debugfs_file_put(dentry);
+ return r;
+}
+
+const struct file_operations debugfs_short_proxy_file_operations = {
+ .open = short_proxy_open,
+ .llseek = full_proxy_llseek,
+ .read = full_proxy_read,
+ .write = full_proxy_write,
+};
+
ssize_t debugfs_attr_read(struct file *file, char __user *buf,
size_t len, loff_t *ppos)
{
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index 82155dc0bff3..590d77757c92 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -243,15 +243,10 @@ static void debugfs_release_dentry(struct dentry *dentry)
{
struct debugfs_fsdata *fsd = dentry->d_fsdata;
- if ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)
- return;
-
- /* check it wasn't a dir or automount (no fsdata) */
if (fsd) {
WARN_ON(!list_empty(&fsd->cancellations));
mutex_destroy(&fsd->cancellations_mtx);
}
-
kfree(fsd);
}
@@ -459,9 +454,10 @@ static struct dentry *__debugfs_create_file(const char *name, umode_t mode,
inode->i_private = data;
inode->i_op = &debugfs_file_inode_operations;
+ if (!real_fops)
+ proxy_fops = &debugfs_noop_file_operations;
inode->i_fop = proxy_fops;
- dentry->d_fsdata = (void *)((unsigned long)real_fops |
- DEBUGFS_FSDATA_IS_REAL_FOPS_BIT);
+ DEBUGFS_I(inode)->raw = real_fops;
d_instantiate(dentry, inode);
fsnotify_create(d_inode(dentry->d_parent), dentry);
@@ -472,14 +468,8 @@ struct dentry *debugfs_create_file_full(const char *name, umode_t mode,
struct dentry *parent, void *data,
const struct file_operations *fops)
{
- if (WARN_ON((unsigned long)fops &
- (DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT |
- DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)))
- return ERR_PTR(-EINVAL);
-
return __debugfs_create_file(name, mode, parent, data,
- fops ? &debugfs_full_proxy_file_operations :
- &debugfs_noop_file_operations,
+ &debugfs_full_proxy_file_operations,
fops);
}
EXPORT_SYMBOL_GPL(debugfs_create_file_full);
@@ -488,16 +478,9 @@ struct dentry *debugfs_create_file_short(const char *name, umode_t mode,
struct dentry *parent, void *data,
const struct debugfs_short_fops *fops)
{
- if (WARN_ON((unsigned long)fops &
- (DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT |
- DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)))
- return ERR_PTR(-EINVAL);
-
return __debugfs_create_file(name, mode, parent, data,
- fops ? &debugfs_full_proxy_file_operations :
- &debugfs_noop_file_operations,
- (const void *)((unsigned long)fops |
- DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT));
+ &debugfs_short_proxy_file_operations,
+ fops);
}
EXPORT_SYMBOL_GPL(debugfs_create_file_short);
@@ -534,8 +517,7 @@ struct dentry *debugfs_create_file_unsafe(const char *name, umode_t mode,
{
return __debugfs_create_file(name, mode, parent, data,
- fops ? &debugfs_open_proxy_file_operations :
- &debugfs_noop_file_operations,
+ &debugfs_open_proxy_file_operations,
fops);
}
EXPORT_SYMBOL_GPL(debugfs_create_file_unsafe);
@@ -740,7 +722,7 @@ static void __debugfs_file_removed(struct dentry *dentry)
*/
smp_mb();
fsd = READ_ONCE(dentry->d_fsdata);
- if ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)
+ if (!fsd)
return;
/* if this was the last reference, we're done */
diff --git a/fs/debugfs/internal.h b/fs/debugfs/internal.h
index 72f0034953b5..a168951a751a 100644
--- a/fs/debugfs/internal.h
+++ b/fs/debugfs/internal.h
@@ -14,6 +14,9 @@ struct file_operations;
struct debugfs_inode_info {
struct inode vfs_inode;
union {
+ const void *raw;
+ const struct file_operations *real_fops;
+ const struct debugfs_short_fops *short_fops;
debugfs_automount_t automount;
};
};
@@ -27,6 +30,7 @@ static inline struct debugfs_inode_info *DEBUGFS_I(struct inode *inode)
extern const struct file_operations debugfs_noop_file_operations;
extern const struct file_operations debugfs_open_proxy_file_operations;
extern const struct file_operations debugfs_full_proxy_file_operations;
+extern const struct file_operations debugfs_short_proxy_file_operations;
struct debugfs_fsdata {
const struct file_operations *real_fops;
@@ -50,19 +54,6 @@ enum {
HAS_IOCTL = 16
};
-/*
- * A dentry's ->d_fsdata either points to the real fops or to a
- * dynamically allocated debugfs_fsdata instance.
- * In order to distinguish between these two cases, a real fops
- * pointer gets its lowest bit set.
- */
-#define DEBUGFS_FSDATA_IS_REAL_FOPS_BIT BIT(0)
-/*
- * A dentry's ->d_fsdata, when pointing to real fops, is with
- * short fops instead of full fops.
- */
-#define DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT BIT(1)
-
/* Access BITS */
#define DEBUGFS_ALLOW_API BIT(0)
#define DEBUGFS_ALLOW_MOUNT BIT(1)
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH 06/20] debugfs: allow to store an additional opaque pointer at file creation
2024-12-29 8:12 ` [PATCH 01/20] debugfs: fix missing mutex_destroy() in short_fops case Al Viro
` (3 preceding siblings ...)
2024-12-29 8:12 ` [PATCH 05/20] debugfs: don't mess with bits in ->d_fsdata Al Viro
@ 2024-12-29 8:12 ` Al Viro
2024-12-29 8:12 ` [PATCH 07/20] carl9170: stop embedding file_operations into their objects Al Viro
` (14 subsequent siblings)
19 siblings, 0 replies; 53+ messages in thread
From: Al Viro @ 2024-12-29 8:12 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
Set by debugfs_create_file_aux(name, mode, parent, data, aux, fops).
Plain debugfs_create_file() has it set to NULL.
Accessed by debugfs_get_aux(file).
Convenience macros for numeric opaque data - debugfs_create_file_aux_num
and debugfs_get_aux_num, resp.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/debugfs/file.c | 6 ++++++
fs/debugfs/inode.c | 14 +++++++++-----
fs/debugfs/internal.h | 1 +
include/linux/debugfs.h | 27 ++++++++++++++++++++++++++-
4 files changed, 42 insertions(+), 6 deletions(-)
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index cb65ebc1a992..dec23ede8d6c 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -47,6 +47,12 @@ const struct file_operations debugfs_noop_file_operations = {
#define F_DENTRY(filp) ((filp)->f_path.dentry)
+const void *debugfs_get_aux(const struct file *file)
+{
+ return DEBUGFS_I(file_inode(file))->aux;
+}
+EXPORT_SYMBOL_GPL(debugfs_get_aux);
+
const struct file_operations *debugfs_real_fops(const struct file *filp)
{
struct debugfs_fsdata *fsd = F_DENTRY(filp)->d_fsdata;
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index 590d77757c92..c62e6b26412a 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -424,6 +424,7 @@ static struct dentry *end_creating(struct dentry *dentry)
static struct dentry *__debugfs_create_file(const char *name, umode_t mode,
struct dentry *parent, void *data,
+ const void *aux,
const struct file_operations *proxy_fops,
const void *real_fops)
{
@@ -458,6 +459,7 @@ static struct dentry *__debugfs_create_file(const char *name, umode_t mode,
proxy_fops = &debugfs_noop_file_operations;
inode->i_fop = proxy_fops;
DEBUGFS_I(inode)->raw = real_fops;
+ DEBUGFS_I(inode)->aux = aux;
d_instantiate(dentry, inode);
fsnotify_create(d_inode(dentry->d_parent), dentry);
@@ -466,19 +468,21 @@ static struct dentry *__debugfs_create_file(const char *name, umode_t mode,
struct dentry *debugfs_create_file_full(const char *name, umode_t mode,
struct dentry *parent, void *data,
+ const void *aux,
const struct file_operations *fops)
{
- return __debugfs_create_file(name, mode, parent, data,
+ return __debugfs_create_file(name, mode, parent, data, aux,
&debugfs_full_proxy_file_operations,
fops);
}
EXPORT_SYMBOL_GPL(debugfs_create_file_full);
struct dentry *debugfs_create_file_short(const char *name, umode_t mode,
- struct dentry *parent, void *data,
- const struct debugfs_short_fops *fops)
+ struct dentry *parent, void *data,
+ const void *aux,
+ const struct debugfs_short_fops *fops)
{
- return __debugfs_create_file(name, mode, parent, data,
+ return __debugfs_create_file(name, mode, parent, data, aux,
&debugfs_short_proxy_file_operations,
fops);
}
@@ -516,7 +520,7 @@ struct dentry *debugfs_create_file_unsafe(const char *name, umode_t mode,
const struct file_operations *fops)
{
- return __debugfs_create_file(name, mode, parent, data,
+ return __debugfs_create_file(name, mode, parent, data, NULL,
&debugfs_open_proxy_file_operations,
fops);
}
diff --git a/fs/debugfs/internal.h b/fs/debugfs/internal.h
index a168951a751a..01e18c42eb83 100644
--- a/fs/debugfs/internal.h
+++ b/fs/debugfs/internal.h
@@ -19,6 +19,7 @@ struct debugfs_inode_info {
const struct debugfs_short_fops *short_fops;
debugfs_automount_t automount;
};
+ const void *aux;
};
static inline struct debugfs_inode_info *DEBUGFS_I(struct inode *inode)
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h
index 59444b495d49..7c97417d73b5 100644
--- a/include/linux/debugfs.h
+++ b/include/linux/debugfs.h
@@ -79,9 +79,11 @@ struct debugfs_short_fops {
struct dentry *debugfs_create_file_full(const char *name, umode_t mode,
struct dentry *parent, void *data,
+ const void *aux,
const struct file_operations *fops);
struct dentry *debugfs_create_file_short(const char *name, umode_t mode,
struct dentry *parent, void *data,
+ const void *aux,
const struct debugfs_short_fops *fops);
/**
@@ -126,7 +128,15 @@ struct dentry *debugfs_create_file_short(const char *name, umode_t mode,
const struct debugfs_short_fops *: debugfs_create_file_short, \
struct file_operations *: debugfs_create_file_full, \
struct debugfs_short_fops *: debugfs_create_file_short) \
- (name, mode, parent, data, fops)
+ (name, mode, parent, data, NULL, fops)
+
+#define debugfs_create_file_aux(name, mode, parent, data, aux, fops) \
+ _Generic(fops, \
+ const struct file_operations *: debugfs_create_file_full, \
+ const struct debugfs_short_fops *: debugfs_create_file_short, \
+ struct file_operations *: debugfs_create_file_full, \
+ struct debugfs_short_fops *: debugfs_create_file_short) \
+ (name, mode, parent, data, aux, fops)
struct dentry *debugfs_create_file_unsafe(const char *name, umode_t mode,
struct dentry *parent, void *data,
@@ -153,6 +163,7 @@ void debugfs_remove(struct dentry *dentry);
void debugfs_lookup_and_remove(const char *name, struct dentry *parent);
const struct file_operations *debugfs_real_fops(const struct file *filp);
+const void *debugfs_get_aux(const struct file *file);
int debugfs_file_get(struct dentry *dentry);
void debugfs_file_put(struct dentry *dentry);
@@ -259,6 +270,14 @@ static inline struct dentry *debugfs_lookup(const char *name,
return ERR_PTR(-ENODEV);
}
+static inline struct dentry *debugfs_create_file_aux(const char *name,
+ umode_t mode, struct dentry *parent,
+ void *data, void *aux,
+ const void *fops)
+{
+ return ERR_PTR(-ENODEV);
+}
+
static inline struct dentry *debugfs_create_file(const char *name, umode_t mode,
struct dentry *parent, void *data,
const void *fops)
@@ -312,6 +331,7 @@ static inline void debugfs_lookup_and_remove(const char *name,
{ }
const struct file_operations *debugfs_real_fops(const struct file *filp);
+void *debugfs_get_aux(const struct file *file);
static inline int debugfs_file_get(struct dentry *dentry)
{
@@ -452,6 +472,11 @@ static inline ssize_t debugfs_read_file_str(struct file *file,
#endif
+#define debugfs_create_file_aux_num(name, mode, parent, data, n, fops) \
+ debugfs_create_file_aux(name, mode, parent, data, \
+ (void *)(unsigned long)n, fops)
+#define debugfs_get_aux_num(f) (unsigned long)debugfs_get_aux(f)
+
/**
* debugfs_create_xul - create a debugfs file that is used to read and write an
* unsigned long value, formatted in hexadecimal
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH 07/20] carl9170: stop embedding file_operations into their objects
2024-12-29 8:12 ` [PATCH 01/20] debugfs: fix missing mutex_destroy() in short_fops case Al Viro
` (4 preceding siblings ...)
2024-12-29 8:12 ` [PATCH 06/20] debugfs: allow to store an additional opaque pointer at file creation Al Viro
@ 2024-12-29 8:12 ` Al Viro
2024-12-29 8:12 ` [PATCH 08/20] b43: stop embedding struct " Al Viro
` (13 subsequent siblings)
19 siblings, 0 replies; 53+ messages in thread
From: Al Viro @ 2024-12-29 8:12 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
use debugfs_get_aux() instead; switch to debugfs_short_ops as well.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
drivers/net/wireless/ath/carl9170/debug.c | 28 ++++++++++-------------
1 file changed, 12 insertions(+), 16 deletions(-)
diff --git a/drivers/net/wireless/ath/carl9170/debug.c b/drivers/net/wireless/ath/carl9170/debug.c
index bb40889d7c72..2d734567000a 100644
--- a/drivers/net/wireless/ath/carl9170/debug.c
+++ b/drivers/net/wireless/ath/carl9170/debug.c
@@ -54,7 +54,6 @@ struct carl9170_debugfs_fops {
char *(*read)(struct ar9170 *ar, char *buf, size_t bufsize,
ssize_t *len);
ssize_t (*write)(struct ar9170 *aru, const char *buf, size_t size);
- const struct file_operations fops;
enum carl9170_device_state req_dev_state;
};
@@ -62,7 +61,7 @@ struct carl9170_debugfs_fops {
static ssize_t carl9170_debugfs_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
- struct carl9170_debugfs_fops *dfops;
+ const struct carl9170_debugfs_fops *dfops;
struct ar9170 *ar;
char *buf = NULL, *res_buf = NULL;
ssize_t ret = 0;
@@ -75,8 +74,7 @@ static ssize_t carl9170_debugfs_read(struct file *file, char __user *userbuf,
if (!ar)
return -ENODEV;
- dfops = container_of(debugfs_real_fops(file),
- struct carl9170_debugfs_fops, fops);
+ dfops = debugfs_get_aux(file);
if (!dfops->read)
return -ENOSYS;
@@ -113,7 +111,7 @@ static ssize_t carl9170_debugfs_read(struct file *file, char __user *userbuf,
static ssize_t carl9170_debugfs_write(struct file *file,
const char __user *userbuf, size_t count, loff_t *ppos)
{
- struct carl9170_debugfs_fops *dfops;
+ const struct carl9170_debugfs_fops *dfops;
struct ar9170 *ar;
char *buf = NULL;
int err = 0;
@@ -128,8 +126,7 @@ static ssize_t carl9170_debugfs_write(struct file *file,
if (!ar)
return -ENODEV;
- dfops = container_of(debugfs_real_fops(file),
- struct carl9170_debugfs_fops, fops);
+ dfops = debugfs_get_aux(file);
if (!dfops->write)
return -ENOSYS;
@@ -165,6 +162,11 @@ static ssize_t carl9170_debugfs_write(struct file *file,
return err;
}
+static struct debugfs_short_fops debugfs_fops = {
+ .read = carl9170_debugfs_read,
+ .write = carl9170_debugfs_write,
+};
+
#define __DEBUGFS_DECLARE_FILE(name, _read, _write, _read_bufsize, \
_attr, _dstate) \
static const struct carl9170_debugfs_fops carl_debugfs_##name ##_ops = {\
@@ -173,12 +175,6 @@ static const struct carl9170_debugfs_fops carl_debugfs_##name ##_ops = {\
.write = _write, \
.attr = _attr, \
.req_dev_state = _dstate, \
- .fops = { \
- .open = simple_open, \
- .read = carl9170_debugfs_read, \
- .write = carl9170_debugfs_write, \
- .owner = THIS_MODULE \
- }, \
}
#define DEBUGFS_DECLARE_FILE(name, _read, _write, _read_bufsize, _attr) \
@@ -816,9 +812,9 @@ void carl9170_debugfs_register(struct ar9170 *ar)
ar->hw->wiphy->debugfsdir);
#define DEBUGFS_ADD(name) \
- debugfs_create_file(#name, carl_debugfs_##name ##_ops.attr, \
- ar->debug_dir, ar, \
- &carl_debugfs_##name ## _ops.fops)
+ debugfs_create_file_aux(#name, carl_debugfs_##name ##_ops.attr, \
+ ar->debug_dir, ar, &carl_debugfs_##name ## _ops, \
+ &debugfs_fops)
DEBUGFS_ADD(usb_tx_anch_urbs);
DEBUGFS_ADD(usb_rx_pool_urbs);
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH 08/20] b43: stop embedding struct file_operations into their objects
2024-12-29 8:12 ` [PATCH 01/20] debugfs: fix missing mutex_destroy() in short_fops case Al Viro
` (5 preceding siblings ...)
2024-12-29 8:12 ` [PATCH 07/20] carl9170: stop embedding file_operations into their objects Al Viro
@ 2024-12-29 8:12 ` Al Viro
2024-12-29 8:12 ` [PATCH 09/20] b43legacy: make use of debugfs_get_aux() Al Viro
` (12 subsequent siblings)
19 siblings, 0 replies; 53+ messages in thread
From: Al Viro @ 2024-12-29 8:12 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
Use debugfs_get_aux() instead. And switch to debugfs_short_fops, while we
are at it...
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
drivers/net/wireless/broadcom/b43/debugfs.c | 27 +++++++++------------
1 file changed, 12 insertions(+), 15 deletions(-)
diff --git a/drivers/net/wireless/broadcom/b43/debugfs.c b/drivers/net/wireless/broadcom/b43/debugfs.c
index efa98444e3fb..5a49970afc8c 100644
--- a/drivers/net/wireless/broadcom/b43/debugfs.c
+++ b/drivers/net/wireless/broadcom/b43/debugfs.c
@@ -30,7 +30,6 @@ static struct dentry *rootdir;
struct b43_debugfs_fops {
ssize_t (*read)(struct b43_wldev *dev, char *buf, size_t bufsize);
int (*write)(struct b43_wldev *dev, const char *buf, size_t count);
- struct file_operations fops;
/* Offset of struct b43_dfs_file in struct b43_dfsentry */
size_t file_struct_offset;
};
@@ -491,7 +490,7 @@ static ssize_t b43_debugfs_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
struct b43_wldev *dev;
- struct b43_debugfs_fops *dfops;
+ const struct b43_debugfs_fops *dfops;
struct b43_dfs_file *dfile;
ssize_t ret;
char *buf;
@@ -511,8 +510,7 @@ static ssize_t b43_debugfs_read(struct file *file, char __user *userbuf,
goto out_unlock;
}
- dfops = container_of(debugfs_real_fops(file),
- struct b43_debugfs_fops, fops);
+ dfops = debugfs_get_aux(file);
if (!dfops->read) {
err = -ENOSYS;
goto out_unlock;
@@ -555,7 +553,7 @@ static ssize_t b43_debugfs_write(struct file *file,
size_t count, loff_t *ppos)
{
struct b43_wldev *dev;
- struct b43_debugfs_fops *dfops;
+ const struct b43_debugfs_fops *dfops;
char *buf;
int err = 0;
@@ -573,8 +571,7 @@ static ssize_t b43_debugfs_write(struct file *file,
goto out_unlock;
}
- dfops = container_of(debugfs_real_fops(file),
- struct b43_debugfs_fops, fops);
+ dfops = debugfs_get_aux(file);
if (!dfops->write) {
err = -ENOSYS;
goto out_unlock;
@@ -602,16 +599,16 @@ static ssize_t b43_debugfs_write(struct file *file,
}
+static struct debugfs_short_fops debugfs_ops = {
+ .read = b43_debugfs_read,
+ .write = b43_debugfs_write,
+ .llseek = generic_file_llseek,
+};
+
#define B43_DEBUGFS_FOPS(name, _read, _write) \
static struct b43_debugfs_fops fops_##name = { \
.read = _read, \
.write = _write, \
- .fops = { \
- .open = simple_open, \
- .read = b43_debugfs_read, \
- .write = b43_debugfs_write, \
- .llseek = generic_file_llseek, \
- }, \
.file_struct_offset = offsetof(struct b43_dfsentry, \
file_##name), \
}
@@ -703,9 +700,9 @@ void b43_debugfs_add_device(struct b43_wldev *dev)
#define ADD_FILE(name, mode) \
do { \
- debugfs_create_file(__stringify(name), \
+ debugfs_create_file_aux(__stringify(name), \
mode, e->subdir, dev, \
- &fops_##name.fops); \
+ &fops_##name, &debugfs_ops); \
} while (0)
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH 09/20] b43legacy: make use of debugfs_get_aux()
2024-12-29 8:12 ` [PATCH 01/20] debugfs: fix missing mutex_destroy() in short_fops case Al Viro
` (6 preceding siblings ...)
2024-12-29 8:12 ` [PATCH 08/20] b43: stop embedding struct " Al Viro
@ 2024-12-29 8:12 ` Al Viro
2024-12-29 8:12 ` [PATCH 10/20] netdevsim: don't embed file_operations into your structs Al Viro
` (11 subsequent siblings)
19 siblings, 0 replies; 53+ messages in thread
From: Al Viro @ 2024-12-29 8:12 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
.../net/wireless/broadcom/b43legacy/debugfs.c | 26 ++++++++-----------
1 file changed, 11 insertions(+), 15 deletions(-)
diff --git a/drivers/net/wireless/broadcom/b43legacy/debugfs.c b/drivers/net/wireless/broadcom/b43legacy/debugfs.c
index 6b0e8d117061..5d04bcc216e5 100644
--- a/drivers/net/wireless/broadcom/b43legacy/debugfs.c
+++ b/drivers/net/wireless/broadcom/b43legacy/debugfs.c
@@ -31,7 +31,6 @@ static struct dentry *rootdir;
struct b43legacy_debugfs_fops {
ssize_t (*read)(struct b43legacy_wldev *dev, char *buf, size_t bufsize);
int (*write)(struct b43legacy_wldev *dev, const char *buf, size_t count);
- struct file_operations fops;
/* Offset of struct b43legacy_dfs_file in struct b43legacy_dfsentry */
size_t file_struct_offset;
/* Take wl->irq_lock before calling read/write? */
@@ -188,7 +187,7 @@ static ssize_t b43legacy_debugfs_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
struct b43legacy_wldev *dev;
- struct b43legacy_debugfs_fops *dfops;
+ const struct b43legacy_debugfs_fops *dfops;
struct b43legacy_dfs_file *dfile;
ssize_t ret;
char *buf;
@@ -208,8 +207,7 @@ static ssize_t b43legacy_debugfs_read(struct file *file, char __user *userbuf,
goto out_unlock;
}
- dfops = container_of(debugfs_real_fops(file),
- struct b43legacy_debugfs_fops, fops);
+ dfops = debugfs_get_aux(file);
if (!dfops->read) {
err = -ENOSYS;
goto out_unlock;
@@ -257,7 +255,7 @@ static ssize_t b43legacy_debugfs_write(struct file *file,
size_t count, loff_t *ppos)
{
struct b43legacy_wldev *dev;
- struct b43legacy_debugfs_fops *dfops;
+ const struct b43legacy_debugfs_fops *dfops;
char *buf;
int err = 0;
@@ -275,8 +273,7 @@ static ssize_t b43legacy_debugfs_write(struct file *file,
goto out_unlock;
}
- dfops = container_of(debugfs_real_fops(file),
- struct b43legacy_debugfs_fops, fops);
+ dfops = debugfs_get_aux(file);
if (!dfops->write) {
err = -ENOSYS;
goto out_unlock;
@@ -308,17 +305,16 @@ static ssize_t b43legacy_debugfs_write(struct file *file,
return err ? err : count;
}
+static struct debugfs_short_fops debugfs_ops = {
+ .read = b43legacy_debugfs_read,
+ .write = b43legacy_debugfs_write,
+ .llseek = generic_file_llseek
+};
#define B43legacy_DEBUGFS_FOPS(name, _read, _write, _take_irqlock) \
static struct b43legacy_debugfs_fops fops_##name = { \
.read = _read, \
.write = _write, \
- .fops = { \
- .open = simple_open, \
- .read = b43legacy_debugfs_read, \
- .write = b43legacy_debugfs_write, \
- .llseek = generic_file_llseek, \
- }, \
.file_struct_offset = offsetof(struct b43legacy_dfsentry, \
file_##name), \
.take_irqlock = _take_irqlock, \
@@ -386,9 +382,9 @@ void b43legacy_debugfs_add_device(struct b43legacy_wldev *dev)
#define ADD_FILE(name, mode) \
do { \
- debugfs_create_file(__stringify(name), mode, \
+ debugfs_create_file_aux(__stringify(name), mode, \
e->subdir, dev, \
- &fops_##name.fops); \
+ &fops_##name, &debugfs_ops); \
} while (0)
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH 10/20] netdevsim: don't embed file_operations into your structs
2024-12-29 8:12 ` [PATCH 01/20] debugfs: fix missing mutex_destroy() in short_fops case Al Viro
` (7 preceding siblings ...)
2024-12-29 8:12 ` [PATCH 09/20] b43legacy: make use of debugfs_get_aux() Al Viro
@ 2024-12-29 8:12 ` Al Viro
2024-12-29 8:12 ` [PATCH 11/20] mediatek: stop messing with ->d_iname Al Viro
` (10 subsequent siblings)
19 siblings, 0 replies; 53+ messages in thread
From: Al Viro @ 2024-12-29 8:12 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
Just use debugfs_get_aux() instead of debugfs_real_fops().
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
drivers/net/netdevsim/hwstats.c | 29 +++++++++++++----------------
1 file changed, 13 insertions(+), 16 deletions(-)
diff --git a/drivers/net/netdevsim/hwstats.c b/drivers/net/netdevsim/hwstats.c
index 0e58aa7f0374..66b3215db3ac 100644
--- a/drivers/net/netdevsim/hwstats.c
+++ b/drivers/net/netdevsim/hwstats.c
@@ -331,7 +331,6 @@ enum nsim_dev_hwstats_do {
};
struct nsim_dev_hwstats_fops {
- const struct file_operations fops;
enum nsim_dev_hwstats_do action;
enum netdev_offload_xstats_type type;
};
@@ -342,13 +341,12 @@ nsim_dev_hwstats_do_write(struct file *file,
size_t count, loff_t *ppos)
{
struct nsim_dev_hwstats *hwstats = file->private_data;
- struct nsim_dev_hwstats_fops *hwsfops;
+ const struct nsim_dev_hwstats_fops *hwsfops;
struct list_head *hwsdev_list;
int ifindex;
int err;
- hwsfops = container_of(debugfs_real_fops(file),
- struct nsim_dev_hwstats_fops, fops);
+ hwsfops = debugfs_get_aux(file);
err = kstrtoint_from_user(data, count, 0, &ifindex);
if (err)
@@ -381,14 +379,13 @@ nsim_dev_hwstats_do_write(struct file *file,
return count;
}
+static struct debugfs_short_fops debugfs_ops = {
+ .write = nsim_dev_hwstats_do_write,
+ .llseek = generic_file_llseek,
+};
+
#define NSIM_DEV_HWSTATS_FOPS(ACTION, TYPE) \
{ \
- .fops = { \
- .open = simple_open, \
- .write = nsim_dev_hwstats_do_write, \
- .llseek = generic_file_llseek, \
- .owner = THIS_MODULE, \
- }, \
.action = ACTION, \
.type = TYPE, \
}
@@ -433,12 +430,12 @@ int nsim_dev_hwstats_init(struct nsim_dev *nsim_dev)
goto err_remove_hwstats_recursive;
}
- debugfs_create_file("enable_ifindex", 0200, hwstats->l3_ddir, hwstats,
- &nsim_dev_hwstats_l3_enable_fops.fops);
- debugfs_create_file("disable_ifindex", 0200, hwstats->l3_ddir, hwstats,
- &nsim_dev_hwstats_l3_disable_fops.fops);
- debugfs_create_file("fail_next_enable", 0200, hwstats->l3_ddir, hwstats,
- &nsim_dev_hwstats_l3_fail_fops.fops);
+ debugfs_create_file_aux("enable_ifindex", 0200, hwstats->l3_ddir, hwstats,
+ &nsim_dev_hwstats_l3_enable_fops, &debugfs_ops);
+ debugfs_create_file_aux("disable_ifindex", 0200, hwstats->l3_ddir, hwstats,
+ &nsim_dev_hwstats_l3_disable_fops, &debugfs_ops);
+ debugfs_create_file_aux("fail_next_enable", 0200, hwstats->l3_ddir, hwstats,
+ &nsim_dev_hwstats_l3_fail_fops, &debugfs_ops);
INIT_DELAYED_WORK(&hwstats->traffic_dw,
&nsim_dev_hwstats_traffic_work);
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH 11/20] mediatek: stop messing with ->d_iname
2024-12-29 8:12 ` [PATCH 01/20] debugfs: fix missing mutex_destroy() in short_fops case Al Viro
` (8 preceding siblings ...)
2024-12-29 8:12 ` [PATCH 10/20] netdevsim: don't embed file_operations into your structs Al Viro
@ 2024-12-29 8:12 ` Al Viro
2024-12-29 8:12 ` [PATCH 12/20] [not even compile-tested] greybus/camera - " Al Viro
` (9 subsequent siblings)
19 siblings, 0 replies; 53+ messages in thread
From: Al Viro @ 2024-12-29 8:12 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
use debgufs_{create_file,get}_aux_num() instead.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
drivers/phy/mediatek/phy-mtk-tphy.c | 40 ++++++++---------------------
1 file changed, 10 insertions(+), 30 deletions(-)
diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c b/drivers/phy/mediatek/phy-mtk-tphy.c
index 3f7095ec5978..a496fbe3352b 100644
--- a/drivers/phy/mediatek/phy-mtk-tphy.c
+++ b/drivers/phy/mediatek/phy-mtk-tphy.c
@@ -381,17 +381,12 @@ static const char *const u3_phy_files[] = {
static int u2_phy_params_show(struct seq_file *sf, void *unused)
{
struct mtk_phy_instance *inst = sf->private;
- const char *fname = file_dentry(sf->file)->d_iname;
struct u2phy_banks *u2_banks = &inst->u2_banks;
void __iomem *com = u2_banks->com;
u32 max = 0;
u32 tmp = 0;
u32 val = 0;
- int ret;
-
- ret = match_string(u2_phy_files, ARRAY_SIZE(u2_phy_files), fname);
- if (ret < 0)
- return ret;
+ int ret = debugfs_get_aux_num(sf->file);
switch (ret) {
case U2P_EYE_VRT:
@@ -438,7 +433,7 @@ static int u2_phy_params_show(struct seq_file *sf, void *unused)
break;
}
- seq_printf(sf, "%s : %d [0, %d]\n", fname, val, max);
+ seq_printf(sf, "%s : %d [0, %d]\n", u2_phy_files[ret], val, max);
return 0;
}
@@ -451,23 +446,18 @@ static int u2_phy_params_open(struct inode *inode, struct file *file)
static ssize_t u2_phy_params_write(struct file *file, const char __user *ubuf,
size_t count, loff_t *ppos)
{
- const char *fname = file_dentry(file)->d_iname;
struct seq_file *sf = file->private_data;
struct mtk_phy_instance *inst = sf->private;
struct u2phy_banks *u2_banks = &inst->u2_banks;
void __iomem *com = u2_banks->com;
ssize_t rc;
u32 val;
- int ret;
+ int ret = debugfs_get_aux_num(file);
rc = kstrtouint_from_user(ubuf, USER_BUF_LEN(count), 0, &val);
if (rc)
return rc;
- ret = match_string(u2_phy_files, ARRAY_SIZE(u2_phy_files), fname);
- if (ret < 0)
- return (ssize_t)ret;
-
switch (ret) {
case U2P_EYE_VRT:
mtk_phy_update_field(com + U3P_USBPHYACR1, PA1_RG_VRT_SEL, val);
@@ -516,23 +506,18 @@ static void u2_phy_dbgfs_files_create(struct mtk_phy_instance *inst)
int i;
for (i = 0; i < count; i++)
- debugfs_create_file(u2_phy_files[i], 0644, inst->phy->debugfs,
- inst, &u2_phy_fops);
+ debugfs_create_file_aux_num(u2_phy_files[i], 0644, inst->phy->debugfs,
+ inst, i, &u2_phy_fops);
}
static int u3_phy_params_show(struct seq_file *sf, void *unused)
{
struct mtk_phy_instance *inst = sf->private;
- const char *fname = file_dentry(sf->file)->d_iname;
struct u3phy_banks *u3_banks = &inst->u3_banks;
u32 val = 0;
u32 max = 0;
u32 tmp;
- int ret;
-
- ret = match_string(u3_phy_files, ARRAY_SIZE(u3_phy_files), fname);
- if (ret < 0)
- return ret;
+ int ret = debugfs_get_aux_num(sf->file);
switch (ret) {
case U3P_EFUSE_EN:
@@ -564,7 +549,7 @@ static int u3_phy_params_show(struct seq_file *sf, void *unused)
break;
}
- seq_printf(sf, "%s : %d [0, %d]\n", fname, val, max);
+ seq_printf(sf, "%s : %d [0, %d]\n", u3_phy_files[ret], val, max);
return 0;
}
@@ -577,23 +562,18 @@ static int u3_phy_params_open(struct inode *inode, struct file *file)
static ssize_t u3_phy_params_write(struct file *file, const char __user *ubuf,
size_t count, loff_t *ppos)
{
- const char *fname = file_dentry(file)->d_iname;
struct seq_file *sf = file->private_data;
struct mtk_phy_instance *inst = sf->private;
struct u3phy_banks *u3_banks = &inst->u3_banks;
void __iomem *phyd = u3_banks->phyd;
ssize_t rc;
u32 val;
- int ret;
+ int ret = debugfs_get_aux_num(sf->file);
rc = kstrtouint_from_user(ubuf, USER_BUF_LEN(count), 0, &val);
if (rc)
return rc;
- ret = match_string(u3_phy_files, ARRAY_SIZE(u3_phy_files), fname);
- if (ret < 0)
- return (ssize_t)ret;
-
switch (ret) {
case U3P_EFUSE_EN:
mtk_phy_update_field(phyd + U3P_U3_PHYD_RSV,
@@ -636,8 +616,8 @@ static void u3_phy_dbgfs_files_create(struct mtk_phy_instance *inst)
int i;
for (i = 0; i < count; i++)
- debugfs_create_file(u3_phy_files[i], 0644, inst->phy->debugfs,
- inst, &u3_phy_fops);
+ debugfs_create_file_aux_num(u3_phy_files[i], 0644, inst->phy->debugfs,
+ inst, i, &u3_phy_fops);
}
static int phy_type_show(struct seq_file *sf, void *unused)
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH 12/20] [not even compile-tested] greybus/camera - stop messing with ->d_iname
2024-12-29 8:12 ` [PATCH 01/20] debugfs: fix missing mutex_destroy() in short_fops case Al Viro
` (9 preceding siblings ...)
2024-12-29 8:12 ` [PATCH 11/20] mediatek: stop messing with ->d_iname Al Viro
@ 2024-12-29 8:12 ` Al Viro
2024-12-29 8:12 ` [PATCH 13/20] mtu3: don't mess wiht ->d_iname Al Viro
` (8 subsequent siblings)
19 siblings, 0 replies; 53+ messages in thread
From: Al Viro @ 2024-12-29 8:12 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
drivers/staging/greybus/camera.c | 17 +++--------------
1 file changed, 3 insertions(+), 14 deletions(-)
diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c
index ca71023df447..5d80ace41d8e 100644
--- a/drivers/staging/greybus/camera.c
+++ b/drivers/staging/greybus/camera.c
@@ -1128,18 +1128,7 @@ static ssize_t gb_camera_debugfs_write(struct file *file,
static int gb_camera_debugfs_open(struct inode *inode, struct file *file)
{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(gb_camera_debugfs_entries); ++i) {
- const struct gb_camera_debugfs_entry *entry =
- &gb_camera_debugfs_entries[i];
-
- if (!strcmp(file->f_path.dentry->d_iname, entry->name)) {
- file->private_data = (void *)entry;
- break;
- }
- }
-
+ file->private_data = (void *)debugfs_get_aux(file);
return 0;
}
@@ -1175,8 +1164,8 @@ static int gb_camera_debugfs_init(struct gb_camera *gcam)
gcam->debugfs.buffers[i].length = 0;
- debugfs_create_file(entry->name, entry->mask,
- gcam->debugfs.root, gcam,
+ debugfs_create_file_aux(entry->name, entry->mask,
+ gcam->debugfs.root, gcam, entry,
&gb_camera_debugfs_ops);
}
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH 13/20] mtu3: don't mess wiht ->d_iname
2024-12-29 8:12 ` [PATCH 01/20] debugfs: fix missing mutex_destroy() in short_fops case Al Viro
` (10 preceding siblings ...)
2024-12-29 8:12 ` [PATCH 12/20] [not even compile-tested] greybus/camera - " Al Viro
@ 2024-12-29 8:12 ` Al Viro
2024-12-29 8:12 ` [PATCH 14/20] xhci: don't mess with ->d_iname Al Viro
` (7 subsequent siblings)
19 siblings, 0 replies; 53+ messages in thread
From: Al Viro @ 2024-12-29 8:12 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
use debugfs_{create_file,get}_aux() instead.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
drivers/usb/mtu3/mtu3_debugfs.c | 40 ++++++---------------------------
1 file changed, 7 insertions(+), 33 deletions(-)
diff --git a/drivers/usb/mtu3/mtu3_debugfs.c b/drivers/usb/mtu3/mtu3_debugfs.c
index f0de99858353..deeac2c8f589 100644
--- a/drivers/usb/mtu3/mtu3_debugfs.c
+++ b/drivers/usb/mtu3/mtu3_debugfs.c
@@ -256,16 +256,7 @@ static const struct mtu3_file_map mtu3_ep_files[] = {
static int mtu3_ep_open(struct inode *inode, struct file *file)
{
- const char *file_name = file_dentry(file)->d_iname;
- const struct mtu3_file_map *f_map;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(mtu3_ep_files); i++) {
- f_map = &mtu3_ep_files[i];
-
- if (strcmp(f_map->name, file_name) == 0)
- break;
- }
+ const struct mtu3_file_map *f_map = debugfs_get_aux(file);
return single_open(file, f_map->show, inode->i_private);
}
@@ -288,17 +279,8 @@ static const struct debugfs_reg32 mtu3_prb_regs[] = {
static int mtu3_probe_show(struct seq_file *sf, void *unused)
{
- const char *file_name = file_dentry(sf->file)->d_iname;
struct mtu3 *mtu = sf->private;
- const struct debugfs_reg32 *regs;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(mtu3_prb_regs); i++) {
- regs = &mtu3_prb_regs[i];
-
- if (strcmp(regs->name, file_name) == 0)
- break;
- }
+ const struct debugfs_reg32 *regs = debugfs_get_aux(sf->file);
seq_printf(sf, "0x%04x - 0x%08x\n", (u32)regs->offset,
mtu3_readl(mtu->ippc_base, (u32)regs->offset));
@@ -314,13 +296,11 @@ static int mtu3_probe_open(struct inode *inode, struct file *file)
static ssize_t mtu3_probe_write(struct file *file, const char __user *ubuf,
size_t count, loff_t *ppos)
{
- const char *file_name = file_dentry(file)->d_iname;
struct seq_file *sf = file->private_data;
struct mtu3 *mtu = sf->private;
- const struct debugfs_reg32 *regs;
+ const struct debugfs_reg32 *regs = debugfs_get_aux(file);
char buf[32];
u32 val;
- int i;
if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
return -EFAULT;
@@ -328,12 +308,6 @@ static ssize_t mtu3_probe_write(struct file *file, const char __user *ubuf,
if (kstrtou32(buf, 0, &val))
return -EINVAL;
- for (i = 0; i < ARRAY_SIZE(mtu3_prb_regs); i++) {
- regs = &mtu3_prb_regs[i];
-
- if (strcmp(regs->name, file_name) == 0)
- break;
- }
mtu3_writel(mtu->ippc_base, (u32)regs->offset, val);
return count;
@@ -358,8 +332,8 @@ static void mtu3_debugfs_create_prb_files(struct mtu3 *mtu)
for (i = 0; i < ARRAY_SIZE(mtu3_prb_regs); i++) {
regs = &mtu3_prb_regs[i];
- debugfs_create_file(regs->name, 0644, dir_prb,
- mtu, &mtu3_probe_fops);
+ debugfs_create_file_aux(regs->name, 0644, dir_prb,
+ mtu, regs, &mtu3_probe_fops);
}
mtu3_debugfs_regset(mtu, mtu->ippc_base, mtu3_prb_regs,
@@ -379,8 +353,8 @@ static void mtu3_debugfs_create_ep_dir(struct mtu3_ep *mep,
for (i = 0; i < ARRAY_SIZE(mtu3_ep_files); i++) {
files = &mtu3_ep_files[i];
- debugfs_create_file(files->name, 0444, dir_ep,
- mep, &mtu3_ep_fops);
+ debugfs_create_file_aux(files->name, 0444, dir_ep,
+ mep, files, &mtu3_ep_fops);
}
}
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH 14/20] xhci: don't mess with ->d_iname
2024-12-29 8:12 ` [PATCH 01/20] debugfs: fix missing mutex_destroy() in short_fops case Al Viro
` (11 preceding siblings ...)
2024-12-29 8:12 ` [PATCH 13/20] mtu3: don't mess wiht ->d_iname Al Viro
@ 2024-12-29 8:12 ` Al Viro
2024-12-29 8:12 ` [PATCH 15/20] qat: don't mess with ->d_name Al Viro
` (6 subsequent siblings)
19 siblings, 0 replies; 53+ messages in thread
From: Al Viro @ 2024-12-29 8:12 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
use debugs_{creat_file,get}_aux() instead
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
drivers/usb/host/xhci-debugfs.c | 25 ++++---------------------
1 file changed, 4 insertions(+), 21 deletions(-)
diff --git a/drivers/usb/host/xhci-debugfs.c b/drivers/usb/host/xhci-debugfs.c
index 4f0c1b96e208..1f5ef174abea 100644
--- a/drivers/usb/host/xhci-debugfs.c
+++ b/drivers/usb/host/xhci-debugfs.c
@@ -232,16 +232,7 @@ static struct xhci_file_map ring_files[] = {
static int xhci_ring_open(struct inode *inode, struct file *file)
{
- int i;
- struct xhci_file_map *f_map;
- const char *file_name = file_dentry(file)->d_iname;
-
- for (i = 0; i < ARRAY_SIZE(ring_files); i++) {
- f_map = &ring_files[i];
-
- if (strcmp(f_map->name, file_name) == 0)
- break;
- }
+ const struct xhci_file_map *f_map = debugfs_get_aux(file);
return single_open(file, f_map->show, inode->i_private);
}
@@ -318,16 +309,7 @@ static struct xhci_file_map context_files[] = {
static int xhci_context_open(struct inode *inode, struct file *file)
{
- int i;
- struct xhci_file_map *f_map;
- const char *file_name = file_dentry(file)->d_iname;
-
- for (i = 0; i < ARRAY_SIZE(context_files); i++) {
- f_map = &context_files[i];
-
- if (strcmp(f_map->name, file_name) == 0)
- break;
- }
+ const struct xhci_file_map *f_map = debugfs_get_aux(file);
return single_open(file, f_map->show, inode->i_private);
}
@@ -410,7 +392,8 @@ static void xhci_debugfs_create_files(struct xhci_hcd *xhci,
int i;
for (i = 0; i < nentries; i++)
- debugfs_create_file(files[i].name, 0444, parent, data, fops);
+ debugfs_create_file_aux(files[i].name, 0444, parent,
+ data, &files[i], fops);
}
static struct dentry *xhci_debugfs_create_ring_dir(struct xhci_hcd *xhci,
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH 15/20] qat: don't mess with ->d_name
2024-12-29 8:12 ` [PATCH 01/20] debugfs: fix missing mutex_destroy() in short_fops case Al Viro
` (12 preceding siblings ...)
2024-12-29 8:12 ` [PATCH 14/20] xhci: don't mess with ->d_iname Al Viro
@ 2024-12-29 8:12 ` Al Viro
2024-12-29 8:12 ` [PATCH 16/20] sof-client-ipc-flood-test: " Al Viro
` (5 subsequent siblings)
19 siblings, 0 replies; 53+ messages in thread
From: Al Viro @ 2024-12-29 8:12 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
use debugfs_{create_file,get}_aux_num() instead.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
.../intel/qat/qat_common/adf_tl_debugfs.c | 36 +++----------------
1 file changed, 4 insertions(+), 32 deletions(-)
diff --git a/drivers/crypto/intel/qat/qat_common/adf_tl_debugfs.c b/drivers/crypto/intel/qat/qat_common/adf_tl_debugfs.c
index c8241f5a0a26..f20ae7e35a0d 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_tl_debugfs.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_tl_debugfs.c
@@ -473,22 +473,6 @@ static ssize_t tl_control_write(struct file *file, const char __user *userbuf,
}
DEFINE_SHOW_STORE_ATTRIBUTE(tl_control);
-static int get_rp_index_from_file(const struct file *f, u8 *rp_id, u8 rp_num)
-{
- char alpha;
- u8 index;
- int ret;
-
- ret = sscanf(f->f_path.dentry->d_name.name, ADF_TL_RP_REGS_FNAME, &alpha);
- if (ret != 1)
- return -EINVAL;
-
- index = ADF_TL_DBG_RP_INDEX_ALPHA(alpha);
- *rp_id = index;
-
- return 0;
-}
-
static int adf_tl_dbg_change_rp_index(struct adf_accel_dev *accel_dev,
unsigned int new_rp_num,
unsigned int rp_regs_index)
@@ -611,18 +595,11 @@ static int tl_rp_data_show(struct seq_file *s, void *unused)
{
struct adf_accel_dev *accel_dev = s->private;
u8 rp_regs_index;
- u8 max_rp;
- int ret;
if (!accel_dev)
return -EINVAL;
- max_rp = GET_TL_DATA(accel_dev).max_rp;
- ret = get_rp_index_from_file(s->file, &rp_regs_index, max_rp);
- if (ret) {
- dev_dbg(&GET_DEV(accel_dev), "invalid RP data file name\n");
- return ret;
- }
+ rp_regs_index = debugfs_get_aux_num(s->file);
return tl_print_rp_data(accel_dev, s, rp_regs_index);
}
@@ -635,7 +612,6 @@ static ssize_t tl_rp_data_write(struct file *file, const char __user *userbuf,
struct adf_telemetry *telemetry;
unsigned int new_rp_num;
u8 rp_regs_index;
- u8 max_rp;
int ret;
accel_dev = seq_f->private;
@@ -643,15 +619,10 @@ static ssize_t tl_rp_data_write(struct file *file, const char __user *userbuf,
return -EINVAL;
telemetry = accel_dev->telemetry;
- max_rp = GET_TL_DATA(accel_dev).max_rp;
mutex_lock(&telemetry->wr_lock);
- ret = get_rp_index_from_file(file, &rp_regs_index, max_rp);
- if (ret) {
- dev_dbg(&GET_DEV(accel_dev), "invalid RP data file name\n");
- goto unlock_and_exit;
- }
+ rp_regs_index = debugfs_get_aux_num(file);
ret = kstrtou32_from_user(userbuf, count, 10, &new_rp_num);
if (ret)
@@ -689,7 +660,8 @@ void adf_tl_dbgfs_add(struct adf_accel_dev *accel_dev)
for (i = 0; i < max_rp; i++) {
snprintf(name, sizeof(name), ADF_TL_RP_REGS_FNAME,
ADF_TL_DBG_RP_ALPHA_INDEX(i));
- debugfs_create_file(name, 0644, dir, accel_dev, &tl_rp_data_fops);
+ debugfs_create_file_aux_num(name, 0644, dir, accel_dev, i,
+ &tl_rp_data_fops);
}
}
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH 16/20] sof-client-ipc-flood-test: don't mess with ->d_name
2024-12-29 8:12 ` [PATCH 01/20] debugfs: fix missing mutex_destroy() in short_fops case Al Viro
` (13 preceding siblings ...)
2024-12-29 8:12 ` [PATCH 15/20] qat: don't mess with ->d_name Al Viro
@ 2024-12-29 8:12 ` Al Viro
2024-12-29 8:12 ` [PATCH 17/20] slub: " Al Viro
` (4 subsequent siblings)
19 siblings, 0 replies; 53+ messages in thread
From: Al Viro @ 2024-12-29 8:12 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
sound/soc/sof/sof-client-ipc-flood-test.c | 39 +++++++----------------
1 file changed, 12 insertions(+), 27 deletions(-)
diff --git a/sound/soc/sof/sof-client-ipc-flood-test.c b/sound/soc/sof/sof-client-ipc-flood-test.c
index b35c98896968..11b6f7da2882 100644
--- a/sound/soc/sof/sof-client-ipc-flood-test.c
+++ b/sound/soc/sof/sof-client-ipc-flood-test.c
@@ -158,7 +158,6 @@ static ssize_t sof_ipc_flood_dfs_write(struct file *file, const char __user *buf
unsigned long ipc_duration_ms = 0;
bool flood_duration_test = false;
unsigned long ipc_count = 0;
- struct dentry *dentry;
int err;
char *string;
int ret;
@@ -182,14 +181,7 @@ static ssize_t sof_ipc_flood_dfs_write(struct file *file, const char __user *buf
* ipc_duration_ms test floods the DSP for the time specified
* in the debugfs entry.
*/
- dentry = file->f_path.dentry;
- if (strcmp(dentry->d_name.name, DEBUGFS_IPC_FLOOD_COUNT) &&
- strcmp(dentry->d_name.name, DEBUGFS_IPC_FLOOD_DURATION)) {
- ret = -EINVAL;
- goto out;
- }
-
- if (!strcmp(dentry->d_name.name, DEBUGFS_IPC_FLOOD_DURATION))
+ if (debugfs_get_aux_num(file))
flood_duration_test = true;
/* test completion criterion */
@@ -252,22 +244,15 @@ static ssize_t sof_ipc_flood_dfs_read(struct file *file, char __user *buffer,
struct sof_ipc_flood_priv *priv = cdev->data;
size_t size_ret;
- struct dentry *dentry;
+ if (*ppos)
+ return 0;
- dentry = file->f_path.dentry;
- if (!strcmp(dentry->d_name.name, DEBUGFS_IPC_FLOOD_COUNT) ||
- !strcmp(dentry->d_name.name, DEBUGFS_IPC_FLOOD_DURATION)) {
- if (*ppos)
- return 0;
+ count = min_t(size_t, count, strlen(priv->buf));
+ size_ret = copy_to_user(buffer, priv->buf, count);
+ if (size_ret)
+ return -EFAULT;
- count = min_t(size_t, count, strlen(priv->buf));
- size_ret = copy_to_user(buffer, priv->buf, count);
- if (size_ret)
- return -EFAULT;
-
- *ppos += count;
- return count;
- }
+ *ppos += count;
return count;
}
@@ -320,12 +305,12 @@ static int sof_ipc_flood_probe(struct auxiliary_device *auxdev,
priv->dfs_root = debugfs_create_dir(dev_name(dev), debugfs_root);
if (!IS_ERR_OR_NULL(priv->dfs_root)) {
/* create read-write ipc_flood_count debugfs entry */
- debugfs_create_file(DEBUGFS_IPC_FLOOD_COUNT, 0644, priv->dfs_root,
- cdev, &sof_ipc_flood_fops);
+ debugfs_create_file_aux_num(DEBUGFS_IPC_FLOOD_COUNT, 0644,
+ priv->dfs_root, cdev, 0, &sof_ipc_flood_fops);
/* create read-write ipc_flood_duration_ms debugfs entry */
- debugfs_create_file(DEBUGFS_IPC_FLOOD_DURATION, 0644,
- priv->dfs_root, cdev, &sof_ipc_flood_fops);
+ debugfs_create_file_aux_num(DEBUGFS_IPC_FLOOD_DURATION, 0644,
+ priv->dfs_root, cdev, 1, &sof_ipc_flood_fops);
if (auxdev->id == 0) {
/*
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH 17/20] slub: don't mess with ->d_name
2024-12-29 8:12 ` [PATCH 01/20] debugfs: fix missing mutex_destroy() in short_fops case Al Viro
` (14 preceding siblings ...)
2024-12-29 8:12 ` [PATCH 16/20] sof-client-ipc-flood-test: " Al Viro
@ 2024-12-29 8:12 ` Al Viro
2024-12-29 8:12 ` [PATCH 18/20] arm_scmi: don't mess with ->d_parent->d_name Al Viro
` (3 subsequent siblings)
19 siblings, 0 replies; 53+ messages in thread
From: Al Viro @ 2024-12-29 8:12 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
mm/slub.c | 13 +++++--------
1 file changed, 5 insertions(+), 8 deletions(-)
diff --git a/mm/slub.c b/mm/slub.c
index c2151c9fee22..4f006b047552 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -7513,10 +7513,7 @@ static int slab_debug_trace_open(struct inode *inode, struct file *filep)
return -ENOMEM;
}
- if (strcmp(filep->f_path.dentry->d_name.name, "alloc_traces") == 0)
- alloc = TRACK_ALLOC;
- else
- alloc = TRACK_FREE;
+ alloc = debugfs_get_aux_num(filep);
if (!alloc_loc_track(t, PAGE_SIZE / sizeof(struct location), GFP_KERNEL)) {
bitmap_free(obj_map);
@@ -7572,11 +7569,11 @@ static void debugfs_slab_add(struct kmem_cache *s)
slab_cache_dir = debugfs_create_dir(s->name, slab_debugfs_root);
- debugfs_create_file("alloc_traces", 0400,
- slab_cache_dir, s, &slab_debugfs_fops);
+ debugfs_create_file_aux_num("alloc_traces", 0400, slab_cache_dir, s,
+ TRACK_ALLOC, &slab_debugfs_fops);
- debugfs_create_file("free_traces", 0400,
- slab_cache_dir, s, &slab_debugfs_fops);
+ debugfs_create_file_aux_num("free_traces", 0400, slab_cache_dir, s,
+ TRACK_FREE, &slab_debugfs_fops);
}
void debugfs_slab_release(struct kmem_cache *s)
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH 18/20] arm_scmi: don't mess with ->d_parent->d_name
2024-12-29 8:12 ` [PATCH 01/20] debugfs: fix missing mutex_destroy() in short_fops case Al Viro
` (15 preceding siblings ...)
2024-12-29 8:12 ` [PATCH 17/20] slub: " Al Viro
@ 2024-12-29 8:12 ` Al Viro
2024-12-29 8:12 ` [PATCH 19/20] octeontx2: don't mess with ->d_parent or ->d_parent->d_name Al Viro
` (2 subsequent siblings)
19 siblings, 0 replies; 53+ messages in thread
From: Al Viro @ 2024-12-29 8:12 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
drivers/firmware/arm_scmi/raw_mode.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/firmware/arm_scmi/raw_mode.c b/drivers/firmware/arm_scmi/raw_mode.c
index 9e89a6a763da..7cc0d616b8de 100644
--- a/drivers/firmware/arm_scmi/raw_mode.c
+++ b/drivers/firmware/arm_scmi/raw_mode.c
@@ -886,10 +886,8 @@ static __poll_t scmi_dbg_raw_mode_message_poll(struct file *filp,
static int scmi_dbg_raw_mode_open(struct inode *inode, struct file *filp)
{
- u8 id;
struct scmi_raw_mode_info *raw;
struct scmi_dbg_raw_data *rd;
- const char *id_str = filp->f_path.dentry->d_parent->d_name.name;
if (!inode->i_private)
return -ENODEV;
@@ -915,8 +913,8 @@ static int scmi_dbg_raw_mode_open(struct inode *inode, struct file *filp)
}
/* Grab channel ID from debugfs entry naming if any */
- if (!kstrtou8(id_str, 16, &id))
- rd->chan_id = id;
+ /* not set - reassing 0 we already had after kzalloc() */
+ rd->chan_id = debugfs_get_aux_num(filp);
rd->raw = raw;
filp->private_data = rd;
@@ -1225,10 +1223,12 @@ void *scmi_raw_mode_init(const struct scmi_handle *handle,
snprintf(cdir, 8, "0x%02X", channels[i]);
chd = debugfs_create_dir(cdir, top_chans);
- debugfs_create_file("message", 0600, chd, raw,
+ debugfs_create_file_aux_num("message", 0600, chd,
+ raw, channels[i],
&scmi_dbg_raw_mode_message_fops);
- debugfs_create_file("message_async", 0600, chd, raw,
+ debugfs_create_file_aux_num("message_async", 0600, chd,
+ raw, channels[i],
&scmi_dbg_raw_mode_message_async_fops);
}
}
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH 19/20] octeontx2: don't mess with ->d_parent or ->d_parent->d_name
2024-12-29 8:12 ` [PATCH 01/20] debugfs: fix missing mutex_destroy() in short_fops case Al Viro
` (16 preceding siblings ...)
2024-12-29 8:12 ` [PATCH 18/20] arm_scmi: don't mess with ->d_parent->d_name Al Viro
@ 2024-12-29 8:12 ` Al Viro
2024-12-29 8:12 ` [PATCH 20/20] saner replacement for debugfs_rename() Al Viro
2025-01-07 15:20 ` [PATCH 01/20] debugfs: fix missing mutex_destroy() in short_fops case Greg KH
19 siblings, 0 replies; 53+ messages in thread
From: Al Viro @ 2024-12-29 8:12 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
use debugfs_{create_file,get}_aux_num() instead.
[and for fsck sake, don't call variables filp - especially the
ones that are not even struct file *]
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
.../marvell/octeontx2/af/rvu_debugfs.c | 76 ++++++-------------
1 file changed, 24 insertions(+), 52 deletions(-)
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c
index 148144f5b61d..a1f9ec03c2ce 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c
@@ -917,19 +917,18 @@ static void print_npa_qsize(struct seq_file *m, struct rvu_pfvf *pfvf)
/* The 'qsize' entry dumps current Aura/Pool context Qsize
* and each context's current enable/disable status in a bitmap.
*/
-static int rvu_dbg_qsize_display(struct seq_file *filp, void *unsused,
+static int rvu_dbg_qsize_display(struct seq_file *s, void *unsused,
int blktype)
{
- void (*print_qsize)(struct seq_file *filp,
+ void (*print_qsize)(struct seq_file *s,
struct rvu_pfvf *pfvf) = NULL;
- struct dentry *current_dir;
struct rvu_pfvf *pfvf;
struct rvu *rvu;
int qsize_id;
u16 pcifunc;
int blkaddr;
- rvu = filp->private;
+ rvu = s->private;
switch (blktype) {
case BLKTYPE_NPA:
qsize_id = rvu->rvu_dbg.npa_qsize_id;
@@ -945,32 +944,28 @@ static int rvu_dbg_qsize_display(struct seq_file *filp, void *unsused,
return -EINVAL;
}
- if (blktype == BLKTYPE_NPA) {
+ if (blktype == BLKTYPE_NPA)
blkaddr = BLKADDR_NPA;
- } else {
- current_dir = filp->file->f_path.dentry->d_parent;
- blkaddr = (!strcmp(current_dir->d_name.name, "nix1") ?
- BLKADDR_NIX1 : BLKADDR_NIX0);
- }
+ else
+ blkaddr = debugfs_get_aux_num(s->file);
if (!rvu_dbg_is_valid_lf(rvu, blkaddr, qsize_id, &pcifunc))
return -EINVAL;
pfvf = rvu_get_pfvf(rvu, pcifunc);
- print_qsize(filp, pfvf);
+ print_qsize(s, pfvf);
return 0;
}
-static ssize_t rvu_dbg_qsize_write(struct file *filp,
+static ssize_t rvu_dbg_qsize_write(struct file *file,
const char __user *buffer, size_t count,
loff_t *ppos, int blktype)
{
char *blk_string = (blktype == BLKTYPE_NPA) ? "npa" : "nix";
- struct seq_file *seqfile = filp->private_data;
+ struct seq_file *seqfile = file->private_data;
char *cmd_buf, *cmd_buf_tmp, *subtoken;
struct rvu *rvu = seqfile->private;
- struct dentry *current_dir;
int blkaddr;
u16 pcifunc;
int ret, lf;
@@ -996,13 +991,10 @@ static ssize_t rvu_dbg_qsize_write(struct file *filp,
goto qsize_write_done;
}
- if (blktype == BLKTYPE_NPA) {
+ if (blktype == BLKTYPE_NPA)
blkaddr = BLKADDR_NPA;
- } else {
- current_dir = filp->f_path.dentry->d_parent;
- blkaddr = (!strcmp(current_dir->d_name.name, "nix1") ?
- BLKADDR_NIX1 : BLKADDR_NIX0);
- }
+ else
+ blkaddr = debugfs_get_aux_num(file);
if (!rvu_dbg_is_valid_lf(rvu, blkaddr, lf, &pcifunc)) {
ret = -EINVAL;
@@ -2704,8 +2696,8 @@ static void rvu_dbg_nix_init(struct rvu *rvu, int blkaddr)
&rvu_dbg_nix_ndc_tx_hits_miss_fops);
debugfs_create_file("ndc_rx_hits_miss", 0600, rvu->rvu_dbg.nix, nix_hw,
&rvu_dbg_nix_ndc_rx_hits_miss_fops);
- debugfs_create_file("qsize", 0600, rvu->rvu_dbg.nix, rvu,
- &rvu_dbg_nix_qsize_fops);
+ debugfs_create_file_aux_num("qsize", 0600, rvu->rvu_dbg.nix, rvu,
+ blkaddr, &rvu_dbg_nix_qsize_fops);
debugfs_create_file("ingress_policer_ctx", 0600, rvu->rvu_dbg.nix, nix_hw,
&rvu_dbg_nix_band_prof_ctx_fops);
debugfs_create_file("ingress_policer_rsrc", 0600, rvu->rvu_dbg.nix, nix_hw,
@@ -2854,28 +2846,14 @@ static int cgx_print_stats(struct seq_file *s, int lmac_id)
return err;
}
-static int rvu_dbg_derive_lmacid(struct seq_file *filp, int *lmac_id)
+static int rvu_dbg_derive_lmacid(struct seq_file *s)
{
- struct dentry *current_dir;
- char *buf;
-
- current_dir = filp->file->f_path.dentry->d_parent;
- buf = strrchr(current_dir->d_name.name, 'c');
- if (!buf)
- return -EINVAL;
-
- return kstrtoint(buf + 1, 10, lmac_id);
+ return debugfs_get_aux_num(s->file);
}
-static int rvu_dbg_cgx_stat_display(struct seq_file *filp, void *unused)
+static int rvu_dbg_cgx_stat_display(struct seq_file *s, void *unused)
{
- int lmac_id, err;
-
- err = rvu_dbg_derive_lmacid(filp, &lmac_id);
- if (!err)
- return cgx_print_stats(filp, lmac_id);
-
- return err;
+ return cgx_print_stats(s, rvu_dbg_derive_lmacid(s));
}
RVU_DEBUG_SEQ_FOPS(cgx_stat, cgx_stat_display, NULL);
@@ -2933,15 +2911,9 @@ static int cgx_print_dmac_flt(struct seq_file *s, int lmac_id)
return 0;
}
-static int rvu_dbg_cgx_dmac_flt_display(struct seq_file *filp, void *unused)
+static int rvu_dbg_cgx_dmac_flt_display(struct seq_file *s, void *unused)
{
- int err, lmac_id;
-
- err = rvu_dbg_derive_lmacid(filp, &lmac_id);
- if (!err)
- return cgx_print_dmac_flt(filp, lmac_id);
-
- return err;
+ return cgx_print_dmac_flt(s, rvu_dbg_derive_lmacid(s));
}
RVU_DEBUG_SEQ_FOPS(cgx_dmac_flt, cgx_dmac_flt_display, NULL);
@@ -2980,10 +2952,10 @@ static void rvu_dbg_cgx_init(struct rvu *rvu)
rvu->rvu_dbg.lmac =
debugfs_create_dir(dname, rvu->rvu_dbg.cgx);
- debugfs_create_file("stats", 0600, rvu->rvu_dbg.lmac,
- cgx, &rvu_dbg_cgx_stat_fops);
- debugfs_create_file("mac_filter", 0600,
- rvu->rvu_dbg.lmac, cgx,
+ debugfs_create_file_aux_num("stats", 0600, rvu->rvu_dbg.lmac,
+ cgx, lmac_id, &rvu_dbg_cgx_stat_fops);
+ debugfs_create_file_aux_num("mac_filter", 0600,
+ rvu->rvu_dbg.lmac, cgx, lmac_id,
&rvu_dbg_cgx_dmac_flt_fops);
}
}
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH 20/20] saner replacement for debugfs_rename()
2024-12-29 8:12 ` [PATCH 01/20] debugfs: fix missing mutex_destroy() in short_fops case Al Viro
` (17 preceding siblings ...)
2024-12-29 8:12 ` [PATCH 19/20] octeontx2: don't mess with ->d_parent or ->d_parent->d_name Al Viro
@ 2024-12-29 8:12 ` Al Viro
2024-12-29 16:38 ` Al Viro
2025-01-07 15:20 ` [PATCH 01/20] debugfs: fix missing mutex_destroy() in short_fops case Greg KH
19 siblings, 1 reply; 53+ messages in thread
From: Al Viro @ 2024-12-29 8:12 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
Existing primitive has several problems:
1) calling conventions are clumsy - it returns a dentry reference
that is either identical to its second argument or is an ERR_PTR(-E...);
in both cases no refcount changes happen. Inconvenient for users and
bug-prone; it would be better to have it return 0 on success and -E... on
failure.
2) it allows cross-directory moves; however, no such caller have
ever materialized and considering the way debugfs is used, it's unlikely
to happen in the future. What's more, any such caller would have fun
issues to deal with wrt interplay with recursive removal. It also makes
the calling conventions clumsier...
3) tautological rename fails; the callers have no race-free way
to deal with that.
4) new name must have been formed by the caller; quite a few
callers have it done by sprintf/kasprintf/etc., ending up with considerable
boilerplate.
Proposed replacement: int debugfs_change_name(dentry, fmt, ...). All callers
convert to that easily, and it's simpler internally.
IMO debugfs_rename() should go; if we ever get a real-world use case for
cross-directory moves in debugfs, we can always look into the right way
to handle that.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
Documentation/filesystems/debugfs.rst | 12 +-
drivers/net/bonding/bond_debugfs.c | 9 +-
drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c | 19 +---
drivers/net/ethernet/marvell/skge.c | 5 +-
drivers/net/ethernet/marvell/sky2.c | 5 +-
.../net/ethernet/stmicro/stmmac/stmmac_main.c | 6 +-
drivers/opp/debugfs.c | 10 +-
fs/debugfs/inode.c | 106 +++++++++---------
include/linux/debugfs.h | 9 +-
mm/shrinker_debug.c | 16 +--
net/hsr/hsr_debugfs.c | 9 +-
net/mac80211/debugfs_netdev.c | 11 +-
net/wireless/core.c | 5 +-
13 files changed, 77 insertions(+), 145 deletions(-)
diff --git a/Documentation/filesystems/debugfs.rst b/Documentation/filesystems/debugfs.rst
index dc35da8b8792..f7f977ffbf8d 100644
--- a/Documentation/filesystems/debugfs.rst
+++ b/Documentation/filesystems/debugfs.rst
@@ -211,18 +211,16 @@ seq_file content.
There are a couple of other directory-oriented helper functions::
- struct dentry *debugfs_rename(struct dentry *old_dir,
- struct dentry *old_dentry,
- struct dentry *new_dir,
- const char *new_name);
+ struct dentry *debugfs_change_name(struct dentry *dentry,
+ const char *fmt, ...);
struct dentry *debugfs_create_symlink(const char *name,
struct dentry *parent,
const char *target);
-A call to debugfs_rename() will give a new name to an existing debugfs
-file, possibly in a different directory. The new_name must not exist prior
-to the call; the return value is old_dentry with updated information.
+A call to debugfs_change_name() will give a new name to an existing debugfs
+file, always in the same directory. The new_name must not exist prior
+to the call; the return value is 0 on success and -E... on failuer.
Symbolic links can be created with debugfs_create_symlink().
There is one important thing that all debugfs users must take into account:
diff --git a/drivers/net/bonding/bond_debugfs.c b/drivers/net/bonding/bond_debugfs.c
index b19492a7f6ad..2b78be129770 100644
--- a/drivers/net/bonding/bond_debugfs.c
+++ b/drivers/net/bonding/bond_debugfs.c
@@ -63,13 +63,8 @@ void bond_debug_unregister(struct bonding *bond)
void bond_debug_reregister(struct bonding *bond)
{
- struct dentry *d;
-
- d = debugfs_rename(bonding_debug_root, bond->debug_dir,
- bonding_debug_root, bond->dev->name);
- if (!IS_ERR(d)) {
- bond->debug_dir = d;
- } else {
+ err = debugfs_change_name(bond->debug_dir, "%s", bond->dev->name);
+ if (err) {
netdev_warn(bond->dev, "failed to reregister, so just unregister old one\n");
bond_debug_unregister(bond);
}
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c b/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
index b0a6c96b6ef4..b35808d3d07f 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
@@ -505,21 +505,6 @@ void xgbe_debugfs_exit(struct xgbe_prv_data *pdata)
void xgbe_debugfs_rename(struct xgbe_prv_data *pdata)
{
- char *buf;
-
- if (!pdata->xgbe_debugfs)
- return;
-
- buf = kasprintf(GFP_KERNEL, "amd-xgbe-%s", pdata->netdev->name);
- if (!buf)
- return;
-
- if (!strcmp(pdata->xgbe_debugfs->d_name.name, buf))
- goto out;
-
- debugfs_rename(pdata->xgbe_debugfs->d_parent, pdata->xgbe_debugfs,
- pdata->xgbe_debugfs->d_parent, buf);
-
-out:
- kfree(buf);
+ debugfs_change_name(pdata->xgbe_debugfs,
+ "amd-xgbe-%s", pdata->netdev->name);
}
diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c
index 25bf6ec44289..a1bada9eaaf6 100644
--- a/drivers/net/ethernet/marvell/skge.c
+++ b/drivers/net/ethernet/marvell/skge.c
@@ -3742,10 +3742,7 @@ static int skge_device_event(struct notifier_block *unused,
skge = netdev_priv(dev);
switch (event) {
case NETDEV_CHANGENAME:
- if (skge->debugfs)
- skge->debugfs = debugfs_rename(skge_debug,
- skge->debugfs,
- skge_debug, dev->name);
+ debugfs_change_name(skge->debugfs, "%s", dev->name);
break;
case NETDEV_GOING_DOWN:
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index 3914cd9210d4..719ae94a5f97 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -4493,10 +4493,7 @@ static int sky2_device_event(struct notifier_block *unused,
switch (event) {
case NETDEV_CHANGENAME:
- if (sky2->debugfs) {
- sky2->debugfs = debugfs_rename(sky2_debug, sky2->debugfs,
- sky2_debug, dev->name);
- }
+ debugfs_change_name(sky2->debugfs, "%s", dev->name);
break;
case NETDEV_GOING_DOWN:
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index c81ea8cdfe6e..82e2908016bd 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -6489,11 +6489,7 @@ static int stmmac_device_event(struct notifier_block *unused,
switch (event) {
case NETDEV_CHANGENAME:
- if (priv->dbgfs_dir)
- priv->dbgfs_dir = debugfs_rename(stmmac_fs_dir,
- priv->dbgfs_dir,
- stmmac_fs_dir,
- dev->name);
+ debugfs_change_name(priv->dbgfs_dir, "%s", dev->name);
break;
}
done:
diff --git a/drivers/opp/debugfs.c b/drivers/opp/debugfs.c
index 105de7c3274a..8fc6238b1728 100644
--- a/drivers/opp/debugfs.c
+++ b/drivers/opp/debugfs.c
@@ -217,7 +217,7 @@ static void opp_migrate_dentry(struct opp_device *opp_dev,
{
struct opp_device *new_dev = NULL, *iter;
const struct device *dev;
- struct dentry *dentry;
+ int err;
/* Look for next opp-dev */
list_for_each_entry(iter, &opp_table->dev_list, node)
@@ -234,16 +234,14 @@ static void opp_migrate_dentry(struct opp_device *opp_dev,
opp_set_dev_name(dev, opp_table->dentry_name);
- dentry = debugfs_rename(rootdir, opp_dev->dentry, rootdir,
- opp_table->dentry_name);
- if (IS_ERR(dentry)) {
+ err = debugfs_change_name(opp_dev->dentry, "%s", opp_table->dentry_name);
+ if (err) {
dev_err(dev, "%s: Failed to rename link from: %s to %s\n",
__func__, dev_name(opp_dev->dev), dev_name(dev));
return;
}
- new_dev->dentry = dentry;
- opp_table->dentry = dentry;
+ new_dev->dentry = opp_table->dentry = opp_dev->dentry;
}
/**
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index c62e6b26412a..948345d1226e 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -830,76 +830,70 @@ void debugfs_lookup_and_remove(const char *name, struct dentry *parent)
EXPORT_SYMBOL_GPL(debugfs_lookup_and_remove);
/**
- * debugfs_rename - rename a file/directory in the debugfs filesystem
- * @old_dir: a pointer to the parent dentry for the renamed object. This
- * should be a directory dentry.
- * @old_dentry: dentry of an object to be renamed.
- * @new_dir: a pointer to the parent dentry where the object should be
- * moved. This should be a directory dentry.
- * @new_name: a pointer to a string containing the target name.
+ * debugfs_change_name - rename a file/directory in the debugfs filesystem
+ * @dentry: dentry of an object to be renamed.
+ * @fmt: format for new name
*
* This function renames a file/directory in debugfs. The target must not
* exist for rename to succeed.
*
- * This function will return a pointer to old_dentry (which is updated to
- * reflect renaming) if it succeeds. If an error occurs, ERR_PTR(-ERROR)
- * will be returned.
+ * This function will return 0 on success and -E... on failure.
*
* If debugfs is not enabled in the kernel, the value -%ENODEV will be
* returned.
*/
-struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
- struct dentry *new_dir, const char *new_name)
+int __printf(2, 3) debugfs_change_name(struct dentry *dentry, const char *fmt, ...)
{
- int error;
- struct dentry *dentry = NULL, *trap;
+ int error = 0;
+ const char *new_name;
struct name_snapshot old_name;
+ struct dentry *parent, *target;
+ struct inode *dir;
+ va_list ap;
- if (IS_ERR(old_dir))
- return old_dir;
- if (IS_ERR(new_dir))
- return new_dir;
- if (IS_ERR_OR_NULL(old_dentry))
- return old_dentry;
-
- trap = lock_rename(new_dir, old_dir);
- /* Source or destination directories don't exist? */
- if (d_really_is_negative(old_dir) || d_really_is_negative(new_dir))
- goto exit;
- /* Source does not exist, cyclic rename, or mountpoint? */
- if (d_really_is_negative(old_dentry) || old_dentry == trap ||
- d_mountpoint(old_dentry))
- goto exit;
- dentry = lookup_one_len(new_name, new_dir, strlen(new_name));
- /* Lookup failed, cyclic rename or target exists? */
- if (IS_ERR(dentry) || dentry == trap || d_really_is_positive(dentry))
- goto exit;
-
- take_dentry_name_snapshot(&old_name, old_dentry);
-
- error = simple_rename(&nop_mnt_idmap, d_inode(old_dir), old_dentry,
- d_inode(new_dir), dentry, 0);
- if (error) {
- release_dentry_name_snapshot(&old_name);
- goto exit;
+ if (IS_ERR_OR_NULL(dentry))
+ return 0;
+
+ va_start(ap, fmt);
+ new_name = kvasprintf_const(GFP_KERNEL, fmt, ap);
+ va_end(ap);
+ if (!new_name)
+ return -ENOMEM;
+
+ parent = dget_parent(dentry);
+ dir = d_inode(parent);
+ inode_lock(dir);
+
+ take_dentry_name_snapshot(&old_name, dentry);
+
+ if (WARN_ON_ONCE(dentry->d_parent != parent)) {
+ error = -EINVAL;
+ goto out;
+ }
+ if (strcmp(old_name.name.name, new_name) == 0)
+ goto out;
+ target = lookup_one_len(new_name, parent, strlen(new_name));
+ if (IS_ERR(target)) {
+ error = PTR_ERR(target);
+ goto out;
}
- d_move(old_dentry, dentry);
- fsnotify_move(d_inode(old_dir), d_inode(new_dir), &old_name.name,
- d_is_dir(old_dentry),
- NULL, old_dentry);
+ if (d_really_is_positive(target)) {
+ dput(target);
+ error = -EINVAL;
+ goto out;
+ }
+ simple_rename_timestamp(dir, dentry, dir, target);
+ d_move(dentry, target);
+ dput(target);
+ fsnotify_move(dir, dir, &old_name.name, d_is_dir(dentry), NULL, dentry);
+out:
release_dentry_name_snapshot(&old_name);
- unlock_rename(new_dir, old_dir);
- dput(dentry);
- return old_dentry;
-exit:
- if (dentry && !IS_ERR(dentry))
- dput(dentry);
- unlock_rename(new_dir, old_dir);
- if (IS_ERR(dentry))
- return dentry;
- return ERR_PTR(-EINVAL);
+ inode_unlock(dir);
+ dput(parent);
+ kfree_const(new_name);
+ return error;
}
-EXPORT_SYMBOL_GPL(debugfs_rename);
+EXPORT_SYMBOL_GPL(debugfs_change_name);
/**
* debugfs_initialized - Tells whether debugfs has been registered
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h
index 7c97417d73b5..9ad00d8b6f89 100644
--- a/include/linux/debugfs.h
+++ b/include/linux/debugfs.h
@@ -175,8 +175,7 @@ ssize_t debugfs_attr_write(struct file *file, const char __user *buf,
ssize_t debugfs_attr_write_signed(struct file *file, const char __user *buf,
size_t len, loff_t *ppos);
-struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
- struct dentry *new_dir, const char *new_name);
+int debugfs_change_name(struct dentry *dentry, const char *fmt, ...) __printf(2, 3);
void debugfs_create_u8(const char *name, umode_t mode, struct dentry *parent,
u8 *value);
@@ -361,10 +360,10 @@ static inline ssize_t debugfs_attr_write_signed(struct file *file,
return -ENODEV;
}
-static inline struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
- struct dentry *new_dir, char *new_name)
+static inline int __printf(2, 3) debugfs_change_name(struct dentry *dentry,
+ const char *fmt, ...)
{
- return ERR_PTR(-ENODEV);
+ return -ENODEV;
}
static inline void debugfs_create_u8(const char *name, umode_t mode,
diff --git a/mm/shrinker_debug.c b/mm/shrinker_debug.c
index 4a85b94d12ce..794bd433cce0 100644
--- a/mm/shrinker_debug.c
+++ b/mm/shrinker_debug.c
@@ -195,8 +195,6 @@ int shrinker_debugfs_add(struct shrinker *shrinker)
int shrinker_debugfs_rename(struct shrinker *shrinker, const char *fmt, ...)
{
- struct dentry *entry;
- char buf[128];
const char *new, *old;
va_list ap;
int ret = 0;
@@ -213,18 +211,8 @@ int shrinker_debugfs_rename(struct shrinker *shrinker, const char *fmt, ...)
old = shrinker->name;
shrinker->name = new;
- if (shrinker->debugfs_entry) {
- snprintf(buf, sizeof(buf), "%s-%d", shrinker->name,
- shrinker->debugfs_id);
-
- entry = debugfs_rename(shrinker_debugfs_root,
- shrinker->debugfs_entry,
- shrinker_debugfs_root, buf);
- if (IS_ERR(entry))
- ret = PTR_ERR(entry);
- else
- shrinker->debugfs_entry = entry;
- }
+ ret = debugfs_change_name(shrinker->debugfs_entry, "%s-%d",
+ shrinker->name, shrinker->debugfs_id);
mutex_unlock(&shrinker_mutex);
diff --git a/net/hsr/hsr_debugfs.c b/net/hsr/hsr_debugfs.c
index 1a195efc79cd..5b2cfac3b2ba 100644
--- a/net/hsr/hsr_debugfs.c
+++ b/net/hsr/hsr_debugfs.c
@@ -57,14 +57,11 @@ DEFINE_SHOW_ATTRIBUTE(hsr_node_table);
void hsr_debugfs_rename(struct net_device *dev)
{
struct hsr_priv *priv = netdev_priv(dev);
- struct dentry *d;
+ int err;
- d = debugfs_rename(hsr_debugfs_root_dir, priv->node_tbl_root,
- hsr_debugfs_root_dir, dev->name);
- if (IS_ERR(d))
+ err = debugfs_change_name(priv->node_tbl_root, "%s", dev->name);
+ if (err)
netdev_warn(dev, "failed to rename\n");
- else
- priv->node_tbl_root = d;
}
/* hsr_debugfs_init - create hsr node_table file for dumping
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index a9bc2fd59f55..9fa38c489edc 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -1025,16 +1025,7 @@ void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata)
void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata)
{
- struct dentry *dir;
- char buf[10 + IFNAMSIZ];
-
- dir = sdata->vif.debugfs_dir;
-
- if (IS_ERR_OR_NULL(dir))
- return;
-
- sprintf(buf, "netdev:%s", sdata->name);
- debugfs_rename(dir->d_parent, dir, dir->d_parent, buf);
+ debugfs_change_name(sdata->vif.debugfs_dir, "netdev:%s", sdata->name);
}
void ieee80211_debugfs_recreate_netdev(struct ieee80211_sub_if_data *sdata,
diff --git a/net/wireless/core.c b/net/wireless/core.c
index afbdc549fb4a..9130cb872ed3 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -143,10 +143,7 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
if (result)
return result;
- if (!IS_ERR_OR_NULL(rdev->wiphy.debugfsdir))
- debugfs_rename(rdev->wiphy.debugfsdir->d_parent,
- rdev->wiphy.debugfsdir,
- rdev->wiphy.debugfsdir->d_parent, newname);
+ debugfs_change_name(rdev->wiphy.debugfsdir, "%s", newname);
nl80211_notify_wiphy(rdev, NL80211_CMD_NEW_WIPHY);
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* Re: [PATCH 20/20] saner replacement for debugfs_rename()
2024-12-29 8:12 ` [PATCH 20/20] saner replacement for debugfs_rename() Al Viro
@ 2024-12-29 16:38 ` Al Viro
0 siblings, 0 replies; 53+ messages in thread
From: Al Viro @ 2024-12-29 16:38 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
On Sun, Dec 29, 2024 at 08:12:23AM +0000, Al Viro wrote:
> diff --git a/drivers/net/bonding/bond_debugfs.c b/drivers/net/bonding/bond_debugfs.c
> index b19492a7f6ad..2b78be129770 100644
> --- a/drivers/net/bonding/bond_debugfs.c
> +++ b/drivers/net/bonding/bond_debugfs.c
> @@ -63,13 +63,8 @@ void bond_debug_unregister(struct bonding *bond)
>
> void bond_debug_reregister(struct bonding *bond)
> {
> - struct dentry *d;
> -
> - d = debugfs_rename(bonding_debug_root, bond->debug_dir,
> - bonding_debug_root, bond->dev->name);
> - if (!IS_ERR(d)) {
> - bond->debug_dir = d;
> - } else {
> + err = debugfs_change_name(bond->debug_dir, "%s", bond->dev->name);
That should be
+ int err = debugfs_change_name(bond->debug_dir, "%s", bond->dev->name);
obviously...
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCHES][RFC][CFT] debugfs cleanups
2024-12-29 8:09 [PATCHES][RFC][CFT] debugfs cleanups Al Viro
2024-12-29 8:12 ` [PATCH 01/20] debugfs: fix missing mutex_destroy() in short_fops case Al Viro
@ 2024-12-29 20:58 ` Al Viro
2025-01-07 14:56 ` Greg KH
2025-01-12 8:05 ` [PATCHES v2][RFC][CFT] " Al Viro
2 siblings, 1 reply; 53+ messages in thread
From: Al Viro @ 2024-12-29 20:58 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
On Sun, Dec 29, 2024 at 08:09:48AM +0000, Al Viro wrote:
> All of that could be avoided if we augmented debugfs inodes with
> a couple of pointers - no more stashing crap in ->d_fsdata, etc.
> And it's really not hard to do. The series below attempts to untangle
> that mess; it can be found in
> git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs.git #work.debugfs
>
> It's very lightly tested; review and more testing would be
> very welcome.
BTW, looking through debugfs-related stuff...
arch/x86/kernel/cpu/resctrl/pseudo_lock.c:pseudo_lock_measure_trigger()
debugfs_file_get()/debugfs_file_put() pair inside, even though the
only use of that sucker is ->write() of file_operations fed
to debugfs_create_file(). In other words, it's going to be
called only by full_proxy_write(), which already has such a pair
around that...
drivers/base/regmap/regmap-debugfs.c:regmap_cache_{only,bypass}_write_file()
ditto
drivers/gpu/drm/xlnx/zynqmp_dp.c:zynqmp_dp_{pattern,custom}_write()
ditto
drivers/gpu/drm/xlnx/zynqmp_dp.c:zynqmp_dp_{pattern,custom}_read()
similar, except that it's ->read() rather than ->write()
drivers/infiniband/hw/hfi1/debugfs.c:hfi1_seq_read()
ditto, AFAICS. Verifying that is not pleasant (use of ## in
that forest of macros is seriously grep-hostile), but...
drivers/infiniband/hw/hfi1/debugfs.c:hfi1_seq_lseek()
same story for ->llseek()
drivers/infiniband/hw/hfi1/fault.c:fault_opcodes_{read,write}()
same story
drivers/thermal/testing/command.c:tt_command_write()
same, but debugfs_file_put() is apparently lost.
Attempt to rmmod that sucker ought to deadlock if there had
been a call of that...
sound/soc/sof/ipc4-mtrace.c:sof_ipc4_mtrace_dfs_open()
->open() calling debugfs_file_get(), with matching debugfs_file_put()
only in ->release(). Again, that's debugfs_create_file() fodder -
with nothing to trigger removal in sight. Fortunately, since had
that been triggerable from userland, you could get a nice deadlock
by opening that file and triggering removal...
sound/soc/sof/sof-client-ipc-flood-test.c:sof_ipc_flood_dfs_open()
same, except that here removal *is* triggerable. Do rmmod with
e.g. stdin redirected from that file and you are screwed.
sound/soc/sof/sof-client-ipc-kernel-injector.c:sof_msg_inject_dfs_open()
same, complete with deadlock on rmmod...
sound/soc/sof/sof-client-ipc-msg-injector.c:sof_msg_inject_dfs_open()
... and here as well.
As far as I can see, there's not a single legitimate caller of
debugfs_file_{get,put}() outside of fs/debugfs/file.c. Is there any
reason to keep that stuff non-static, let alone exported?
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCHES][RFC][CFT] debugfs cleanups
2024-12-29 20:58 ` [PATCHES][RFC][CFT] debugfs cleanups Al Viro
@ 2025-01-07 14:56 ` Greg KH
0 siblings, 0 replies; 53+ messages in thread
From: Greg KH @ 2025-01-07 14:56 UTC (permalink / raw)
To: Al Viro; +Cc: linux-fsdevel
On Sun, Dec 29, 2024 at 08:58:28PM +0000, Al Viro wrote:
> On Sun, Dec 29, 2024 at 08:09:48AM +0000, Al Viro wrote:
>
> > All of that could be avoided if we augmented debugfs inodes with
> > a couple of pointers - no more stashing crap in ->d_fsdata, etc.
> > And it's really not hard to do. The series below attempts to untangle
> > that mess; it can be found in
> > git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs.git #work.debugfs
> >
> > It's very lightly tested; review and more testing would be
> > very welcome.
>
> BTW, looking through debugfs-related stuff...
>
> arch/x86/kernel/cpu/resctrl/pseudo_lock.c:pseudo_lock_measure_trigger()
> debugfs_file_get()/debugfs_file_put() pair inside, even though the
> only use of that sucker is ->write() of file_operations fed
> to debugfs_create_file(). In other words, it's going to be
> called only by full_proxy_write(), which already has such a pair
> around that...
> drivers/base/regmap/regmap-debugfs.c:regmap_cache_{only,bypass}_write_file()
> ditto
> drivers/gpu/drm/xlnx/zynqmp_dp.c:zynqmp_dp_{pattern,custom}_write()
> ditto
> drivers/gpu/drm/xlnx/zynqmp_dp.c:zynqmp_dp_{pattern,custom}_read()
> similar, except that it's ->read() rather than ->write()
> drivers/infiniband/hw/hfi1/debugfs.c:hfi1_seq_read()
> ditto, AFAICS. Verifying that is not pleasant (use of ## in
> that forest of macros is seriously grep-hostile), but...
> drivers/infiniband/hw/hfi1/debugfs.c:hfi1_seq_lseek()
> same story for ->llseek()
> drivers/infiniband/hw/hfi1/fault.c:fault_opcodes_{read,write}()
> same story
> drivers/thermal/testing/command.c:tt_command_write()
> same, but debugfs_file_put() is apparently lost.
> Attempt to rmmod that sucker ought to deadlock if there had
> been a call of that...
> sound/soc/sof/ipc4-mtrace.c:sof_ipc4_mtrace_dfs_open()
> ->open() calling debugfs_file_get(), with matching debugfs_file_put()
> only in ->release(). Again, that's debugfs_create_file() fodder -
> with nothing to trigger removal in sight. Fortunately, since had
> that been triggerable from userland, you could get a nice deadlock
> by opening that file and triggering removal...
> sound/soc/sof/sof-client-ipc-flood-test.c:sof_ipc_flood_dfs_open()
> same, except that here removal *is* triggerable. Do rmmod with
> e.g. stdin redirected from that file and you are screwed.
> sound/soc/sof/sof-client-ipc-kernel-injector.c:sof_msg_inject_dfs_open()
> same, complete with deadlock on rmmod...
> sound/soc/sof/sof-client-ipc-msg-injector.c:sof_msg_inject_dfs_open()
> ... and here as well.
>
>
> As far as I can see, there's not a single legitimate caller of
> debugfs_file_{get,put}() outside of fs/debugfs/file.c. Is there any
> reason to keep that stuff non-static, let alone exported?
Nope, not at all!
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH 01/20] debugfs: fix missing mutex_destroy() in short_fops case
2024-12-29 8:12 ` [PATCH 01/20] debugfs: fix missing mutex_destroy() in short_fops case Al Viro
` (18 preceding siblings ...)
2024-12-29 8:12 ` [PATCH 20/20] saner replacement for debugfs_rename() Al Viro
@ 2025-01-07 15:20 ` Greg KH
19 siblings, 0 replies; 53+ messages in thread
From: Greg KH @ 2025-01-07 15:20 UTC (permalink / raw)
To: Al Viro; +Cc: linux-fsdevel
On Sun, Dec 29, 2024 at 08:12:04AM +0000, Al Viro wrote:
> we need that in ->real_fops == NULL, ->short_fops != NULL case
>
> Fixes: 8dc6d81c6b2a "debugfs: add small file operations for most files"
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
> fs/debugfs/inode.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
> index 38a9c7eb97e6..c99a0599c811 100644
> --- a/fs/debugfs/inode.c
> +++ b/fs/debugfs/inode.c
> @@ -229,7 +229,7 @@ static void debugfs_release_dentry(struct dentry *dentry)
> return;
>
> /* check it wasn't a dir (no fsdata) or automount (no real_fops) */
> - if (fsd && fsd->real_fops) {
> + if (fsd && (fsd->real_fops || fsd->short_fops)) {
> WARN_ON(!list_empty(&fsd->cancellations));
> mutex_destroy(&fsd->cancellations_mtx);
> }
> --
> 2.39.5
>
I've taken this one now as it fixes an issue in -rc1.
thanks,
greg k-h
^ permalink raw reply [flat|nested] 53+ messages in thread
* [PATCHES v2][RFC][CFT] debugfs cleanups
2024-12-29 8:09 [PATCHES][RFC][CFT] debugfs cleanups Al Viro
2024-12-29 8:12 ` [PATCH 01/20] debugfs: fix missing mutex_destroy() in short_fops case Al Viro
2024-12-29 20:58 ` [PATCHES][RFC][CFT] debugfs cleanups Al Viro
@ 2025-01-12 8:05 ` Al Viro
2025-01-12 8:06 ` [PATCH v2 01/21] debugfs: separate cache for debugfs inodes Al Viro
2 siblings, 1 reply; 53+ messages in thread
From: Al Viro @ 2025-01-12 8:05 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
On Sun, Dec 29, 2024 at 08:09:48AM +0000, Al Viro wrote:
> All of that could be avoided if we augmented debugfs inodes with
> a couple of pointers - no more stashing crap in ->d_fsdata, etc.
> And it's really not hard to do. The series below attempts to untangle
> that mess; it can be found in
> git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs.git #work.debugfs
Rebased on top of
git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git driver-core-linus
and force-pushed into the same branch.
Changes since v1:
* "debugfs: fix missing mutex_destroy() in short_fops case" dropped - already
merged.
* struct debugfs_short_fops made available without CONFIG_DEBUG_FS (fixes
build breakage on !DEBUG_FS builds)
* orangefs-debugfs converted to debugfs_create_file_aux_num() (accidentally
missed in the original series)
Shortlog:
Al Viro (21):
debugfs: separate cache for debugfs inodes
debugfs: move ->automount into debugfs_inode_info
debugfs: get rid of dynamically allocation proxy_ops
debugfs: don't mess with bits in ->d_fsdata
debugfs: allow to store an additional opaque pointer at file creation
debugfs: take debugfs_short_fops definition out of ifdef
carl9170: stop embedding file_operations into their objects
b43: stop embedding struct file_operations into their objects
b43legacy: make use of debugfs_get_aux()
netdevsim: don't embed file_operations into your structs
mediatek: stop messing with ->d_iname
[not even compile-tested] greybus/camera - stop messing with ->d_iname
mtu3: don't mess wiht ->d_iname
xhci: don't mess with ->d_iname
qat: don't mess with ->d_name
sof-client-ipc-flood-test: don't mess with ->d_name
slub: don't mess with ->d_name
arm_scmi: don't mess with ->d_parent->d_name
octeontx2: don't mess with ->d_parent or ->d_parent->d_name
orangefs-debugfs: don't mess with ->d_name
saner replacement for debugfs_rename()
Diffstat:
Documentation/filesystems/debugfs.rst | 12 +-
.../crypto/intel/qat/qat_common/adf_tl_debugfs.c | 36 +---
drivers/firmware/arm_scmi/raw_mode.c | 12 +-
drivers/net/bonding/bond_debugfs.c | 9 +-
drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c | 19 +-
.../ethernet/marvell/octeontx2/af/rvu_debugfs.c | 76 +++-----
drivers/net/ethernet/marvell/skge.c | 5 +-
drivers/net/ethernet/marvell/sky2.c | 5 +-
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 6 +-
drivers/net/netdevsim/hwstats.c | 29 ++-
drivers/net/wireless/ath/carl9170/debug.c | 28 ++-
drivers/net/wireless/broadcom/b43/debugfs.c | 27 ++-
drivers/net/wireless/broadcom/b43legacy/debugfs.c | 26 ++-
drivers/opp/debugfs.c | 10 +-
drivers/phy/mediatek/phy-mtk-tphy.c | 40 +---
drivers/staging/greybus/camera.c | 17 +-
drivers/usb/host/xhci-debugfs.c | 25 +--
drivers/usb/mtu3/mtu3_debugfs.c | 40 +---
fs/debugfs/file.c | 165 ++++++++--------
fs/debugfs/inode.c | 208 ++++++++++-----------
fs/debugfs/internal.h | 50 +++--
fs/orangefs/orangefs-debugfs.c | 16 +-
include/linux/debugfs.h | 44 ++++-
mm/shrinker_debug.c | 16 +-
mm/slub.c | 13 +-
net/hsr/hsr_debugfs.c | 9 +-
net/mac80211/debugfs_netdev.c | 11 +-
net/wireless/core.c | 5 +-
sound/soc/sof/sof-client-ipc-flood-test.c | 39 ++--
29 files changed, 402 insertions(+), 596 deletions(-)
Individual patches in followups.
^ permalink raw reply [flat|nested] 53+ messages in thread
* [PATCH v2 01/21] debugfs: separate cache for debugfs inodes
2025-01-12 8:05 ` [PATCHES v2][RFC][CFT] " Al Viro
@ 2025-01-12 8:06 ` Al Viro
2025-01-12 8:06 ` [PATCH v2 02/21] debugfs: move ->automount into debugfs_inode_info Al Viro
` (20 more replies)
0 siblings, 21 replies; 53+ messages in thread
From: Al Viro @ 2025-01-12 8:06 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
Embed them into container (struct debugfs_inode_info, with nothing
else in it at the moment), set the cache up, etc.
Just the infrastructure changes letting us augment debugfs inodes
here; adding stuff will come at the next step.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/debugfs/inode.c | 40 ++++++++++++++++++++++++++++++++++------
fs/debugfs/internal.h | 9 +++++++++
2 files changed, 43 insertions(+), 6 deletions(-)
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index e752009de929..5d423bd92f93 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -208,16 +208,34 @@ static int debugfs_show_options(struct seq_file *m, struct dentry *root)
return 0;
}
+static struct kmem_cache *debugfs_inode_cachep __ro_after_init;
+
+static void init_once(void *foo)
+{
+ struct debugfs_inode_info *info = foo;
+ inode_init_once(&info->vfs_inode);
+}
+
+static struct inode *debugfs_alloc_inode(struct super_block *sb)
+{
+ struct debugfs_inode_info *info;
+ info = alloc_inode_sb(sb, debugfs_inode_cachep, GFP_KERNEL);
+ if (!info)
+ return NULL;
+ return &info->vfs_inode;
+}
+
static void debugfs_free_inode(struct inode *inode)
{
if (S_ISLNK(inode->i_mode))
kfree(inode->i_link);
- free_inode_nonrcu(inode);
+ kmem_cache_free(debugfs_inode_cachep, DEBUGFS_I(inode));
}
static const struct super_operations debugfs_super_operations = {
.statfs = simple_statfs,
.show_options = debugfs_show_options,
+ .alloc_inode = debugfs_alloc_inode,
.free_inode = debugfs_free_inode,
};
@@ -939,12 +957,22 @@ static int __init debugfs_init(void)
if (retval)
return retval;
- retval = register_filesystem(&debug_fs_type);
- if (retval)
+ debugfs_inode_cachep = kmem_cache_create("debugfs_inode_cache",
+ sizeof(struct debugfs_inode_info), 0,
+ SLAB_RECLAIM_ACCOUNT | SLAB_ACCOUNT,
+ init_once);
+ if (debugfs_inode_cachep == NULL) {
sysfs_remove_mount_point(kernel_kobj, "debug");
- else
- debugfs_registered = true;
+ return -ENOMEM;
+ }
- return retval;
+ retval = register_filesystem(&debug_fs_type);
+ if (retval) { // Really not going to happen
+ sysfs_remove_mount_point(kernel_kobj, "debug");
+ kmem_cache_destroy(debugfs_inode_cachep);
+ return retval;
+ }
+ debugfs_registered = true;
+ return 0;
}
core_initcall(debugfs_init);
diff --git a/fs/debugfs/internal.h b/fs/debugfs/internal.h
index bbae4a228ef4..5cb940b0b8f6 100644
--- a/fs/debugfs/internal.h
+++ b/fs/debugfs/internal.h
@@ -11,6 +11,15 @@
struct file_operations;
+struct debugfs_inode_info {
+ struct inode vfs_inode;
+};
+
+static inline struct debugfs_inode_info *DEBUGFS_I(struct inode *inode)
+{
+ return container_of(inode, struct debugfs_inode_info, vfs_inode);
+}
+
/* declared over in file.c */
extern const struct file_operations debugfs_noop_file_operations;
extern const struct file_operations debugfs_open_proxy_file_operations;
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH v2 02/21] debugfs: move ->automount into debugfs_inode_info
2025-01-12 8:06 ` [PATCH v2 01/21] debugfs: separate cache for debugfs inodes Al Viro
@ 2025-01-12 8:06 ` Al Viro
2025-01-13 14:49 ` Christian Brauner
2025-01-12 8:06 ` [PATCH v2 03/21] debugfs: get rid of dynamically allocation proxy_ops Al Viro
` (19 subsequent siblings)
20 siblings, 1 reply; 53+ messages in thread
From: Al Viro @ 2025-01-12 8:06 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
... and don't bother with debugfs_fsdata for those. Life's
simpler that way...
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/debugfs/inode.c | 21 +++++----------------
fs/debugfs/internal.h | 19 +++++++++----------
2 files changed, 14 insertions(+), 26 deletions(-)
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index 5d423bd92f93..2f5afd7b1b94 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -246,8 +246,8 @@ static void debugfs_release_dentry(struct dentry *dentry)
if ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)
return;
- /* check it wasn't a dir (no fsdata) or automount (no real_fops) */
- if (fsd && (fsd->real_fops || fsd->short_fops)) {
+ /* check it wasn't a dir or automount (no fsdata) */
+ if (fsd) {
WARN_ON(!list_empty(&fsd->cancellations));
mutex_destroy(&fsd->cancellations_mtx);
}
@@ -257,9 +257,9 @@ static void debugfs_release_dentry(struct dentry *dentry)
static struct vfsmount *debugfs_automount(struct path *path)
{
- struct debugfs_fsdata *fsd = path->dentry->d_fsdata;
+ struct inode *inode = path->dentry->d_inode;
- return fsd->automount(path->dentry, d_inode(path->dentry)->i_private);
+ return DEBUGFS_I(inode)->automount(path->dentry, inode->i_private);
}
static const struct dentry_operations debugfs_dops = {
@@ -642,23 +642,13 @@ struct dentry *debugfs_create_automount(const char *name,
void *data)
{
struct dentry *dentry = start_creating(name, parent);
- struct debugfs_fsdata *fsd;
struct inode *inode;
if (IS_ERR(dentry))
return dentry;
- fsd = kzalloc(sizeof(*fsd), GFP_KERNEL);
- if (!fsd) {
- failed_creating(dentry);
- return ERR_PTR(-ENOMEM);
- }
-
- fsd->automount = f;
-
if (!(debugfs_allow & DEBUGFS_ALLOW_API)) {
failed_creating(dentry);
- kfree(fsd);
return ERR_PTR(-EPERM);
}
@@ -666,14 +656,13 @@ struct dentry *debugfs_create_automount(const char *name,
if (unlikely(!inode)) {
pr_err("out of free dentries, can not create automount '%s'\n",
name);
- kfree(fsd);
return failed_creating(dentry);
}
make_empty_dir_inode(inode);
inode->i_flags |= S_AUTOMOUNT;
inode->i_private = data;
- dentry->d_fsdata = fsd;
+ DEBUGFS_I(inode)->automount = f;
/* directory inodes start off with i_nlink == 2 (for "." entry) */
inc_nlink(inode);
d_instantiate(dentry, inode);
diff --git a/fs/debugfs/internal.h b/fs/debugfs/internal.h
index 5cb940b0b8f6..a644e44a0ee4 100644
--- a/fs/debugfs/internal.h
+++ b/fs/debugfs/internal.h
@@ -13,6 +13,9 @@ struct file_operations;
struct debugfs_inode_info {
struct inode vfs_inode;
+ union {
+ debugfs_automount_t automount;
+ };
};
static inline struct debugfs_inode_info *DEBUGFS_I(struct inode *inode)
@@ -29,17 +32,13 @@ extern const struct file_operations debugfs_full_short_proxy_file_operations;
struct debugfs_fsdata {
const struct file_operations *real_fops;
const struct debugfs_short_fops *short_fops;
- union {
- /* automount_fn is used when real_fops is NULL */
- debugfs_automount_t automount;
- struct {
- refcount_t active_users;
- struct completion active_users_drained;
+ struct {
+ refcount_t active_users;
+ struct completion active_users_drained;
- /* protect cancellations */
- struct mutex cancellations_mtx;
- struct list_head cancellations;
- };
+ /* protect cancellations */
+ struct mutex cancellations_mtx;
+ struct list_head cancellations;
};
};
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH v2 03/21] debugfs: get rid of dynamically allocation proxy_ops
2025-01-12 8:06 ` [PATCH v2 01/21] debugfs: separate cache for debugfs inodes Al Viro
2025-01-12 8:06 ` [PATCH v2 02/21] debugfs: move ->automount into debugfs_inode_info Al Viro
@ 2025-01-12 8:06 ` Al Viro
2025-01-13 14:51 ` Christian Brauner
2025-01-12 8:06 ` [PATCH v2 04/21] debugfs: don't mess with bits in ->d_fsdata Al Viro
` (18 subsequent siblings)
20 siblings, 1 reply; 53+ messages in thread
From: Al Viro @ 2025-01-12 8:06 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
All it takes is having full_proxy_open() collect the information
about available methods and store it in debugfs_fsdata.
Wrappers are called only after full_proxy_open() has succeeded
calling debugfs_get_file(), so they are guaranteed to have
->d_fsdata already pointing to debugfs_fsdata.
As the result, they can check if method is absent and bugger off
early, without any atomic operations, etc. - same effect as what
we'd have from NULL method. Which makes the entire proxy_fops
contents unconditional, making it completely pointless - we can
just put those methods (unconditionally) into
debugfs_full_proxy_file_operations and forget about dynamic
allocation, replace_fops, etc.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/debugfs/file.c | 113 +++++++++++++++++++-----------------------
fs/debugfs/internal.h | 9 ++++
2 files changed, 61 insertions(+), 61 deletions(-)
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index 16e198a26339..eb59b01f5f25 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -95,13 +95,31 @@ static int __debugfs_file_get(struct dentry *dentry, enum dbgfs_get_mode mode)
return -ENOMEM;
if (mode == DBGFS_GET_SHORT) {
- fsd->real_fops = NULL;
- fsd->short_fops = (void *)((unsigned long)d_fsd &
- ~DEBUGFS_FSDATA_IS_REAL_FOPS_BIT);
+ const struct debugfs_short_fops *ops;
+ ops = (void *)((unsigned long)d_fsd &
+ ~DEBUGFS_FSDATA_IS_REAL_FOPS_BIT);
+ fsd->short_fops = ops;
+ if (ops->llseek)
+ fsd->methods |= HAS_LSEEK;
+ if (ops->read)
+ fsd->methods |= HAS_READ;
+ if (ops->write)
+ fsd->methods |= HAS_WRITE;
} else {
- fsd->real_fops = (void *)((unsigned long)d_fsd &
- ~DEBUGFS_FSDATA_IS_REAL_FOPS_BIT);
- fsd->short_fops = NULL;
+ const struct file_operations *ops;
+ ops = (void *)((unsigned long)d_fsd &
+ ~DEBUGFS_FSDATA_IS_REAL_FOPS_BIT);
+ fsd->real_fops = ops;
+ if (ops->llseek)
+ fsd->methods |= HAS_LSEEK;
+ if (ops->read)
+ fsd->methods |= HAS_READ;
+ if (ops->write)
+ fsd->methods |= HAS_WRITE;
+ if (ops->unlocked_ioctl)
+ fsd->methods |= HAS_IOCTL;
+ if (ops->poll)
+ fsd->methods |= HAS_POLL;
}
refcount_set(&fsd->active_users, 1);
init_completion(&fsd->active_users_drained);
@@ -322,13 +340,16 @@ const struct file_operations debugfs_open_proxy_file_operations = {
#define PROTO(args...) args
#define ARGS(args...) args
-#define FULL_PROXY_FUNC(name, ret_type, filp, proto, args) \
+#define FULL_PROXY_FUNC(name, ret_type, filp, proto, args, bit, ret) \
static ret_type full_proxy_ ## name(proto) \
{ \
- struct dentry *dentry = F_DENTRY(filp); \
+ struct dentry *dentry = F_DENTRY(filp); \
+ struct debugfs_fsdata *fsd = dentry->d_fsdata; \
const struct file_operations *real_fops; \
ret_type r; \
\
+ if (!(fsd->methods & bit)) \
+ return ret; \
r = debugfs_file_get(dentry); \
if (unlikely(r)) \
return r; \
@@ -338,17 +359,18 @@ static ret_type full_proxy_ ## name(proto) \
return r; \
}
-#define FULL_PROXY_FUNC_BOTH(name, ret_type, filp, proto, args) \
+#define FULL_PROXY_FUNC_BOTH(name, ret_type, filp, proto, args, bit, ret) \
static ret_type full_proxy_ ## name(proto) \
{ \
struct dentry *dentry = F_DENTRY(filp); \
- struct debugfs_fsdata *fsd; \
+ struct debugfs_fsdata *fsd = dentry->d_fsdata; \
ret_type r; \
\
+ if (!(fsd->methods & bit)) \
+ return ret; \
r = debugfs_file_get(dentry); \
if (unlikely(r)) \
return r; \
- fsd = dentry->d_fsdata; \
if (fsd->real_fops) \
r = fsd->real_fops->name(args); \
else \
@@ -359,29 +381,32 @@ static ret_type full_proxy_ ## name(proto) \
FULL_PROXY_FUNC_BOTH(llseek, loff_t, filp,
PROTO(struct file *filp, loff_t offset, int whence),
- ARGS(filp, offset, whence));
+ ARGS(filp, offset, whence), HAS_LSEEK, -ESPIPE);
FULL_PROXY_FUNC_BOTH(read, ssize_t, filp,
PROTO(struct file *filp, char __user *buf, size_t size,
loff_t *ppos),
- ARGS(filp, buf, size, ppos));
+ ARGS(filp, buf, size, ppos), HAS_READ, -EINVAL);
FULL_PROXY_FUNC_BOTH(write, ssize_t, filp,
PROTO(struct file *filp, const char __user *buf,
size_t size, loff_t *ppos),
- ARGS(filp, buf, size, ppos));
+ ARGS(filp, buf, size, ppos), HAS_WRITE, -EINVAL);
FULL_PROXY_FUNC(unlocked_ioctl, long, filp,
PROTO(struct file *filp, unsigned int cmd, unsigned long arg),
- ARGS(filp, cmd, arg));
+ ARGS(filp, cmd, arg), HAS_IOCTL, -ENOTTY);
static __poll_t full_proxy_poll(struct file *filp,
struct poll_table_struct *wait)
{
struct dentry *dentry = F_DENTRY(filp);
+ struct debugfs_fsdata *fsd = dentry->d_fsdata;
__poll_t r = 0;
const struct file_operations *real_fops;
+ if (!(fsd->methods & HAS_POLL))
+ return DEFAULT_POLLMASK;
if (debugfs_file_get(dentry))
return EPOLLHUP;
@@ -393,9 +418,7 @@ static __poll_t 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 = debugfs_real_fops(filp);
- const struct file_operations *proxy_fops = filp->f_op;
int r = 0;
/*
@@ -407,42 +430,15 @@ static int full_proxy_release(struct inode *inode, struct file *filp)
if (real_fops && real_fops->release)
r = real_fops->release(inode, filp);
- replace_fops(filp, d_inode(dentry)->i_fop);
- kfree(proxy_fops);
fops_put(real_fops);
return r;
}
-static void __full_proxy_fops_init(struct file_operations *proxy_fops,
- struct debugfs_fsdata *fsd)
-{
- proxy_fops->release = full_proxy_release;
-
- if ((fsd->real_fops && fsd->real_fops->llseek) ||
- (fsd->short_fops && fsd->short_fops->llseek))
- proxy_fops->llseek = full_proxy_llseek;
-
- if ((fsd->real_fops && fsd->real_fops->read) ||
- (fsd->short_fops && fsd->short_fops->read))
- proxy_fops->read = full_proxy_read;
-
- if ((fsd->real_fops && fsd->real_fops->write) ||
- (fsd->short_fops && fsd->short_fops->write))
- proxy_fops->write = full_proxy_write;
-
- if (fsd->real_fops && fsd->real_fops->poll)
- proxy_fops->poll = full_proxy_poll;
-
- if (fsd->real_fops && fsd->real_fops->unlocked_ioctl)
- proxy_fops->unlocked_ioctl = full_proxy_unlocked_ioctl;
-}
-
static int full_proxy_open(struct inode *inode, struct file *filp,
enum dbgfs_get_mode mode)
{
struct dentry *dentry = F_DENTRY(filp);
const struct file_operations *real_fops;
- struct file_operations *proxy_fops = NULL;
struct debugfs_fsdata *fsd;
int r;
@@ -472,34 +468,20 @@ static int full_proxy_open(struct inode *inode, struct file *filp,
goto out;
}
- proxy_fops = kzalloc(sizeof(*proxy_fops), GFP_KERNEL);
- if (!proxy_fops) {
- r = -ENOMEM;
- goto free_proxy;
- }
- __full_proxy_fops_init(proxy_fops, fsd);
- replace_fops(filp, proxy_fops);
-
if (!real_fops || real_fops->open) {
if (real_fops)
r = real_fops->open(inode, filp);
else
r = simple_open(inode, filp);
if (r) {
- replace_fops(filp, d_inode(dentry)->i_fop);
- goto free_proxy;
- } else if (filp->f_op != proxy_fops) {
+ fops_put(real_fops);
+ } else if (filp->f_op != &debugfs_full_proxy_file_operations) {
/* No protection against file removal anymore. */
WARN(1, "debugfs file owner replaced proxy fops: %pd",
dentry);
- goto free_proxy;
+ fops_put(real_fops);
}
}
-
- goto out;
-free_proxy:
- kfree(proxy_fops);
- fops_put(real_fops);
out:
debugfs_file_put(dentry);
return r;
@@ -512,6 +494,12 @@ static int full_proxy_open_regular(struct inode *inode, struct file *filp)
const struct file_operations debugfs_full_proxy_file_operations = {
.open = full_proxy_open_regular,
+ .release = full_proxy_release,
+ .llseek = full_proxy_llseek,
+ .read = full_proxy_read,
+ .write = full_proxy_write,
+ .poll = full_proxy_poll,
+ .unlocked_ioctl = full_proxy_unlocked_ioctl
};
static int full_proxy_open_short(struct inode *inode, struct file *filp)
@@ -521,6 +509,9 @@ static int full_proxy_open_short(struct inode *inode, struct file *filp)
const struct file_operations debugfs_full_short_proxy_file_operations = {
.open = full_proxy_open_short,
+ .llseek = full_proxy_llseek,
+ .read = full_proxy_read,
+ .write = full_proxy_write,
};
ssize_t debugfs_attr_read(struct file *file, char __user *buf,
diff --git a/fs/debugfs/internal.h b/fs/debugfs/internal.h
index a644e44a0ee4..011ef8b1a99a 100644
--- a/fs/debugfs/internal.h
+++ b/fs/debugfs/internal.h
@@ -39,9 +39,18 @@ struct debugfs_fsdata {
/* protect cancellations */
struct mutex cancellations_mtx;
struct list_head cancellations;
+ unsigned int methods;
};
};
+enum {
+ HAS_READ = 1,
+ HAS_WRITE = 2,
+ HAS_LSEEK = 4,
+ HAS_POLL = 8,
+ HAS_IOCTL = 16
+};
+
/*
* A dentry's ->d_fsdata either points to the real fops or to a
* dynamically allocated debugfs_fsdata instance.
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH v2 04/21] debugfs: don't mess with bits in ->d_fsdata
2025-01-12 8:06 ` [PATCH v2 01/21] debugfs: separate cache for debugfs inodes Al Viro
2025-01-12 8:06 ` [PATCH v2 02/21] debugfs: move ->automount into debugfs_inode_info Al Viro
2025-01-12 8:06 ` [PATCH v2 03/21] debugfs: get rid of dynamically allocation proxy_ops Al Viro
@ 2025-01-12 8:06 ` Al Viro
2025-01-13 14:55 ` Christian Brauner
2025-01-12 8:06 ` [PATCH v2 05/21] debugfs: allow to store an additional opaque pointer at file creation Al Viro
` (17 subsequent siblings)
20 siblings, 1 reply; 53+ messages in thread
From: Al Viro @ 2025-01-12 8:06 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
The reason we need that crap is the dual use ->d_fsdata has there -
it's both holding a debugfs_fsdata reference after the first
debugfs_file_get() (actually, after the call of proxy ->open())
*and* it serves as a place to stash a reference to real file_operations
from object creation to the first open. Oh, and it's triple use,
actually - that stashed reference might be to debugfs_short_fops.
Bugger that for a game of solidiers - just put the operations
reference into debugfs-private augmentation of inode. And split
debugfs_full_file_operations into full and short cases, so that
debugfs_get_file() could tell one from another.
Voila - ->d_fsdata holds NULL until the first (successful) debugfs_get_file()
and a reference to struct debugfs_fsdata afterwards.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/debugfs/file.c | 58 +++++++++++++++++++++----------------------
fs/debugfs/inode.c | 29 ++++++----------------
fs/debugfs/internal.h | 12 +++------
3 files changed, 38 insertions(+), 61 deletions(-)
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index eb59b01f5f25..ae014bd36a6f 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -51,7 +51,7 @@ const struct file_operations *debugfs_real_fops(const struct file *filp)
{
struct debugfs_fsdata *fsd = F_DENTRY(filp)->d_fsdata;
- if ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT) {
+ if (!fsd) {
/*
* Urgh, we've been called w/o a protecting
* debugfs_file_get().
@@ -84,9 +84,11 @@ static int __debugfs_file_get(struct dentry *dentry, enum dbgfs_get_mode mode)
return -EINVAL;
d_fsd = READ_ONCE(dentry->d_fsdata);
- if (!((unsigned long)d_fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)) {
+ if (d_fsd) {
fsd = d_fsd;
} else {
+ struct inode *inode = dentry->d_inode;
+
if (WARN_ON(mode == DBGFS_GET_ALREADY))
return -EINVAL;
@@ -96,9 +98,7 @@ static int __debugfs_file_get(struct dentry *dentry, enum dbgfs_get_mode mode)
if (mode == DBGFS_GET_SHORT) {
const struct debugfs_short_fops *ops;
- ops = (void *)((unsigned long)d_fsd &
- ~DEBUGFS_FSDATA_IS_REAL_FOPS_BIT);
- fsd->short_fops = ops;
+ ops = fsd->short_fops = DEBUGFS_I(inode)->short_fops;
if (ops->llseek)
fsd->methods |= HAS_LSEEK;
if (ops->read)
@@ -107,9 +107,7 @@ static int __debugfs_file_get(struct dentry *dentry, enum dbgfs_get_mode mode)
fsd->methods |= HAS_WRITE;
} else {
const struct file_operations *ops;
- ops = (void *)((unsigned long)d_fsd &
- ~DEBUGFS_FSDATA_IS_REAL_FOPS_BIT);
- fsd->real_fops = ops;
+ ops = fsd->real_fops = DEBUGFS_I(inode)->real_fops;
if (ops->llseek)
fsd->methods |= HAS_LSEEK;
if (ops->read)
@@ -126,10 +124,11 @@ static int __debugfs_file_get(struct dentry *dentry, enum dbgfs_get_mode mode)
INIT_LIST_HEAD(&fsd->cancellations);
mutex_init(&fsd->cancellations_mtx);
- if (cmpxchg(&dentry->d_fsdata, d_fsd, fsd) != d_fsd) {
+ d_fsd = cmpxchg(&dentry->d_fsdata, NULL, fsd);
+ if (d_fsd) {
mutex_destroy(&fsd->cancellations_mtx);
kfree(fsd);
- fsd = READ_ONCE(dentry->d_fsdata);
+ fsd = d_fsd;
}
}
@@ -226,8 +225,7 @@ void debugfs_enter_cancellation(struct file *file,
return;
fsd = READ_ONCE(dentry->d_fsdata);
- if (WARN_ON(!fsd ||
- ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)))
+ if (WARN_ON(!fsd))
return;
mutex_lock(&fsd->cancellations_mtx);
@@ -258,8 +256,7 @@ void debugfs_leave_cancellation(struct file *file,
return;
fsd = READ_ONCE(dentry->d_fsdata);
- if (WARN_ON(!fsd ||
- ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)))
+ if (WARN_ON(!fsd))
return;
mutex_lock(&fsd->cancellations_mtx);
@@ -427,22 +424,21 @@ static int full_proxy_release(struct inode *inode, struct file *filp)
* not to leak any resources. Releasers must not assume that
* ->i_private is still being meaningful here.
*/
- if (real_fops && real_fops->release)
+ if (real_fops->release)
r = real_fops->release(inode, filp);
fops_put(real_fops);
return r;
}
-static int full_proxy_open(struct inode *inode, struct file *filp,
- enum dbgfs_get_mode mode)
+static int full_proxy_open_regular(struct inode *inode, struct file *filp)
{
struct dentry *dentry = F_DENTRY(filp);
const struct file_operations *real_fops;
struct debugfs_fsdata *fsd;
int r;
- r = __debugfs_file_get(dentry, mode);
+ r = __debugfs_file_get(dentry, DBGFS_GET_REGULAR);
if (r)
return r == -EIO ? -ENOENT : r;
@@ -452,7 +448,7 @@ static int full_proxy_open(struct inode *inode, struct file *filp,
if (r)
goto out;
- if (real_fops && !fops_get(real_fops)) {
+ if (!fops_get(real_fops)) {
#ifdef CONFIG_MODULES
if (real_fops->owner &&
real_fops->owner->state == MODULE_STATE_GOING) {
@@ -468,11 +464,8 @@ static int full_proxy_open(struct inode *inode, struct file *filp,
goto out;
}
- if (!real_fops || real_fops->open) {
- if (real_fops)
- r = real_fops->open(inode, filp);
- else
- r = simple_open(inode, filp);
+ if (real_fops->open) {
+ r = real_fops->open(inode, filp);
if (r) {
fops_put(real_fops);
} else if (filp->f_op != &debugfs_full_proxy_file_operations) {
@@ -487,11 +480,6 @@ static int full_proxy_open(struct inode *inode, struct file *filp,
return r;
}
-static int full_proxy_open_regular(struct inode *inode, struct file *filp)
-{
- return full_proxy_open(inode, filp, DBGFS_GET_REGULAR);
-}
-
const struct file_operations debugfs_full_proxy_file_operations = {
.open = full_proxy_open_regular,
.release = full_proxy_release,
@@ -504,7 +492,17 @@ const struct file_operations debugfs_full_proxy_file_operations = {
static int full_proxy_open_short(struct inode *inode, struct file *filp)
{
- return full_proxy_open(inode, filp, DBGFS_GET_SHORT);
+ struct dentry *dentry = F_DENTRY(filp);
+ int r;
+
+ r = __debugfs_file_get(dentry, DBGFS_GET_SHORT);
+ if (r)
+ return r == -EIO ? -ENOENT : r;
+ r = debugfs_locked_down(inode, filp, NULL);
+ if (!r)
+ r = simple_open(inode, filp);
+ debugfs_file_put(dentry);
+ return r;
}
const struct file_operations debugfs_full_short_proxy_file_operations = {
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index 2f5afd7b1b94..c4e8b7f758e0 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -243,15 +243,10 @@ static void debugfs_release_dentry(struct dentry *dentry)
{
struct debugfs_fsdata *fsd = dentry->d_fsdata;
- if ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)
- return;
-
- /* check it wasn't a dir or automount (no fsdata) */
if (fsd) {
WARN_ON(!list_empty(&fsd->cancellations));
mutex_destroy(&fsd->cancellations_mtx);
}
-
kfree(fsd);
}
@@ -459,9 +454,10 @@ static struct dentry *__debugfs_create_file(const char *name, umode_t mode,
inode->i_private = data;
inode->i_op = &debugfs_file_inode_operations;
+ if (!real_fops)
+ proxy_fops = &debugfs_noop_file_operations;
inode->i_fop = proxy_fops;
- dentry->d_fsdata = (void *)((unsigned long)real_fops |
- DEBUGFS_FSDATA_IS_REAL_FOPS_BIT);
+ DEBUGFS_I(inode)->raw = real_fops;
d_instantiate(dentry, inode);
fsnotify_create(d_inode(dentry->d_parent), dentry);
@@ -472,13 +468,8 @@ struct dentry *debugfs_create_file_full(const char *name, umode_t mode,
struct dentry *parent, void *data,
const struct file_operations *fops)
{
- if (WARN_ON((unsigned long)fops &
- DEBUGFS_FSDATA_IS_REAL_FOPS_BIT))
- return ERR_PTR(-EINVAL);
-
return __debugfs_create_file(name, mode, parent, data,
- fops ? &debugfs_full_proxy_file_operations :
- &debugfs_noop_file_operations,
+ &debugfs_full_proxy_file_operations,
fops);
}
EXPORT_SYMBOL_GPL(debugfs_create_file_full);
@@ -487,13 +478,8 @@ struct dentry *debugfs_create_file_short(const char *name, umode_t mode,
struct dentry *parent, void *data,
const struct debugfs_short_fops *fops)
{
- if (WARN_ON((unsigned long)fops &
- DEBUGFS_FSDATA_IS_REAL_FOPS_BIT))
- return ERR_PTR(-EINVAL);
-
return __debugfs_create_file(name, mode, parent, data,
- fops ? &debugfs_full_short_proxy_file_operations :
- &debugfs_noop_file_operations,
+ &debugfs_full_short_proxy_file_operations,
fops);
}
EXPORT_SYMBOL_GPL(debugfs_create_file_short);
@@ -531,8 +517,7 @@ struct dentry *debugfs_create_file_unsafe(const char *name, umode_t mode,
{
return __debugfs_create_file(name, mode, parent, data,
- fops ? &debugfs_open_proxy_file_operations :
- &debugfs_noop_file_operations,
+ &debugfs_open_proxy_file_operations,
fops);
}
EXPORT_SYMBOL_GPL(debugfs_create_file_unsafe);
@@ -737,7 +722,7 @@ static void __debugfs_file_removed(struct dentry *dentry)
*/
smp_mb();
fsd = READ_ONCE(dentry->d_fsdata);
- if ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)
+ if (!fsd)
return;
/* if this was the last reference, we're done */
diff --git a/fs/debugfs/internal.h b/fs/debugfs/internal.h
index 011ef8b1a99a..8d2de647b42c 100644
--- a/fs/debugfs/internal.h
+++ b/fs/debugfs/internal.h
@@ -14,6 +14,9 @@ struct file_operations;
struct debugfs_inode_info {
struct inode vfs_inode;
union {
+ const void *raw;
+ const struct file_operations *real_fops;
+ const struct debugfs_short_fops *short_fops;
debugfs_automount_t automount;
};
};
@@ -51,15 +54,6 @@ enum {
HAS_IOCTL = 16
};
-/*
- * A dentry's ->d_fsdata either points to the real fops or to a
- * dynamically allocated debugfs_fsdata instance.
- * In order to distinguish between these two cases, a real fops
- * pointer gets its lowest bit set.
- */
-#define DEBUGFS_FSDATA_IS_REAL_FOPS_BIT BIT(0)
-
-/* Access BITS */
#define DEBUGFS_ALLOW_API BIT(0)
#define DEBUGFS_ALLOW_MOUNT BIT(1)
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH v2 05/21] debugfs: allow to store an additional opaque pointer at file creation
2025-01-12 8:06 ` [PATCH v2 01/21] debugfs: separate cache for debugfs inodes Al Viro
` (2 preceding siblings ...)
2025-01-12 8:06 ` [PATCH v2 04/21] debugfs: don't mess with bits in ->d_fsdata Al Viro
@ 2025-01-12 8:06 ` Al Viro
2025-01-13 14:56 ` Christian Brauner
2025-01-12 8:06 ` [PATCH v2 06/21] debugfs: take debugfs_short_fops definition out of ifdef Al Viro
` (16 subsequent siblings)
20 siblings, 1 reply; 53+ messages in thread
From: Al Viro @ 2025-01-12 8:06 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
Set by debugfs_create_file_aux(name, mode, parent, data, aux, fops).
Plain debugfs_create_file() has it set to NULL.
Accessed by debugfs_get_aux(file).
Convenience macros for numeric opaque data - debugfs_create_file_aux_num
and debugfs_get_aux_num, resp.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/debugfs/file.c | 6 ++++++
fs/debugfs/inode.c | 14 +++++++++-----
fs/debugfs/internal.h | 1 +
include/linux/debugfs.h | 27 ++++++++++++++++++++++++++-
4 files changed, 42 insertions(+), 6 deletions(-)
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index ae014bd36a6f..e33cc77699cd 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -47,6 +47,12 @@ const struct file_operations debugfs_noop_file_operations = {
#define F_DENTRY(filp) ((filp)->f_path.dentry)
+const void *debugfs_get_aux(const struct file *file)
+{
+ return DEBUGFS_I(file_inode(file))->aux;
+}
+EXPORT_SYMBOL_GPL(debugfs_get_aux);
+
const struct file_operations *debugfs_real_fops(const struct file *filp)
{
struct debugfs_fsdata *fsd = F_DENTRY(filp)->d_fsdata;
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index c4e8b7f758e0..51d4c3e9d422 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -424,6 +424,7 @@ static struct dentry *end_creating(struct dentry *dentry)
static struct dentry *__debugfs_create_file(const char *name, umode_t mode,
struct dentry *parent, void *data,
+ const void *aux,
const struct file_operations *proxy_fops,
const void *real_fops)
{
@@ -458,6 +459,7 @@ static struct dentry *__debugfs_create_file(const char *name, umode_t mode,
proxy_fops = &debugfs_noop_file_operations;
inode->i_fop = proxy_fops;
DEBUGFS_I(inode)->raw = real_fops;
+ DEBUGFS_I(inode)->aux = aux;
d_instantiate(dentry, inode);
fsnotify_create(d_inode(dentry->d_parent), dentry);
@@ -466,19 +468,21 @@ static struct dentry *__debugfs_create_file(const char *name, umode_t mode,
struct dentry *debugfs_create_file_full(const char *name, umode_t mode,
struct dentry *parent, void *data,
+ const void *aux,
const struct file_operations *fops)
{
- return __debugfs_create_file(name, mode, parent, data,
+ return __debugfs_create_file(name, mode, parent, data, aux,
&debugfs_full_proxy_file_operations,
fops);
}
EXPORT_SYMBOL_GPL(debugfs_create_file_full);
struct dentry *debugfs_create_file_short(const char *name, umode_t mode,
- struct dentry *parent, void *data,
- const struct debugfs_short_fops *fops)
+ struct dentry *parent, void *data,
+ const void *aux,
+ const struct debugfs_short_fops *fops)
{
- return __debugfs_create_file(name, mode, parent, data,
+ return __debugfs_create_file(name, mode, parent, data, aux,
&debugfs_full_short_proxy_file_operations,
fops);
}
@@ -516,7 +520,7 @@ struct dentry *debugfs_create_file_unsafe(const char *name, umode_t mode,
const struct file_operations *fops)
{
- return __debugfs_create_file(name, mode, parent, data,
+ return __debugfs_create_file(name, mode, parent, data, NULL,
&debugfs_open_proxy_file_operations,
fops);
}
diff --git a/fs/debugfs/internal.h b/fs/debugfs/internal.h
index 8d2de647b42c..93483fe84425 100644
--- a/fs/debugfs/internal.h
+++ b/fs/debugfs/internal.h
@@ -19,6 +19,7 @@ struct debugfs_inode_info {
const struct debugfs_short_fops *short_fops;
debugfs_automount_t automount;
};
+ const void *aux;
};
static inline struct debugfs_inode_info *DEBUGFS_I(struct inode *inode)
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h
index 59444b495d49..7c97417d73b5 100644
--- a/include/linux/debugfs.h
+++ b/include/linux/debugfs.h
@@ -79,9 +79,11 @@ struct debugfs_short_fops {
struct dentry *debugfs_create_file_full(const char *name, umode_t mode,
struct dentry *parent, void *data,
+ const void *aux,
const struct file_operations *fops);
struct dentry *debugfs_create_file_short(const char *name, umode_t mode,
struct dentry *parent, void *data,
+ const void *aux,
const struct debugfs_short_fops *fops);
/**
@@ -126,7 +128,15 @@ struct dentry *debugfs_create_file_short(const char *name, umode_t mode,
const struct debugfs_short_fops *: debugfs_create_file_short, \
struct file_operations *: debugfs_create_file_full, \
struct debugfs_short_fops *: debugfs_create_file_short) \
- (name, mode, parent, data, fops)
+ (name, mode, parent, data, NULL, fops)
+
+#define debugfs_create_file_aux(name, mode, parent, data, aux, fops) \
+ _Generic(fops, \
+ const struct file_operations *: debugfs_create_file_full, \
+ const struct debugfs_short_fops *: debugfs_create_file_short, \
+ struct file_operations *: debugfs_create_file_full, \
+ struct debugfs_short_fops *: debugfs_create_file_short) \
+ (name, mode, parent, data, aux, fops)
struct dentry *debugfs_create_file_unsafe(const char *name, umode_t mode,
struct dentry *parent, void *data,
@@ -153,6 +163,7 @@ void debugfs_remove(struct dentry *dentry);
void debugfs_lookup_and_remove(const char *name, struct dentry *parent);
const struct file_operations *debugfs_real_fops(const struct file *filp);
+const void *debugfs_get_aux(const struct file *file);
int debugfs_file_get(struct dentry *dentry);
void debugfs_file_put(struct dentry *dentry);
@@ -259,6 +270,14 @@ static inline struct dentry *debugfs_lookup(const char *name,
return ERR_PTR(-ENODEV);
}
+static inline struct dentry *debugfs_create_file_aux(const char *name,
+ umode_t mode, struct dentry *parent,
+ void *data, void *aux,
+ const void *fops)
+{
+ return ERR_PTR(-ENODEV);
+}
+
static inline struct dentry *debugfs_create_file(const char *name, umode_t mode,
struct dentry *parent, void *data,
const void *fops)
@@ -312,6 +331,7 @@ static inline void debugfs_lookup_and_remove(const char *name,
{ }
const struct file_operations *debugfs_real_fops(const struct file *filp);
+void *debugfs_get_aux(const struct file *file);
static inline int debugfs_file_get(struct dentry *dentry)
{
@@ -452,6 +472,11 @@ static inline ssize_t debugfs_read_file_str(struct file *file,
#endif
+#define debugfs_create_file_aux_num(name, mode, parent, data, n, fops) \
+ debugfs_create_file_aux(name, mode, parent, data, \
+ (void *)(unsigned long)n, fops)
+#define debugfs_get_aux_num(f) (unsigned long)debugfs_get_aux(f)
+
/**
* debugfs_create_xul - create a debugfs file that is used to read and write an
* unsigned long value, formatted in hexadecimal
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH v2 06/21] debugfs: take debugfs_short_fops definition out of ifdef
2025-01-12 8:06 ` [PATCH v2 01/21] debugfs: separate cache for debugfs inodes Al Viro
` (3 preceding siblings ...)
2025-01-12 8:06 ` [PATCH v2 05/21] debugfs: allow to store an additional opaque pointer at file creation Al Viro
@ 2025-01-12 8:06 ` Al Viro
2025-01-13 14:57 ` Christian Brauner
2025-01-12 8:06 ` [PATCH v2 07/21] carl9170: stop embedding file_operations into their objects Al Viro
` (15 subsequent siblings)
20 siblings, 1 reply; 53+ messages in thread
From: Al Viro @ 2025-01-12 8:06 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
include/linux/debugfs.h | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h
index 7c97417d73b5..68e9c6cbd835 100644
--- a/include/linux/debugfs.h
+++ b/include/linux/debugfs.h
@@ -67,16 +67,16 @@ static const struct file_operations __fops = { \
typedef struct vfsmount *(*debugfs_automount_t)(struct dentry *, void *);
-#if defined(CONFIG_DEBUG_FS)
-
-struct dentry *debugfs_lookup(const char *name, struct dentry *parent);
-
struct debugfs_short_fops {
ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);
ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *);
loff_t (*llseek) (struct file *, loff_t, int);
};
+#if defined(CONFIG_DEBUG_FS)
+
+struct dentry *debugfs_lookup(const char *name, struct dentry *parent);
+
struct dentry *debugfs_create_file_full(const char *name, umode_t mode,
struct dentry *parent, void *data,
const void *aux,
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH v2 07/21] carl9170: stop embedding file_operations into their objects
2025-01-12 8:06 ` [PATCH v2 01/21] debugfs: separate cache for debugfs inodes Al Viro
` (4 preceding siblings ...)
2025-01-12 8:06 ` [PATCH v2 06/21] debugfs: take debugfs_short_fops definition out of ifdef Al Viro
@ 2025-01-12 8:06 ` Al Viro
2025-01-12 8:06 ` [PATCH v2 08/21] b43: stop embedding struct " Al Viro
` (14 subsequent siblings)
20 siblings, 0 replies; 53+ messages in thread
From: Al Viro @ 2025-01-12 8:06 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
use debugfs_get_aux() instead; switch to debugfs_short_ops as well.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
drivers/net/wireless/ath/carl9170/debug.c | 28 ++++++++++-------------
1 file changed, 12 insertions(+), 16 deletions(-)
diff --git a/drivers/net/wireless/ath/carl9170/debug.c b/drivers/net/wireless/ath/carl9170/debug.c
index bb40889d7c72..2d734567000a 100644
--- a/drivers/net/wireless/ath/carl9170/debug.c
+++ b/drivers/net/wireless/ath/carl9170/debug.c
@@ -54,7 +54,6 @@ struct carl9170_debugfs_fops {
char *(*read)(struct ar9170 *ar, char *buf, size_t bufsize,
ssize_t *len);
ssize_t (*write)(struct ar9170 *aru, const char *buf, size_t size);
- const struct file_operations fops;
enum carl9170_device_state req_dev_state;
};
@@ -62,7 +61,7 @@ struct carl9170_debugfs_fops {
static ssize_t carl9170_debugfs_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
- struct carl9170_debugfs_fops *dfops;
+ const struct carl9170_debugfs_fops *dfops;
struct ar9170 *ar;
char *buf = NULL, *res_buf = NULL;
ssize_t ret = 0;
@@ -75,8 +74,7 @@ static ssize_t carl9170_debugfs_read(struct file *file, char __user *userbuf,
if (!ar)
return -ENODEV;
- dfops = container_of(debugfs_real_fops(file),
- struct carl9170_debugfs_fops, fops);
+ dfops = debugfs_get_aux(file);
if (!dfops->read)
return -ENOSYS;
@@ -113,7 +111,7 @@ static ssize_t carl9170_debugfs_read(struct file *file, char __user *userbuf,
static ssize_t carl9170_debugfs_write(struct file *file,
const char __user *userbuf, size_t count, loff_t *ppos)
{
- struct carl9170_debugfs_fops *dfops;
+ const struct carl9170_debugfs_fops *dfops;
struct ar9170 *ar;
char *buf = NULL;
int err = 0;
@@ -128,8 +126,7 @@ static ssize_t carl9170_debugfs_write(struct file *file,
if (!ar)
return -ENODEV;
- dfops = container_of(debugfs_real_fops(file),
- struct carl9170_debugfs_fops, fops);
+ dfops = debugfs_get_aux(file);
if (!dfops->write)
return -ENOSYS;
@@ -165,6 +162,11 @@ static ssize_t carl9170_debugfs_write(struct file *file,
return err;
}
+static struct debugfs_short_fops debugfs_fops = {
+ .read = carl9170_debugfs_read,
+ .write = carl9170_debugfs_write,
+};
+
#define __DEBUGFS_DECLARE_FILE(name, _read, _write, _read_bufsize, \
_attr, _dstate) \
static const struct carl9170_debugfs_fops carl_debugfs_##name ##_ops = {\
@@ -173,12 +175,6 @@ static const struct carl9170_debugfs_fops carl_debugfs_##name ##_ops = {\
.write = _write, \
.attr = _attr, \
.req_dev_state = _dstate, \
- .fops = { \
- .open = simple_open, \
- .read = carl9170_debugfs_read, \
- .write = carl9170_debugfs_write, \
- .owner = THIS_MODULE \
- }, \
}
#define DEBUGFS_DECLARE_FILE(name, _read, _write, _read_bufsize, _attr) \
@@ -816,9 +812,9 @@ void carl9170_debugfs_register(struct ar9170 *ar)
ar->hw->wiphy->debugfsdir);
#define DEBUGFS_ADD(name) \
- debugfs_create_file(#name, carl_debugfs_##name ##_ops.attr, \
- ar->debug_dir, ar, \
- &carl_debugfs_##name ## _ops.fops)
+ debugfs_create_file_aux(#name, carl_debugfs_##name ##_ops.attr, \
+ ar->debug_dir, ar, &carl_debugfs_##name ## _ops, \
+ &debugfs_fops)
DEBUGFS_ADD(usb_tx_anch_urbs);
DEBUGFS_ADD(usb_rx_pool_urbs);
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH v2 08/21] b43: stop embedding struct file_operations into their objects
2025-01-12 8:06 ` [PATCH v2 01/21] debugfs: separate cache for debugfs inodes Al Viro
` (5 preceding siblings ...)
2025-01-12 8:06 ` [PATCH v2 07/21] carl9170: stop embedding file_operations into their objects Al Viro
@ 2025-01-12 8:06 ` Al Viro
2025-01-12 8:06 ` [PATCH v2 09/21] b43legacy: make use of debugfs_get_aux() Al Viro
` (13 subsequent siblings)
20 siblings, 0 replies; 53+ messages in thread
From: Al Viro @ 2025-01-12 8:06 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
Use debugfs_get_aux() instead. And switch to debugfs_short_fops, while we
are at it...
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
drivers/net/wireless/broadcom/b43/debugfs.c | 27 +++++++++------------
1 file changed, 12 insertions(+), 15 deletions(-)
diff --git a/drivers/net/wireless/broadcom/b43/debugfs.c b/drivers/net/wireless/broadcom/b43/debugfs.c
index efa98444e3fb..5a49970afc8c 100644
--- a/drivers/net/wireless/broadcom/b43/debugfs.c
+++ b/drivers/net/wireless/broadcom/b43/debugfs.c
@@ -30,7 +30,6 @@ static struct dentry *rootdir;
struct b43_debugfs_fops {
ssize_t (*read)(struct b43_wldev *dev, char *buf, size_t bufsize);
int (*write)(struct b43_wldev *dev, const char *buf, size_t count);
- struct file_operations fops;
/* Offset of struct b43_dfs_file in struct b43_dfsentry */
size_t file_struct_offset;
};
@@ -491,7 +490,7 @@ static ssize_t b43_debugfs_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
struct b43_wldev *dev;
- struct b43_debugfs_fops *dfops;
+ const struct b43_debugfs_fops *dfops;
struct b43_dfs_file *dfile;
ssize_t ret;
char *buf;
@@ -511,8 +510,7 @@ static ssize_t b43_debugfs_read(struct file *file, char __user *userbuf,
goto out_unlock;
}
- dfops = container_of(debugfs_real_fops(file),
- struct b43_debugfs_fops, fops);
+ dfops = debugfs_get_aux(file);
if (!dfops->read) {
err = -ENOSYS;
goto out_unlock;
@@ -555,7 +553,7 @@ static ssize_t b43_debugfs_write(struct file *file,
size_t count, loff_t *ppos)
{
struct b43_wldev *dev;
- struct b43_debugfs_fops *dfops;
+ const struct b43_debugfs_fops *dfops;
char *buf;
int err = 0;
@@ -573,8 +571,7 @@ static ssize_t b43_debugfs_write(struct file *file,
goto out_unlock;
}
- dfops = container_of(debugfs_real_fops(file),
- struct b43_debugfs_fops, fops);
+ dfops = debugfs_get_aux(file);
if (!dfops->write) {
err = -ENOSYS;
goto out_unlock;
@@ -602,16 +599,16 @@ static ssize_t b43_debugfs_write(struct file *file,
}
+static struct debugfs_short_fops debugfs_ops = {
+ .read = b43_debugfs_read,
+ .write = b43_debugfs_write,
+ .llseek = generic_file_llseek,
+};
+
#define B43_DEBUGFS_FOPS(name, _read, _write) \
static struct b43_debugfs_fops fops_##name = { \
.read = _read, \
.write = _write, \
- .fops = { \
- .open = simple_open, \
- .read = b43_debugfs_read, \
- .write = b43_debugfs_write, \
- .llseek = generic_file_llseek, \
- }, \
.file_struct_offset = offsetof(struct b43_dfsentry, \
file_##name), \
}
@@ -703,9 +700,9 @@ void b43_debugfs_add_device(struct b43_wldev *dev)
#define ADD_FILE(name, mode) \
do { \
- debugfs_create_file(__stringify(name), \
+ debugfs_create_file_aux(__stringify(name), \
mode, e->subdir, dev, \
- &fops_##name.fops); \
+ &fops_##name, &debugfs_ops); \
} while (0)
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH v2 09/21] b43legacy: make use of debugfs_get_aux()
2025-01-12 8:06 ` [PATCH v2 01/21] debugfs: separate cache for debugfs inodes Al Viro
` (6 preceding siblings ...)
2025-01-12 8:06 ` [PATCH v2 08/21] b43: stop embedding struct " Al Viro
@ 2025-01-12 8:06 ` Al Viro
2025-01-12 8:06 ` [PATCH v2 10/21] netdevsim: don't embed file_operations into your structs Al Viro
` (12 subsequent siblings)
20 siblings, 0 replies; 53+ messages in thread
From: Al Viro @ 2025-01-12 8:06 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
.../net/wireless/broadcom/b43legacy/debugfs.c | 26 ++++++++-----------
1 file changed, 11 insertions(+), 15 deletions(-)
diff --git a/drivers/net/wireless/broadcom/b43legacy/debugfs.c b/drivers/net/wireless/broadcom/b43legacy/debugfs.c
index 6b0e8d117061..5d04bcc216e5 100644
--- a/drivers/net/wireless/broadcom/b43legacy/debugfs.c
+++ b/drivers/net/wireless/broadcom/b43legacy/debugfs.c
@@ -31,7 +31,6 @@ static struct dentry *rootdir;
struct b43legacy_debugfs_fops {
ssize_t (*read)(struct b43legacy_wldev *dev, char *buf, size_t bufsize);
int (*write)(struct b43legacy_wldev *dev, const char *buf, size_t count);
- struct file_operations fops;
/* Offset of struct b43legacy_dfs_file in struct b43legacy_dfsentry */
size_t file_struct_offset;
/* Take wl->irq_lock before calling read/write? */
@@ -188,7 +187,7 @@ static ssize_t b43legacy_debugfs_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
struct b43legacy_wldev *dev;
- struct b43legacy_debugfs_fops *dfops;
+ const struct b43legacy_debugfs_fops *dfops;
struct b43legacy_dfs_file *dfile;
ssize_t ret;
char *buf;
@@ -208,8 +207,7 @@ static ssize_t b43legacy_debugfs_read(struct file *file, char __user *userbuf,
goto out_unlock;
}
- dfops = container_of(debugfs_real_fops(file),
- struct b43legacy_debugfs_fops, fops);
+ dfops = debugfs_get_aux(file);
if (!dfops->read) {
err = -ENOSYS;
goto out_unlock;
@@ -257,7 +255,7 @@ static ssize_t b43legacy_debugfs_write(struct file *file,
size_t count, loff_t *ppos)
{
struct b43legacy_wldev *dev;
- struct b43legacy_debugfs_fops *dfops;
+ const struct b43legacy_debugfs_fops *dfops;
char *buf;
int err = 0;
@@ -275,8 +273,7 @@ static ssize_t b43legacy_debugfs_write(struct file *file,
goto out_unlock;
}
- dfops = container_of(debugfs_real_fops(file),
- struct b43legacy_debugfs_fops, fops);
+ dfops = debugfs_get_aux(file);
if (!dfops->write) {
err = -ENOSYS;
goto out_unlock;
@@ -308,17 +305,16 @@ static ssize_t b43legacy_debugfs_write(struct file *file,
return err ? err : count;
}
+static struct debugfs_short_fops debugfs_ops = {
+ .read = b43legacy_debugfs_read,
+ .write = b43legacy_debugfs_write,
+ .llseek = generic_file_llseek
+};
#define B43legacy_DEBUGFS_FOPS(name, _read, _write, _take_irqlock) \
static struct b43legacy_debugfs_fops fops_##name = { \
.read = _read, \
.write = _write, \
- .fops = { \
- .open = simple_open, \
- .read = b43legacy_debugfs_read, \
- .write = b43legacy_debugfs_write, \
- .llseek = generic_file_llseek, \
- }, \
.file_struct_offset = offsetof(struct b43legacy_dfsentry, \
file_##name), \
.take_irqlock = _take_irqlock, \
@@ -386,9 +382,9 @@ void b43legacy_debugfs_add_device(struct b43legacy_wldev *dev)
#define ADD_FILE(name, mode) \
do { \
- debugfs_create_file(__stringify(name), mode, \
+ debugfs_create_file_aux(__stringify(name), mode, \
e->subdir, dev, \
- &fops_##name.fops); \
+ &fops_##name, &debugfs_ops); \
} while (0)
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH v2 10/21] netdevsim: don't embed file_operations into your structs
2025-01-12 8:06 ` [PATCH v2 01/21] debugfs: separate cache for debugfs inodes Al Viro
` (7 preceding siblings ...)
2025-01-12 8:06 ` [PATCH v2 09/21] b43legacy: make use of debugfs_get_aux() Al Viro
@ 2025-01-12 8:06 ` Al Viro
2025-01-12 8:06 ` [PATCH v2 11/21] mediatek: stop messing with ->d_iname Al Viro
` (11 subsequent siblings)
20 siblings, 0 replies; 53+ messages in thread
From: Al Viro @ 2025-01-12 8:06 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
Just use debugfs_get_aux() instead of debugfs_real_fops().
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
drivers/net/netdevsim/hwstats.c | 29 +++++++++++++----------------
1 file changed, 13 insertions(+), 16 deletions(-)
diff --git a/drivers/net/netdevsim/hwstats.c b/drivers/net/netdevsim/hwstats.c
index 0e58aa7f0374..66b3215db3ac 100644
--- a/drivers/net/netdevsim/hwstats.c
+++ b/drivers/net/netdevsim/hwstats.c
@@ -331,7 +331,6 @@ enum nsim_dev_hwstats_do {
};
struct nsim_dev_hwstats_fops {
- const struct file_operations fops;
enum nsim_dev_hwstats_do action;
enum netdev_offload_xstats_type type;
};
@@ -342,13 +341,12 @@ nsim_dev_hwstats_do_write(struct file *file,
size_t count, loff_t *ppos)
{
struct nsim_dev_hwstats *hwstats = file->private_data;
- struct nsim_dev_hwstats_fops *hwsfops;
+ const struct nsim_dev_hwstats_fops *hwsfops;
struct list_head *hwsdev_list;
int ifindex;
int err;
- hwsfops = container_of(debugfs_real_fops(file),
- struct nsim_dev_hwstats_fops, fops);
+ hwsfops = debugfs_get_aux(file);
err = kstrtoint_from_user(data, count, 0, &ifindex);
if (err)
@@ -381,14 +379,13 @@ nsim_dev_hwstats_do_write(struct file *file,
return count;
}
+static struct debugfs_short_fops debugfs_ops = {
+ .write = nsim_dev_hwstats_do_write,
+ .llseek = generic_file_llseek,
+};
+
#define NSIM_DEV_HWSTATS_FOPS(ACTION, TYPE) \
{ \
- .fops = { \
- .open = simple_open, \
- .write = nsim_dev_hwstats_do_write, \
- .llseek = generic_file_llseek, \
- .owner = THIS_MODULE, \
- }, \
.action = ACTION, \
.type = TYPE, \
}
@@ -433,12 +430,12 @@ int nsim_dev_hwstats_init(struct nsim_dev *nsim_dev)
goto err_remove_hwstats_recursive;
}
- debugfs_create_file("enable_ifindex", 0200, hwstats->l3_ddir, hwstats,
- &nsim_dev_hwstats_l3_enable_fops.fops);
- debugfs_create_file("disable_ifindex", 0200, hwstats->l3_ddir, hwstats,
- &nsim_dev_hwstats_l3_disable_fops.fops);
- debugfs_create_file("fail_next_enable", 0200, hwstats->l3_ddir, hwstats,
- &nsim_dev_hwstats_l3_fail_fops.fops);
+ debugfs_create_file_aux("enable_ifindex", 0200, hwstats->l3_ddir, hwstats,
+ &nsim_dev_hwstats_l3_enable_fops, &debugfs_ops);
+ debugfs_create_file_aux("disable_ifindex", 0200, hwstats->l3_ddir, hwstats,
+ &nsim_dev_hwstats_l3_disable_fops, &debugfs_ops);
+ debugfs_create_file_aux("fail_next_enable", 0200, hwstats->l3_ddir, hwstats,
+ &nsim_dev_hwstats_l3_fail_fops, &debugfs_ops);
INIT_DELAYED_WORK(&hwstats->traffic_dw,
&nsim_dev_hwstats_traffic_work);
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH v2 11/21] mediatek: stop messing with ->d_iname
2025-01-12 8:06 ` [PATCH v2 01/21] debugfs: separate cache for debugfs inodes Al Viro
` (8 preceding siblings ...)
2025-01-12 8:06 ` [PATCH v2 10/21] netdevsim: don't embed file_operations into your structs Al Viro
@ 2025-01-12 8:06 ` Al Viro
2025-01-12 8:06 ` [PATCH v2 12/21] [not even compile-tested] greybus/camera - " Al Viro
` (10 subsequent siblings)
20 siblings, 0 replies; 53+ messages in thread
From: Al Viro @ 2025-01-12 8:06 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
use debgufs_{create_file,get}_aux_num() instead.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
drivers/phy/mediatek/phy-mtk-tphy.c | 40 ++++++++---------------------
1 file changed, 10 insertions(+), 30 deletions(-)
diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c b/drivers/phy/mediatek/phy-mtk-tphy.c
index 3f7095ec5978..a496fbe3352b 100644
--- a/drivers/phy/mediatek/phy-mtk-tphy.c
+++ b/drivers/phy/mediatek/phy-mtk-tphy.c
@@ -381,17 +381,12 @@ static const char *const u3_phy_files[] = {
static int u2_phy_params_show(struct seq_file *sf, void *unused)
{
struct mtk_phy_instance *inst = sf->private;
- const char *fname = file_dentry(sf->file)->d_iname;
struct u2phy_banks *u2_banks = &inst->u2_banks;
void __iomem *com = u2_banks->com;
u32 max = 0;
u32 tmp = 0;
u32 val = 0;
- int ret;
-
- ret = match_string(u2_phy_files, ARRAY_SIZE(u2_phy_files), fname);
- if (ret < 0)
- return ret;
+ int ret = debugfs_get_aux_num(sf->file);
switch (ret) {
case U2P_EYE_VRT:
@@ -438,7 +433,7 @@ static int u2_phy_params_show(struct seq_file *sf, void *unused)
break;
}
- seq_printf(sf, "%s : %d [0, %d]\n", fname, val, max);
+ seq_printf(sf, "%s : %d [0, %d]\n", u2_phy_files[ret], val, max);
return 0;
}
@@ -451,23 +446,18 @@ static int u2_phy_params_open(struct inode *inode, struct file *file)
static ssize_t u2_phy_params_write(struct file *file, const char __user *ubuf,
size_t count, loff_t *ppos)
{
- const char *fname = file_dentry(file)->d_iname;
struct seq_file *sf = file->private_data;
struct mtk_phy_instance *inst = sf->private;
struct u2phy_banks *u2_banks = &inst->u2_banks;
void __iomem *com = u2_banks->com;
ssize_t rc;
u32 val;
- int ret;
+ int ret = debugfs_get_aux_num(file);
rc = kstrtouint_from_user(ubuf, USER_BUF_LEN(count), 0, &val);
if (rc)
return rc;
- ret = match_string(u2_phy_files, ARRAY_SIZE(u2_phy_files), fname);
- if (ret < 0)
- return (ssize_t)ret;
-
switch (ret) {
case U2P_EYE_VRT:
mtk_phy_update_field(com + U3P_USBPHYACR1, PA1_RG_VRT_SEL, val);
@@ -516,23 +506,18 @@ static void u2_phy_dbgfs_files_create(struct mtk_phy_instance *inst)
int i;
for (i = 0; i < count; i++)
- debugfs_create_file(u2_phy_files[i], 0644, inst->phy->debugfs,
- inst, &u2_phy_fops);
+ debugfs_create_file_aux_num(u2_phy_files[i], 0644, inst->phy->debugfs,
+ inst, i, &u2_phy_fops);
}
static int u3_phy_params_show(struct seq_file *sf, void *unused)
{
struct mtk_phy_instance *inst = sf->private;
- const char *fname = file_dentry(sf->file)->d_iname;
struct u3phy_banks *u3_banks = &inst->u3_banks;
u32 val = 0;
u32 max = 0;
u32 tmp;
- int ret;
-
- ret = match_string(u3_phy_files, ARRAY_SIZE(u3_phy_files), fname);
- if (ret < 0)
- return ret;
+ int ret = debugfs_get_aux_num(sf->file);
switch (ret) {
case U3P_EFUSE_EN:
@@ -564,7 +549,7 @@ static int u3_phy_params_show(struct seq_file *sf, void *unused)
break;
}
- seq_printf(sf, "%s : %d [0, %d]\n", fname, val, max);
+ seq_printf(sf, "%s : %d [0, %d]\n", u3_phy_files[ret], val, max);
return 0;
}
@@ -577,23 +562,18 @@ static int u3_phy_params_open(struct inode *inode, struct file *file)
static ssize_t u3_phy_params_write(struct file *file, const char __user *ubuf,
size_t count, loff_t *ppos)
{
- const char *fname = file_dentry(file)->d_iname;
struct seq_file *sf = file->private_data;
struct mtk_phy_instance *inst = sf->private;
struct u3phy_banks *u3_banks = &inst->u3_banks;
void __iomem *phyd = u3_banks->phyd;
ssize_t rc;
u32 val;
- int ret;
+ int ret = debugfs_get_aux_num(sf->file);
rc = kstrtouint_from_user(ubuf, USER_BUF_LEN(count), 0, &val);
if (rc)
return rc;
- ret = match_string(u3_phy_files, ARRAY_SIZE(u3_phy_files), fname);
- if (ret < 0)
- return (ssize_t)ret;
-
switch (ret) {
case U3P_EFUSE_EN:
mtk_phy_update_field(phyd + U3P_U3_PHYD_RSV,
@@ -636,8 +616,8 @@ static void u3_phy_dbgfs_files_create(struct mtk_phy_instance *inst)
int i;
for (i = 0; i < count; i++)
- debugfs_create_file(u3_phy_files[i], 0644, inst->phy->debugfs,
- inst, &u3_phy_fops);
+ debugfs_create_file_aux_num(u3_phy_files[i], 0644, inst->phy->debugfs,
+ inst, i, &u3_phy_fops);
}
static int phy_type_show(struct seq_file *sf, void *unused)
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH v2 12/21] [not even compile-tested] greybus/camera - stop messing with ->d_iname
2025-01-12 8:06 ` [PATCH v2 01/21] debugfs: separate cache for debugfs inodes Al Viro
` (9 preceding siblings ...)
2025-01-12 8:06 ` [PATCH v2 11/21] mediatek: stop messing with ->d_iname Al Viro
@ 2025-01-12 8:06 ` Al Viro
2025-01-12 8:06 ` [PATCH v2 13/21] mtu3: don't mess wiht ->d_iname Al Viro
` (9 subsequent siblings)
20 siblings, 0 replies; 53+ messages in thread
From: Al Viro @ 2025-01-12 8:06 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
drivers/staging/greybus/camera.c | 17 +++--------------
1 file changed, 3 insertions(+), 14 deletions(-)
diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c
index ca71023df447..5d80ace41d8e 100644
--- a/drivers/staging/greybus/camera.c
+++ b/drivers/staging/greybus/camera.c
@@ -1128,18 +1128,7 @@ static ssize_t gb_camera_debugfs_write(struct file *file,
static int gb_camera_debugfs_open(struct inode *inode, struct file *file)
{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(gb_camera_debugfs_entries); ++i) {
- const struct gb_camera_debugfs_entry *entry =
- &gb_camera_debugfs_entries[i];
-
- if (!strcmp(file->f_path.dentry->d_iname, entry->name)) {
- file->private_data = (void *)entry;
- break;
- }
- }
-
+ file->private_data = (void *)debugfs_get_aux(file);
return 0;
}
@@ -1175,8 +1164,8 @@ static int gb_camera_debugfs_init(struct gb_camera *gcam)
gcam->debugfs.buffers[i].length = 0;
- debugfs_create_file(entry->name, entry->mask,
- gcam->debugfs.root, gcam,
+ debugfs_create_file_aux(entry->name, entry->mask,
+ gcam->debugfs.root, gcam, entry,
&gb_camera_debugfs_ops);
}
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH v2 13/21] mtu3: don't mess wiht ->d_iname
2025-01-12 8:06 ` [PATCH v2 01/21] debugfs: separate cache for debugfs inodes Al Viro
` (10 preceding siblings ...)
2025-01-12 8:06 ` [PATCH v2 12/21] [not even compile-tested] greybus/camera - " Al Viro
@ 2025-01-12 8:06 ` Al Viro
2025-01-12 8:06 ` [PATCH v2 14/21] xhci: don't mess with ->d_iname Al Viro
` (8 subsequent siblings)
20 siblings, 0 replies; 53+ messages in thread
From: Al Viro @ 2025-01-12 8:06 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
use debugfs_{create_file,get}_aux() instead.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
drivers/usb/mtu3/mtu3_debugfs.c | 40 ++++++---------------------------
1 file changed, 7 insertions(+), 33 deletions(-)
diff --git a/drivers/usb/mtu3/mtu3_debugfs.c b/drivers/usb/mtu3/mtu3_debugfs.c
index f0de99858353..deeac2c8f589 100644
--- a/drivers/usb/mtu3/mtu3_debugfs.c
+++ b/drivers/usb/mtu3/mtu3_debugfs.c
@@ -256,16 +256,7 @@ static const struct mtu3_file_map mtu3_ep_files[] = {
static int mtu3_ep_open(struct inode *inode, struct file *file)
{
- const char *file_name = file_dentry(file)->d_iname;
- const struct mtu3_file_map *f_map;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(mtu3_ep_files); i++) {
- f_map = &mtu3_ep_files[i];
-
- if (strcmp(f_map->name, file_name) == 0)
- break;
- }
+ const struct mtu3_file_map *f_map = debugfs_get_aux(file);
return single_open(file, f_map->show, inode->i_private);
}
@@ -288,17 +279,8 @@ static const struct debugfs_reg32 mtu3_prb_regs[] = {
static int mtu3_probe_show(struct seq_file *sf, void *unused)
{
- const char *file_name = file_dentry(sf->file)->d_iname;
struct mtu3 *mtu = sf->private;
- const struct debugfs_reg32 *regs;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(mtu3_prb_regs); i++) {
- regs = &mtu3_prb_regs[i];
-
- if (strcmp(regs->name, file_name) == 0)
- break;
- }
+ const struct debugfs_reg32 *regs = debugfs_get_aux(sf->file);
seq_printf(sf, "0x%04x - 0x%08x\n", (u32)regs->offset,
mtu3_readl(mtu->ippc_base, (u32)regs->offset));
@@ -314,13 +296,11 @@ static int mtu3_probe_open(struct inode *inode, struct file *file)
static ssize_t mtu3_probe_write(struct file *file, const char __user *ubuf,
size_t count, loff_t *ppos)
{
- const char *file_name = file_dentry(file)->d_iname;
struct seq_file *sf = file->private_data;
struct mtu3 *mtu = sf->private;
- const struct debugfs_reg32 *regs;
+ const struct debugfs_reg32 *regs = debugfs_get_aux(file);
char buf[32];
u32 val;
- int i;
if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
return -EFAULT;
@@ -328,12 +308,6 @@ static ssize_t mtu3_probe_write(struct file *file, const char __user *ubuf,
if (kstrtou32(buf, 0, &val))
return -EINVAL;
- for (i = 0; i < ARRAY_SIZE(mtu3_prb_regs); i++) {
- regs = &mtu3_prb_regs[i];
-
- if (strcmp(regs->name, file_name) == 0)
- break;
- }
mtu3_writel(mtu->ippc_base, (u32)regs->offset, val);
return count;
@@ -358,8 +332,8 @@ static void mtu3_debugfs_create_prb_files(struct mtu3 *mtu)
for (i = 0; i < ARRAY_SIZE(mtu3_prb_regs); i++) {
regs = &mtu3_prb_regs[i];
- debugfs_create_file(regs->name, 0644, dir_prb,
- mtu, &mtu3_probe_fops);
+ debugfs_create_file_aux(regs->name, 0644, dir_prb,
+ mtu, regs, &mtu3_probe_fops);
}
mtu3_debugfs_regset(mtu, mtu->ippc_base, mtu3_prb_regs,
@@ -379,8 +353,8 @@ static void mtu3_debugfs_create_ep_dir(struct mtu3_ep *mep,
for (i = 0; i < ARRAY_SIZE(mtu3_ep_files); i++) {
files = &mtu3_ep_files[i];
- debugfs_create_file(files->name, 0444, dir_ep,
- mep, &mtu3_ep_fops);
+ debugfs_create_file_aux(files->name, 0444, dir_ep,
+ mep, files, &mtu3_ep_fops);
}
}
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH v2 14/21] xhci: don't mess with ->d_iname
2025-01-12 8:06 ` [PATCH v2 01/21] debugfs: separate cache for debugfs inodes Al Viro
` (11 preceding siblings ...)
2025-01-12 8:06 ` [PATCH v2 13/21] mtu3: don't mess wiht ->d_iname Al Viro
@ 2025-01-12 8:06 ` Al Viro
2025-01-12 8:06 ` [PATCH v2 15/21] qat: don't mess with ->d_name Al Viro
` (7 subsequent siblings)
20 siblings, 0 replies; 53+ messages in thread
From: Al Viro @ 2025-01-12 8:06 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
use debugs_{creat_file,get}_aux() instead
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
drivers/usb/host/xhci-debugfs.c | 25 ++++---------------------
1 file changed, 4 insertions(+), 21 deletions(-)
diff --git a/drivers/usb/host/xhci-debugfs.c b/drivers/usb/host/xhci-debugfs.c
index 4f0c1b96e208..1f5ef174abea 100644
--- a/drivers/usb/host/xhci-debugfs.c
+++ b/drivers/usb/host/xhci-debugfs.c
@@ -232,16 +232,7 @@ static struct xhci_file_map ring_files[] = {
static int xhci_ring_open(struct inode *inode, struct file *file)
{
- int i;
- struct xhci_file_map *f_map;
- const char *file_name = file_dentry(file)->d_iname;
-
- for (i = 0; i < ARRAY_SIZE(ring_files); i++) {
- f_map = &ring_files[i];
-
- if (strcmp(f_map->name, file_name) == 0)
- break;
- }
+ const struct xhci_file_map *f_map = debugfs_get_aux(file);
return single_open(file, f_map->show, inode->i_private);
}
@@ -318,16 +309,7 @@ static struct xhci_file_map context_files[] = {
static int xhci_context_open(struct inode *inode, struct file *file)
{
- int i;
- struct xhci_file_map *f_map;
- const char *file_name = file_dentry(file)->d_iname;
-
- for (i = 0; i < ARRAY_SIZE(context_files); i++) {
- f_map = &context_files[i];
-
- if (strcmp(f_map->name, file_name) == 0)
- break;
- }
+ const struct xhci_file_map *f_map = debugfs_get_aux(file);
return single_open(file, f_map->show, inode->i_private);
}
@@ -410,7 +392,8 @@ static void xhci_debugfs_create_files(struct xhci_hcd *xhci,
int i;
for (i = 0; i < nentries; i++)
- debugfs_create_file(files[i].name, 0444, parent, data, fops);
+ debugfs_create_file_aux(files[i].name, 0444, parent,
+ data, &files[i], fops);
}
static struct dentry *xhci_debugfs_create_ring_dir(struct xhci_hcd *xhci,
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH v2 15/21] qat: don't mess with ->d_name
2025-01-12 8:06 ` [PATCH v2 01/21] debugfs: separate cache for debugfs inodes Al Viro
` (12 preceding siblings ...)
2025-01-12 8:06 ` [PATCH v2 14/21] xhci: don't mess with ->d_iname Al Viro
@ 2025-01-12 8:06 ` Al Viro
2025-01-12 8:07 ` [PATCH v2 16/21] sof-client-ipc-flood-test: " Al Viro
` (6 subsequent siblings)
20 siblings, 0 replies; 53+ messages in thread
From: Al Viro @ 2025-01-12 8:06 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
use debugfs_{create_file,get}_aux_num() instead.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
.../intel/qat/qat_common/adf_tl_debugfs.c | 36 +++----------------
1 file changed, 4 insertions(+), 32 deletions(-)
diff --git a/drivers/crypto/intel/qat/qat_common/adf_tl_debugfs.c b/drivers/crypto/intel/qat/qat_common/adf_tl_debugfs.c
index c8241f5a0a26..f20ae7e35a0d 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_tl_debugfs.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_tl_debugfs.c
@@ -473,22 +473,6 @@ static ssize_t tl_control_write(struct file *file, const char __user *userbuf,
}
DEFINE_SHOW_STORE_ATTRIBUTE(tl_control);
-static int get_rp_index_from_file(const struct file *f, u8 *rp_id, u8 rp_num)
-{
- char alpha;
- u8 index;
- int ret;
-
- ret = sscanf(f->f_path.dentry->d_name.name, ADF_TL_RP_REGS_FNAME, &alpha);
- if (ret != 1)
- return -EINVAL;
-
- index = ADF_TL_DBG_RP_INDEX_ALPHA(alpha);
- *rp_id = index;
-
- return 0;
-}
-
static int adf_tl_dbg_change_rp_index(struct adf_accel_dev *accel_dev,
unsigned int new_rp_num,
unsigned int rp_regs_index)
@@ -611,18 +595,11 @@ static int tl_rp_data_show(struct seq_file *s, void *unused)
{
struct adf_accel_dev *accel_dev = s->private;
u8 rp_regs_index;
- u8 max_rp;
- int ret;
if (!accel_dev)
return -EINVAL;
- max_rp = GET_TL_DATA(accel_dev).max_rp;
- ret = get_rp_index_from_file(s->file, &rp_regs_index, max_rp);
- if (ret) {
- dev_dbg(&GET_DEV(accel_dev), "invalid RP data file name\n");
- return ret;
- }
+ rp_regs_index = debugfs_get_aux_num(s->file);
return tl_print_rp_data(accel_dev, s, rp_regs_index);
}
@@ -635,7 +612,6 @@ static ssize_t tl_rp_data_write(struct file *file, const char __user *userbuf,
struct adf_telemetry *telemetry;
unsigned int new_rp_num;
u8 rp_regs_index;
- u8 max_rp;
int ret;
accel_dev = seq_f->private;
@@ -643,15 +619,10 @@ static ssize_t tl_rp_data_write(struct file *file, const char __user *userbuf,
return -EINVAL;
telemetry = accel_dev->telemetry;
- max_rp = GET_TL_DATA(accel_dev).max_rp;
mutex_lock(&telemetry->wr_lock);
- ret = get_rp_index_from_file(file, &rp_regs_index, max_rp);
- if (ret) {
- dev_dbg(&GET_DEV(accel_dev), "invalid RP data file name\n");
- goto unlock_and_exit;
- }
+ rp_regs_index = debugfs_get_aux_num(file);
ret = kstrtou32_from_user(userbuf, count, 10, &new_rp_num);
if (ret)
@@ -689,7 +660,8 @@ void adf_tl_dbgfs_add(struct adf_accel_dev *accel_dev)
for (i = 0; i < max_rp; i++) {
snprintf(name, sizeof(name), ADF_TL_RP_REGS_FNAME,
ADF_TL_DBG_RP_ALPHA_INDEX(i));
- debugfs_create_file(name, 0644, dir, accel_dev, &tl_rp_data_fops);
+ debugfs_create_file_aux_num(name, 0644, dir, accel_dev, i,
+ &tl_rp_data_fops);
}
}
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH v2 16/21] sof-client-ipc-flood-test: don't mess with ->d_name
2025-01-12 8:06 ` [PATCH v2 01/21] debugfs: separate cache for debugfs inodes Al Viro
` (13 preceding siblings ...)
2025-01-12 8:06 ` [PATCH v2 15/21] qat: don't mess with ->d_name Al Viro
@ 2025-01-12 8:07 ` Al Viro
2025-01-12 8:07 ` [PATCH v2 17/21] slub: " Al Viro
` (5 subsequent siblings)
20 siblings, 0 replies; 53+ messages in thread
From: Al Viro @ 2025-01-12 8:07 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
sound/soc/sof/sof-client-ipc-flood-test.c | 39 +++++++----------------
1 file changed, 12 insertions(+), 27 deletions(-)
diff --git a/sound/soc/sof/sof-client-ipc-flood-test.c b/sound/soc/sof/sof-client-ipc-flood-test.c
index b35c98896968..11b6f7da2882 100644
--- a/sound/soc/sof/sof-client-ipc-flood-test.c
+++ b/sound/soc/sof/sof-client-ipc-flood-test.c
@@ -158,7 +158,6 @@ static ssize_t sof_ipc_flood_dfs_write(struct file *file, const char __user *buf
unsigned long ipc_duration_ms = 0;
bool flood_duration_test = false;
unsigned long ipc_count = 0;
- struct dentry *dentry;
int err;
char *string;
int ret;
@@ -182,14 +181,7 @@ static ssize_t sof_ipc_flood_dfs_write(struct file *file, const char __user *buf
* ipc_duration_ms test floods the DSP for the time specified
* in the debugfs entry.
*/
- dentry = file->f_path.dentry;
- if (strcmp(dentry->d_name.name, DEBUGFS_IPC_FLOOD_COUNT) &&
- strcmp(dentry->d_name.name, DEBUGFS_IPC_FLOOD_DURATION)) {
- ret = -EINVAL;
- goto out;
- }
-
- if (!strcmp(dentry->d_name.name, DEBUGFS_IPC_FLOOD_DURATION))
+ if (debugfs_get_aux_num(file))
flood_duration_test = true;
/* test completion criterion */
@@ -252,22 +244,15 @@ static ssize_t sof_ipc_flood_dfs_read(struct file *file, char __user *buffer,
struct sof_ipc_flood_priv *priv = cdev->data;
size_t size_ret;
- struct dentry *dentry;
+ if (*ppos)
+ return 0;
- dentry = file->f_path.dentry;
- if (!strcmp(dentry->d_name.name, DEBUGFS_IPC_FLOOD_COUNT) ||
- !strcmp(dentry->d_name.name, DEBUGFS_IPC_FLOOD_DURATION)) {
- if (*ppos)
- return 0;
+ count = min_t(size_t, count, strlen(priv->buf));
+ size_ret = copy_to_user(buffer, priv->buf, count);
+ if (size_ret)
+ return -EFAULT;
- count = min_t(size_t, count, strlen(priv->buf));
- size_ret = copy_to_user(buffer, priv->buf, count);
- if (size_ret)
- return -EFAULT;
-
- *ppos += count;
- return count;
- }
+ *ppos += count;
return count;
}
@@ -320,12 +305,12 @@ static int sof_ipc_flood_probe(struct auxiliary_device *auxdev,
priv->dfs_root = debugfs_create_dir(dev_name(dev), debugfs_root);
if (!IS_ERR_OR_NULL(priv->dfs_root)) {
/* create read-write ipc_flood_count debugfs entry */
- debugfs_create_file(DEBUGFS_IPC_FLOOD_COUNT, 0644, priv->dfs_root,
- cdev, &sof_ipc_flood_fops);
+ debugfs_create_file_aux_num(DEBUGFS_IPC_FLOOD_COUNT, 0644,
+ priv->dfs_root, cdev, 0, &sof_ipc_flood_fops);
/* create read-write ipc_flood_duration_ms debugfs entry */
- debugfs_create_file(DEBUGFS_IPC_FLOOD_DURATION, 0644,
- priv->dfs_root, cdev, &sof_ipc_flood_fops);
+ debugfs_create_file_aux_num(DEBUGFS_IPC_FLOOD_DURATION, 0644,
+ priv->dfs_root, cdev, 1, &sof_ipc_flood_fops);
if (auxdev->id == 0) {
/*
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH v2 17/21] slub: don't mess with ->d_name
2025-01-12 8:06 ` [PATCH v2 01/21] debugfs: separate cache for debugfs inodes Al Viro
` (14 preceding siblings ...)
2025-01-12 8:07 ` [PATCH v2 16/21] sof-client-ipc-flood-test: " Al Viro
@ 2025-01-12 8:07 ` Al Viro
2025-01-12 8:07 ` [PATCH v2 18/21] arm_scmi: don't mess with ->d_parent->d_name Al Viro
` (4 subsequent siblings)
20 siblings, 0 replies; 53+ messages in thread
From: Al Viro @ 2025-01-12 8:07 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
mm/slub.c | 13 +++++--------
1 file changed, 5 insertions(+), 8 deletions(-)
diff --git a/mm/slub.c b/mm/slub.c
index c2151c9fee22..4f006b047552 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -7513,10 +7513,7 @@ static int slab_debug_trace_open(struct inode *inode, struct file *filep)
return -ENOMEM;
}
- if (strcmp(filep->f_path.dentry->d_name.name, "alloc_traces") == 0)
- alloc = TRACK_ALLOC;
- else
- alloc = TRACK_FREE;
+ alloc = debugfs_get_aux_num(filep);
if (!alloc_loc_track(t, PAGE_SIZE / sizeof(struct location), GFP_KERNEL)) {
bitmap_free(obj_map);
@@ -7572,11 +7569,11 @@ static void debugfs_slab_add(struct kmem_cache *s)
slab_cache_dir = debugfs_create_dir(s->name, slab_debugfs_root);
- debugfs_create_file("alloc_traces", 0400,
- slab_cache_dir, s, &slab_debugfs_fops);
+ debugfs_create_file_aux_num("alloc_traces", 0400, slab_cache_dir, s,
+ TRACK_ALLOC, &slab_debugfs_fops);
- debugfs_create_file("free_traces", 0400,
- slab_cache_dir, s, &slab_debugfs_fops);
+ debugfs_create_file_aux_num("free_traces", 0400, slab_cache_dir, s,
+ TRACK_FREE, &slab_debugfs_fops);
}
void debugfs_slab_release(struct kmem_cache *s)
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH v2 18/21] arm_scmi: don't mess with ->d_parent->d_name
2025-01-12 8:06 ` [PATCH v2 01/21] debugfs: separate cache for debugfs inodes Al Viro
` (15 preceding siblings ...)
2025-01-12 8:07 ` [PATCH v2 17/21] slub: " Al Viro
@ 2025-01-12 8:07 ` Al Viro
2025-01-12 8:07 ` [PATCH v2 19/21] octeontx2: don't mess with ->d_parent or ->d_parent->d_name Al Viro
` (3 subsequent siblings)
20 siblings, 0 replies; 53+ messages in thread
From: Al Viro @ 2025-01-12 8:07 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
drivers/firmware/arm_scmi/raw_mode.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/firmware/arm_scmi/raw_mode.c b/drivers/firmware/arm_scmi/raw_mode.c
index 9e89a6a763da..7cc0d616b8de 100644
--- a/drivers/firmware/arm_scmi/raw_mode.c
+++ b/drivers/firmware/arm_scmi/raw_mode.c
@@ -886,10 +886,8 @@ static __poll_t scmi_dbg_raw_mode_message_poll(struct file *filp,
static int scmi_dbg_raw_mode_open(struct inode *inode, struct file *filp)
{
- u8 id;
struct scmi_raw_mode_info *raw;
struct scmi_dbg_raw_data *rd;
- const char *id_str = filp->f_path.dentry->d_parent->d_name.name;
if (!inode->i_private)
return -ENODEV;
@@ -915,8 +913,8 @@ static int scmi_dbg_raw_mode_open(struct inode *inode, struct file *filp)
}
/* Grab channel ID from debugfs entry naming if any */
- if (!kstrtou8(id_str, 16, &id))
- rd->chan_id = id;
+ /* not set - reassing 0 we already had after kzalloc() */
+ rd->chan_id = debugfs_get_aux_num(filp);
rd->raw = raw;
filp->private_data = rd;
@@ -1225,10 +1223,12 @@ void *scmi_raw_mode_init(const struct scmi_handle *handle,
snprintf(cdir, 8, "0x%02X", channels[i]);
chd = debugfs_create_dir(cdir, top_chans);
- debugfs_create_file("message", 0600, chd, raw,
+ debugfs_create_file_aux_num("message", 0600, chd,
+ raw, channels[i],
&scmi_dbg_raw_mode_message_fops);
- debugfs_create_file("message_async", 0600, chd, raw,
+ debugfs_create_file_aux_num("message_async", 0600, chd,
+ raw, channels[i],
&scmi_dbg_raw_mode_message_async_fops);
}
}
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH v2 19/21] octeontx2: don't mess with ->d_parent or ->d_parent->d_name
2025-01-12 8:06 ` [PATCH v2 01/21] debugfs: separate cache for debugfs inodes Al Viro
` (16 preceding siblings ...)
2025-01-12 8:07 ` [PATCH v2 18/21] arm_scmi: don't mess with ->d_parent->d_name Al Viro
@ 2025-01-12 8:07 ` Al Viro
2025-01-12 8:07 ` [PATCH v2 20/21] orangefs-debugfs: don't mess with ->d_name Al Viro
` (2 subsequent siblings)
20 siblings, 0 replies; 53+ messages in thread
From: Al Viro @ 2025-01-12 8:07 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
use debugfs_{create_file,get}_aux_num() instead.
[and for fsck sake, don't call variables filp - especially the
ones that are not even struct file *]
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
.../marvell/octeontx2/af/rvu_debugfs.c | 76 ++++++-------------
1 file changed, 24 insertions(+), 52 deletions(-)
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c
index 148144f5b61d..a1f9ec03c2ce 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c
@@ -917,19 +917,18 @@ static void print_npa_qsize(struct seq_file *m, struct rvu_pfvf *pfvf)
/* The 'qsize' entry dumps current Aura/Pool context Qsize
* and each context's current enable/disable status in a bitmap.
*/
-static int rvu_dbg_qsize_display(struct seq_file *filp, void *unsused,
+static int rvu_dbg_qsize_display(struct seq_file *s, void *unsused,
int blktype)
{
- void (*print_qsize)(struct seq_file *filp,
+ void (*print_qsize)(struct seq_file *s,
struct rvu_pfvf *pfvf) = NULL;
- struct dentry *current_dir;
struct rvu_pfvf *pfvf;
struct rvu *rvu;
int qsize_id;
u16 pcifunc;
int blkaddr;
- rvu = filp->private;
+ rvu = s->private;
switch (blktype) {
case BLKTYPE_NPA:
qsize_id = rvu->rvu_dbg.npa_qsize_id;
@@ -945,32 +944,28 @@ static int rvu_dbg_qsize_display(struct seq_file *filp, void *unsused,
return -EINVAL;
}
- if (blktype == BLKTYPE_NPA) {
+ if (blktype == BLKTYPE_NPA)
blkaddr = BLKADDR_NPA;
- } else {
- current_dir = filp->file->f_path.dentry->d_parent;
- blkaddr = (!strcmp(current_dir->d_name.name, "nix1") ?
- BLKADDR_NIX1 : BLKADDR_NIX0);
- }
+ else
+ blkaddr = debugfs_get_aux_num(s->file);
if (!rvu_dbg_is_valid_lf(rvu, blkaddr, qsize_id, &pcifunc))
return -EINVAL;
pfvf = rvu_get_pfvf(rvu, pcifunc);
- print_qsize(filp, pfvf);
+ print_qsize(s, pfvf);
return 0;
}
-static ssize_t rvu_dbg_qsize_write(struct file *filp,
+static ssize_t rvu_dbg_qsize_write(struct file *file,
const char __user *buffer, size_t count,
loff_t *ppos, int blktype)
{
char *blk_string = (blktype == BLKTYPE_NPA) ? "npa" : "nix";
- struct seq_file *seqfile = filp->private_data;
+ struct seq_file *seqfile = file->private_data;
char *cmd_buf, *cmd_buf_tmp, *subtoken;
struct rvu *rvu = seqfile->private;
- struct dentry *current_dir;
int blkaddr;
u16 pcifunc;
int ret, lf;
@@ -996,13 +991,10 @@ static ssize_t rvu_dbg_qsize_write(struct file *filp,
goto qsize_write_done;
}
- if (blktype == BLKTYPE_NPA) {
+ if (blktype == BLKTYPE_NPA)
blkaddr = BLKADDR_NPA;
- } else {
- current_dir = filp->f_path.dentry->d_parent;
- blkaddr = (!strcmp(current_dir->d_name.name, "nix1") ?
- BLKADDR_NIX1 : BLKADDR_NIX0);
- }
+ else
+ blkaddr = debugfs_get_aux_num(file);
if (!rvu_dbg_is_valid_lf(rvu, blkaddr, lf, &pcifunc)) {
ret = -EINVAL;
@@ -2704,8 +2696,8 @@ static void rvu_dbg_nix_init(struct rvu *rvu, int blkaddr)
&rvu_dbg_nix_ndc_tx_hits_miss_fops);
debugfs_create_file("ndc_rx_hits_miss", 0600, rvu->rvu_dbg.nix, nix_hw,
&rvu_dbg_nix_ndc_rx_hits_miss_fops);
- debugfs_create_file("qsize", 0600, rvu->rvu_dbg.nix, rvu,
- &rvu_dbg_nix_qsize_fops);
+ debugfs_create_file_aux_num("qsize", 0600, rvu->rvu_dbg.nix, rvu,
+ blkaddr, &rvu_dbg_nix_qsize_fops);
debugfs_create_file("ingress_policer_ctx", 0600, rvu->rvu_dbg.nix, nix_hw,
&rvu_dbg_nix_band_prof_ctx_fops);
debugfs_create_file("ingress_policer_rsrc", 0600, rvu->rvu_dbg.nix, nix_hw,
@@ -2854,28 +2846,14 @@ static int cgx_print_stats(struct seq_file *s, int lmac_id)
return err;
}
-static int rvu_dbg_derive_lmacid(struct seq_file *filp, int *lmac_id)
+static int rvu_dbg_derive_lmacid(struct seq_file *s)
{
- struct dentry *current_dir;
- char *buf;
-
- current_dir = filp->file->f_path.dentry->d_parent;
- buf = strrchr(current_dir->d_name.name, 'c');
- if (!buf)
- return -EINVAL;
-
- return kstrtoint(buf + 1, 10, lmac_id);
+ return debugfs_get_aux_num(s->file);
}
-static int rvu_dbg_cgx_stat_display(struct seq_file *filp, void *unused)
+static int rvu_dbg_cgx_stat_display(struct seq_file *s, void *unused)
{
- int lmac_id, err;
-
- err = rvu_dbg_derive_lmacid(filp, &lmac_id);
- if (!err)
- return cgx_print_stats(filp, lmac_id);
-
- return err;
+ return cgx_print_stats(s, rvu_dbg_derive_lmacid(s));
}
RVU_DEBUG_SEQ_FOPS(cgx_stat, cgx_stat_display, NULL);
@@ -2933,15 +2911,9 @@ static int cgx_print_dmac_flt(struct seq_file *s, int lmac_id)
return 0;
}
-static int rvu_dbg_cgx_dmac_flt_display(struct seq_file *filp, void *unused)
+static int rvu_dbg_cgx_dmac_flt_display(struct seq_file *s, void *unused)
{
- int err, lmac_id;
-
- err = rvu_dbg_derive_lmacid(filp, &lmac_id);
- if (!err)
- return cgx_print_dmac_flt(filp, lmac_id);
-
- return err;
+ return cgx_print_dmac_flt(s, rvu_dbg_derive_lmacid(s));
}
RVU_DEBUG_SEQ_FOPS(cgx_dmac_flt, cgx_dmac_flt_display, NULL);
@@ -2980,10 +2952,10 @@ static void rvu_dbg_cgx_init(struct rvu *rvu)
rvu->rvu_dbg.lmac =
debugfs_create_dir(dname, rvu->rvu_dbg.cgx);
- debugfs_create_file("stats", 0600, rvu->rvu_dbg.lmac,
- cgx, &rvu_dbg_cgx_stat_fops);
- debugfs_create_file("mac_filter", 0600,
- rvu->rvu_dbg.lmac, cgx,
+ debugfs_create_file_aux_num("stats", 0600, rvu->rvu_dbg.lmac,
+ cgx, lmac_id, &rvu_dbg_cgx_stat_fops);
+ debugfs_create_file_aux_num("mac_filter", 0600,
+ rvu->rvu_dbg.lmac, cgx, lmac_id,
&rvu_dbg_cgx_dmac_flt_fops);
}
}
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH v2 20/21] orangefs-debugfs: don't mess with ->d_name
2025-01-12 8:06 ` [PATCH v2 01/21] debugfs: separate cache for debugfs inodes Al Viro
` (17 preceding siblings ...)
2025-01-12 8:07 ` [PATCH v2 19/21] octeontx2: don't mess with ->d_parent or ->d_parent->d_name Al Viro
@ 2025-01-12 8:07 ` Al Viro
2025-01-12 8:07 ` [PATCH v2 21/21] saner replacement for debugfs_rename() Al Viro
2025-01-13 14:48 ` [PATCH v2 01/21] debugfs: separate cache for debugfs inodes Christian Brauner
20 siblings, 0 replies; 53+ messages in thread
From: Al Viro @ 2025-01-12 8:07 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/orangefs/orangefs-debugfs.c | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/fs/orangefs/orangefs-debugfs.c b/fs/orangefs/orangefs-debugfs.c
index 1b508f543384..9729f071c5aa 100644
--- a/fs/orangefs/orangefs-debugfs.c
+++ b/fs/orangefs/orangefs-debugfs.c
@@ -206,8 +206,8 @@ static void orangefs_kernel_debug_init(void)
pr_info("%s: overflow 1!\n", __func__);
}
- debugfs_create_file(ORANGEFS_KMOD_DEBUG_FILE, 0444, debug_dir, k_buffer,
- &kernel_debug_fops);
+ debugfs_create_file_aux_num(ORANGEFS_KMOD_DEBUG_FILE, 0444, debug_dir, k_buffer,
+ 0, &kernel_debug_fops);
}
@@ -306,11 +306,10 @@ static void orangefs_client_debug_init(void)
pr_info("%s: overflow! 2\n", __func__);
}
- client_debug_dentry = debugfs_create_file(ORANGEFS_CLIENT_DEBUG_FILE,
- 0444,
- debug_dir,
- c_buffer,
- &kernel_debug_fops);
+ client_debug_dentry = debugfs_create_file_aux_num(
+ ORANGEFS_CLIENT_DEBUG_FILE,
+ 0444, debug_dir, c_buffer, 1,
+ &kernel_debug_fops);
}
/* open ORANGEFS_KMOD_DEBUG_FILE or ORANGEFS_CLIENT_DEBUG_FILE.*/
@@ -418,8 +417,7 @@ static ssize_t orangefs_debug_write(struct file *file,
* A service operation is required to set a new client-side
* debug mask.
*/
- if (!strcmp(file->f_path.dentry->d_name.name,
- ORANGEFS_KMOD_DEBUG_FILE)) {
+ if (!debugfs_get_aux_num(file)) { // kernel-debug
debug_string_to_mask(buf, &orangefs_gossip_debug_mask, 0);
debug_mask_to_string(&orangefs_gossip_debug_mask, 0);
debug_string = kernel_debug_string;
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [PATCH v2 21/21] saner replacement for debugfs_rename()
2025-01-12 8:06 ` [PATCH v2 01/21] debugfs: separate cache for debugfs inodes Al Viro
` (18 preceding siblings ...)
2025-01-12 8:07 ` [PATCH v2 20/21] orangefs-debugfs: don't mess with ->d_name Al Viro
@ 2025-01-12 8:07 ` Al Viro
2025-01-13 14:48 ` [PATCH v2 01/21] debugfs: separate cache for debugfs inodes Christian Brauner
20 siblings, 0 replies; 53+ messages in thread
From: Al Viro @ 2025-01-12 8:07 UTC (permalink / raw)
To: linux-fsdevel; +Cc: gregkh
Existing primitive has several problems:
1) calling conventions are clumsy - it returns a dentry reference
that is either identical to its second argument or is an ERR_PTR(-E...);
in both cases no refcount changes happen. Inconvenient for users and
bug-prone; it would be better to have it return 0 on success and -E... on
failure.
2) it allows cross-directory moves; however, no such caller have
ever materialized and considering the way debugfs is used, it's unlikely
to happen in the future. What's more, any such caller would have fun
issues to deal with wrt interplay with recursive removal. It also makes
the calling conventions clumsier...
3) tautological rename fails; the callers have no race-free way
to deal with that.
4) new name must have been formed by the caller; quite a few
callers have it done by sprintf/kasprintf/etc., ending up with considerable
boilerplate.
Proposed replacement: int debugfs_change_name(dentry, fmt, ...). All callers
convert to that easily, and it's simpler internally.
IMO debugfs_rename() should go; if we ever get a real-world use case for
cross-directory moves in debugfs, we can always look into the right way
to handle that.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
Documentation/filesystems/debugfs.rst | 12 +-
drivers/net/bonding/bond_debugfs.c | 9 +-
drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c | 19 +---
drivers/net/ethernet/marvell/skge.c | 5 +-
drivers/net/ethernet/marvell/sky2.c | 5 +-
.../net/ethernet/stmicro/stmmac/stmmac_main.c | 6 +-
drivers/opp/debugfs.c | 10 +-
fs/debugfs/inode.c | 106 +++++++++---------
include/linux/debugfs.h | 9 +-
mm/shrinker_debug.c | 16 +--
net/hsr/hsr_debugfs.c | 9 +-
net/mac80211/debugfs_netdev.c | 11 +-
net/wireless/core.c | 5 +-
13 files changed, 77 insertions(+), 145 deletions(-)
diff --git a/Documentation/filesystems/debugfs.rst b/Documentation/filesystems/debugfs.rst
index dc35da8b8792..f7f977ffbf8d 100644
--- a/Documentation/filesystems/debugfs.rst
+++ b/Documentation/filesystems/debugfs.rst
@@ -211,18 +211,16 @@ seq_file content.
There are a couple of other directory-oriented helper functions::
- struct dentry *debugfs_rename(struct dentry *old_dir,
- struct dentry *old_dentry,
- struct dentry *new_dir,
- const char *new_name);
+ struct dentry *debugfs_change_name(struct dentry *dentry,
+ const char *fmt, ...);
struct dentry *debugfs_create_symlink(const char *name,
struct dentry *parent,
const char *target);
-A call to debugfs_rename() will give a new name to an existing debugfs
-file, possibly in a different directory. The new_name must not exist prior
-to the call; the return value is old_dentry with updated information.
+A call to debugfs_change_name() will give a new name to an existing debugfs
+file, always in the same directory. The new_name must not exist prior
+to the call; the return value is 0 on success and -E... on failuer.
Symbolic links can be created with debugfs_create_symlink().
There is one important thing that all debugfs users must take into account:
diff --git a/drivers/net/bonding/bond_debugfs.c b/drivers/net/bonding/bond_debugfs.c
index b19492a7f6ad..8adbec7c5084 100644
--- a/drivers/net/bonding/bond_debugfs.c
+++ b/drivers/net/bonding/bond_debugfs.c
@@ -63,13 +63,8 @@ void bond_debug_unregister(struct bonding *bond)
void bond_debug_reregister(struct bonding *bond)
{
- struct dentry *d;
-
- d = debugfs_rename(bonding_debug_root, bond->debug_dir,
- bonding_debug_root, bond->dev->name);
- if (!IS_ERR(d)) {
- bond->debug_dir = d;
- } else {
+ int err = debugfs_change_name(bond->debug_dir, "%s", bond->dev->name);
+ if (err) {
netdev_warn(bond->dev, "failed to reregister, so just unregister old one\n");
bond_debug_unregister(bond);
}
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c b/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
index b0a6c96b6ef4..b35808d3d07f 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
@@ -505,21 +505,6 @@ void xgbe_debugfs_exit(struct xgbe_prv_data *pdata)
void xgbe_debugfs_rename(struct xgbe_prv_data *pdata)
{
- char *buf;
-
- if (!pdata->xgbe_debugfs)
- return;
-
- buf = kasprintf(GFP_KERNEL, "amd-xgbe-%s", pdata->netdev->name);
- if (!buf)
- return;
-
- if (!strcmp(pdata->xgbe_debugfs->d_name.name, buf))
- goto out;
-
- debugfs_rename(pdata->xgbe_debugfs->d_parent, pdata->xgbe_debugfs,
- pdata->xgbe_debugfs->d_parent, buf);
-
-out:
- kfree(buf);
+ debugfs_change_name(pdata->xgbe_debugfs,
+ "amd-xgbe-%s", pdata->netdev->name);
}
diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c
index 25bf6ec44289..a1bada9eaaf6 100644
--- a/drivers/net/ethernet/marvell/skge.c
+++ b/drivers/net/ethernet/marvell/skge.c
@@ -3742,10 +3742,7 @@ static int skge_device_event(struct notifier_block *unused,
skge = netdev_priv(dev);
switch (event) {
case NETDEV_CHANGENAME:
- if (skge->debugfs)
- skge->debugfs = debugfs_rename(skge_debug,
- skge->debugfs,
- skge_debug, dev->name);
+ debugfs_change_name(skge->debugfs, "%s", dev->name);
break;
case NETDEV_GOING_DOWN:
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index 3914cd9210d4..719ae94a5f97 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -4493,10 +4493,7 @@ static int sky2_device_event(struct notifier_block *unused,
switch (event) {
case NETDEV_CHANGENAME:
- if (sky2->debugfs) {
- sky2->debugfs = debugfs_rename(sky2_debug, sky2->debugfs,
- sky2_debug, dev->name);
- }
+ debugfs_change_name(sky2->debugfs, "%s", dev->name);
break;
case NETDEV_GOING_DOWN:
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index c81ea8cdfe6e..82e2908016bd 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -6489,11 +6489,7 @@ static int stmmac_device_event(struct notifier_block *unused,
switch (event) {
case NETDEV_CHANGENAME:
- if (priv->dbgfs_dir)
- priv->dbgfs_dir = debugfs_rename(stmmac_fs_dir,
- priv->dbgfs_dir,
- stmmac_fs_dir,
- dev->name);
+ debugfs_change_name(priv->dbgfs_dir, "%s", dev->name);
break;
}
done:
diff --git a/drivers/opp/debugfs.c b/drivers/opp/debugfs.c
index 105de7c3274a..8fc6238b1728 100644
--- a/drivers/opp/debugfs.c
+++ b/drivers/opp/debugfs.c
@@ -217,7 +217,7 @@ static void opp_migrate_dentry(struct opp_device *opp_dev,
{
struct opp_device *new_dev = NULL, *iter;
const struct device *dev;
- struct dentry *dentry;
+ int err;
/* Look for next opp-dev */
list_for_each_entry(iter, &opp_table->dev_list, node)
@@ -234,16 +234,14 @@ static void opp_migrate_dentry(struct opp_device *opp_dev,
opp_set_dev_name(dev, opp_table->dentry_name);
- dentry = debugfs_rename(rootdir, opp_dev->dentry, rootdir,
- opp_table->dentry_name);
- if (IS_ERR(dentry)) {
+ err = debugfs_change_name(opp_dev->dentry, "%s", opp_table->dentry_name);
+ if (err) {
dev_err(dev, "%s: Failed to rename link from: %s to %s\n",
__func__, dev_name(opp_dev->dev), dev_name(dev));
return;
}
- new_dev->dentry = dentry;
- opp_table->dentry = dentry;
+ new_dev->dentry = opp_table->dentry = opp_dev->dentry;
}
/**
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index 51d4c3e9d422..75715d8877ee 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -830,76 +830,70 @@ void debugfs_lookup_and_remove(const char *name, struct dentry *parent)
EXPORT_SYMBOL_GPL(debugfs_lookup_and_remove);
/**
- * debugfs_rename - rename a file/directory in the debugfs filesystem
- * @old_dir: a pointer to the parent dentry for the renamed object. This
- * should be a directory dentry.
- * @old_dentry: dentry of an object to be renamed.
- * @new_dir: a pointer to the parent dentry where the object should be
- * moved. This should be a directory dentry.
- * @new_name: a pointer to a string containing the target name.
+ * debugfs_change_name - rename a file/directory in the debugfs filesystem
+ * @dentry: dentry of an object to be renamed.
+ * @fmt: format for new name
*
* This function renames a file/directory in debugfs. The target must not
* exist for rename to succeed.
*
- * This function will return a pointer to old_dentry (which is updated to
- * reflect renaming) if it succeeds. If an error occurs, ERR_PTR(-ERROR)
- * will be returned.
+ * This function will return 0 on success and -E... on failure.
*
* If debugfs is not enabled in the kernel, the value -%ENODEV will be
* returned.
*/
-struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
- struct dentry *new_dir, const char *new_name)
+int __printf(2, 3) debugfs_change_name(struct dentry *dentry, const char *fmt, ...)
{
- int error;
- struct dentry *dentry = NULL, *trap;
+ int error = 0;
+ const char *new_name;
struct name_snapshot old_name;
+ struct dentry *parent, *target;
+ struct inode *dir;
+ va_list ap;
- if (IS_ERR(old_dir))
- return old_dir;
- if (IS_ERR(new_dir))
- return new_dir;
- if (IS_ERR_OR_NULL(old_dentry))
- return old_dentry;
-
- trap = lock_rename(new_dir, old_dir);
- /* Source or destination directories don't exist? */
- if (d_really_is_negative(old_dir) || d_really_is_negative(new_dir))
- goto exit;
- /* Source does not exist, cyclic rename, or mountpoint? */
- if (d_really_is_negative(old_dentry) || old_dentry == trap ||
- d_mountpoint(old_dentry))
- goto exit;
- dentry = lookup_one_len(new_name, new_dir, strlen(new_name));
- /* Lookup failed, cyclic rename or target exists? */
- if (IS_ERR(dentry) || dentry == trap || d_really_is_positive(dentry))
- goto exit;
-
- take_dentry_name_snapshot(&old_name, old_dentry);
-
- error = simple_rename(&nop_mnt_idmap, d_inode(old_dir), old_dentry,
- d_inode(new_dir), dentry, 0);
- if (error) {
- release_dentry_name_snapshot(&old_name);
- goto exit;
+ if (IS_ERR_OR_NULL(dentry))
+ return 0;
+
+ va_start(ap, fmt);
+ new_name = kvasprintf_const(GFP_KERNEL, fmt, ap);
+ va_end(ap);
+ if (!new_name)
+ return -ENOMEM;
+
+ parent = dget_parent(dentry);
+ dir = d_inode(parent);
+ inode_lock(dir);
+
+ take_dentry_name_snapshot(&old_name, dentry);
+
+ if (WARN_ON_ONCE(dentry->d_parent != parent)) {
+ error = -EINVAL;
+ goto out;
+ }
+ if (strcmp(old_name.name.name, new_name) == 0)
+ goto out;
+ target = lookup_one_len(new_name, parent, strlen(new_name));
+ if (IS_ERR(target)) {
+ error = PTR_ERR(target);
+ goto out;
}
- d_move(old_dentry, dentry);
- fsnotify_move(d_inode(old_dir), d_inode(new_dir), &old_name.name,
- d_is_dir(old_dentry),
- NULL, old_dentry);
+ if (d_really_is_positive(target)) {
+ dput(target);
+ error = -EINVAL;
+ goto out;
+ }
+ simple_rename_timestamp(dir, dentry, dir, target);
+ d_move(dentry, target);
+ dput(target);
+ fsnotify_move(dir, dir, &old_name.name, d_is_dir(dentry), NULL, dentry);
+out:
release_dentry_name_snapshot(&old_name);
- unlock_rename(new_dir, old_dir);
- dput(dentry);
- return old_dentry;
-exit:
- if (dentry && !IS_ERR(dentry))
- dput(dentry);
- unlock_rename(new_dir, old_dir);
- if (IS_ERR(dentry))
- return dentry;
- return ERR_PTR(-EINVAL);
+ inode_unlock(dir);
+ dput(parent);
+ kfree_const(new_name);
+ return error;
}
-EXPORT_SYMBOL_GPL(debugfs_rename);
+EXPORT_SYMBOL_GPL(debugfs_change_name);
/**
* debugfs_initialized - Tells whether debugfs has been registered
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h
index 68e9c6cbd835..fa2568b4380d 100644
--- a/include/linux/debugfs.h
+++ b/include/linux/debugfs.h
@@ -175,8 +175,7 @@ ssize_t debugfs_attr_write(struct file *file, const char __user *buf,
ssize_t debugfs_attr_write_signed(struct file *file, const char __user *buf,
size_t len, loff_t *ppos);
-struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
- struct dentry *new_dir, const char *new_name);
+int debugfs_change_name(struct dentry *dentry, const char *fmt, ...) __printf(2, 3);
void debugfs_create_u8(const char *name, umode_t mode, struct dentry *parent,
u8 *value);
@@ -361,10 +360,10 @@ static inline ssize_t debugfs_attr_write_signed(struct file *file,
return -ENODEV;
}
-static inline struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
- struct dentry *new_dir, char *new_name)
+static inline int __printf(2, 3) debugfs_change_name(struct dentry *dentry,
+ const char *fmt, ...)
{
- return ERR_PTR(-ENODEV);
+ return -ENODEV;
}
static inline void debugfs_create_u8(const char *name, umode_t mode,
diff --git a/mm/shrinker_debug.c b/mm/shrinker_debug.c
index 4a85b94d12ce..794bd433cce0 100644
--- a/mm/shrinker_debug.c
+++ b/mm/shrinker_debug.c
@@ -195,8 +195,6 @@ int shrinker_debugfs_add(struct shrinker *shrinker)
int shrinker_debugfs_rename(struct shrinker *shrinker, const char *fmt, ...)
{
- struct dentry *entry;
- char buf[128];
const char *new, *old;
va_list ap;
int ret = 0;
@@ -213,18 +211,8 @@ int shrinker_debugfs_rename(struct shrinker *shrinker, const char *fmt, ...)
old = shrinker->name;
shrinker->name = new;
- if (shrinker->debugfs_entry) {
- snprintf(buf, sizeof(buf), "%s-%d", shrinker->name,
- shrinker->debugfs_id);
-
- entry = debugfs_rename(shrinker_debugfs_root,
- shrinker->debugfs_entry,
- shrinker_debugfs_root, buf);
- if (IS_ERR(entry))
- ret = PTR_ERR(entry);
- else
- shrinker->debugfs_entry = entry;
- }
+ ret = debugfs_change_name(shrinker->debugfs_entry, "%s-%d",
+ shrinker->name, shrinker->debugfs_id);
mutex_unlock(&shrinker_mutex);
diff --git a/net/hsr/hsr_debugfs.c b/net/hsr/hsr_debugfs.c
index 1a195efc79cd..5b2cfac3b2ba 100644
--- a/net/hsr/hsr_debugfs.c
+++ b/net/hsr/hsr_debugfs.c
@@ -57,14 +57,11 @@ DEFINE_SHOW_ATTRIBUTE(hsr_node_table);
void hsr_debugfs_rename(struct net_device *dev)
{
struct hsr_priv *priv = netdev_priv(dev);
- struct dentry *d;
+ int err;
- d = debugfs_rename(hsr_debugfs_root_dir, priv->node_tbl_root,
- hsr_debugfs_root_dir, dev->name);
- if (IS_ERR(d))
+ err = debugfs_change_name(priv->node_tbl_root, "%s", dev->name);
+ if (err)
netdev_warn(dev, "failed to rename\n");
- else
- priv->node_tbl_root = d;
}
/* hsr_debugfs_init - create hsr node_table file for dumping
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index a9bc2fd59f55..9fa38c489edc 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -1025,16 +1025,7 @@ void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata)
void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata)
{
- struct dentry *dir;
- char buf[10 + IFNAMSIZ];
-
- dir = sdata->vif.debugfs_dir;
-
- if (IS_ERR_OR_NULL(dir))
- return;
-
- sprintf(buf, "netdev:%s", sdata->name);
- debugfs_rename(dir->d_parent, dir, dir->d_parent, buf);
+ debugfs_change_name(sdata->vif.debugfs_dir, "netdev:%s", sdata->name);
}
void ieee80211_debugfs_recreate_netdev(struct ieee80211_sub_if_data *sdata,
diff --git a/net/wireless/core.c b/net/wireless/core.c
index afbdc549fb4a..9130cb872ed3 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -143,10 +143,7 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
if (result)
return result;
- if (!IS_ERR_OR_NULL(rdev->wiphy.debugfsdir))
- debugfs_rename(rdev->wiphy.debugfsdir->d_parent,
- rdev->wiphy.debugfsdir,
- rdev->wiphy.debugfsdir->d_parent, newname);
+ debugfs_change_name(rdev->wiphy.debugfsdir, "%s", newname);
nl80211_notify_wiphy(rdev, NL80211_CMD_NEW_WIPHY);
--
2.39.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* Re: [PATCH v2 01/21] debugfs: separate cache for debugfs inodes
2025-01-12 8:06 ` [PATCH v2 01/21] debugfs: separate cache for debugfs inodes Al Viro
` (19 preceding siblings ...)
2025-01-12 8:07 ` [PATCH v2 21/21] saner replacement for debugfs_rename() Al Viro
@ 2025-01-13 14:48 ` Christian Brauner
20 siblings, 0 replies; 53+ messages in thread
From: Christian Brauner @ 2025-01-13 14:48 UTC (permalink / raw)
To: Al Viro; +Cc: linux-fsdevel, gregkh
On Sun, Jan 12, 2025 at 08:06:45AM +0000, Al Viro wrote:
> Embed them into container (struct debugfs_inode_info, with nothing
> else in it at the moment), set the cache up, etc.
>
> Just the infrastructure changes letting us augment debugfs inodes
> here; adding stuff will come at the next step.
>
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
Reviewed-by: Christian Brauner <brauner@kernel.org>
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH v2 02/21] debugfs: move ->automount into debugfs_inode_info
2025-01-12 8:06 ` [PATCH v2 02/21] debugfs: move ->automount into debugfs_inode_info Al Viro
@ 2025-01-13 14:49 ` Christian Brauner
0 siblings, 0 replies; 53+ messages in thread
From: Christian Brauner @ 2025-01-13 14:49 UTC (permalink / raw)
To: Al Viro; +Cc: linux-fsdevel, gregkh
On Sun, Jan 12, 2025 at 08:06:46AM +0000, Al Viro wrote:
> ... and don't bother with debugfs_fsdata for those. Life's
> simpler that way...
>
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
Reviewed-by: Christian Brauner <brauner@kernel.org>
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH v2 03/21] debugfs: get rid of dynamically allocation proxy_ops
2025-01-12 8:06 ` [PATCH v2 03/21] debugfs: get rid of dynamically allocation proxy_ops Al Viro
@ 2025-01-13 14:51 ` Christian Brauner
0 siblings, 0 replies; 53+ messages in thread
From: Christian Brauner @ 2025-01-13 14:51 UTC (permalink / raw)
To: Al Viro; +Cc: linux-fsdevel, gregkh
On Sun, Jan 12, 2025 at 08:06:47AM +0000, Al Viro wrote:
> All it takes is having full_proxy_open() collect the information
> about available methods and store it in debugfs_fsdata.
>
> Wrappers are called only after full_proxy_open() has succeeded
> calling debugfs_get_file(), so they are guaranteed to have
> ->d_fsdata already pointing to debugfs_fsdata.
>
> As the result, they can check if method is absent and bugger off
> early, without any atomic operations, etc. - same effect as what
> we'd have from NULL method. Which makes the entire proxy_fops
> contents unconditional, making it completely pointless - we can
> just put those methods (unconditionally) into
> debugfs_full_proxy_file_operations and forget about dynamic
> allocation, replace_fops, etc.
>
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
Reviewed-by: Christian Brauner <brauner@kernel.org>
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH v2 04/21] debugfs: don't mess with bits in ->d_fsdata
2025-01-12 8:06 ` [PATCH v2 04/21] debugfs: don't mess with bits in ->d_fsdata Al Viro
@ 2025-01-13 14:55 ` Christian Brauner
0 siblings, 0 replies; 53+ messages in thread
From: Christian Brauner @ 2025-01-13 14:55 UTC (permalink / raw)
To: Al Viro; +Cc: linux-fsdevel, gregkh
On Sun, Jan 12, 2025 at 08:06:48AM +0000, Al Viro wrote:
> The reason we need that crap is the dual use ->d_fsdata has there -
> it's both holding a debugfs_fsdata reference after the first
> debugfs_file_get() (actually, after the call of proxy ->open())
> *and* it serves as a place to stash a reference to real file_operations
> from object creation to the first open. Oh, and it's triple use,
> actually - that stashed reference might be to debugfs_short_fops.
>
> Bugger that for a game of solidiers - just put the operations
The most confusing part of this patch is this sentence. :)
"game of solidiers"?
> reference into debugfs-private augmentation of inode. And split
> debugfs_full_file_operations into full and short cases, so that
> debugfs_get_file() could tell one from another.
>
> Voila - ->d_fsdata holds NULL until the first (successful) debugfs_get_file()
> and a reference to struct debugfs_fsdata afterwards.
>
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
Reviewed-by: Christian Brauner <brauner@kernel.org>
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH v2 05/21] debugfs: allow to store an additional opaque pointer at file creation
2025-01-12 8:06 ` [PATCH v2 05/21] debugfs: allow to store an additional opaque pointer at file creation Al Viro
@ 2025-01-13 14:56 ` Christian Brauner
0 siblings, 0 replies; 53+ messages in thread
From: Christian Brauner @ 2025-01-13 14:56 UTC (permalink / raw)
To: Al Viro; +Cc: linux-fsdevel, gregkh
On Sun, Jan 12, 2025 at 08:06:49AM +0000, Al Viro wrote:
> Set by debugfs_create_file_aux(name, mode, parent, data, aux, fops).
> Plain debugfs_create_file() has it set to NULL.
> Accessed by debugfs_get_aux(file).
>
> Convenience macros for numeric opaque data - debugfs_create_file_aux_num
> and debugfs_get_aux_num, resp.
>
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
Reviewed-by: Christian Brauner <brauner@kernel.org>
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH v2 06/21] debugfs: take debugfs_short_fops definition out of ifdef
2025-01-12 8:06 ` [PATCH v2 06/21] debugfs: take debugfs_short_fops definition out of ifdef Al Viro
@ 2025-01-13 14:57 ` Christian Brauner
0 siblings, 0 replies; 53+ messages in thread
From: Christian Brauner @ 2025-01-13 14:57 UTC (permalink / raw)
To: Al Viro; +Cc: linux-fsdevel, gregkh
On Sun, Jan 12, 2025 at 08:06:50AM +0000, Al Viro wrote:
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
Reviewed-by: Christian Brauner <brauner@kernel.org>
^ permalink raw reply [flat|nested] 53+ messages in thread
end of thread, other threads:[~2025-01-13 14:57 UTC | newest]
Thread overview: 53+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-12-29 8:09 [PATCHES][RFC][CFT] debugfs cleanups Al Viro
2024-12-29 8:12 ` [PATCH 01/20] debugfs: fix missing mutex_destroy() in short_fops case Al Viro
2024-12-29 8:12 ` [PATCH 02/20] debugfs: separate cache for debugfs inodes Al Viro
2024-12-29 8:12 ` [PATCH 03/20] debugfs: move ->automount into debugfs_inode_info Al Viro
2024-12-29 8:12 ` [PATCH 04/20] debugfs: get rid of dynamically allocation proxy_ops Al Viro
2024-12-29 8:12 ` [PATCH 05/20] debugfs: don't mess with bits in ->d_fsdata Al Viro
2024-12-29 8:12 ` [PATCH 06/20] debugfs: allow to store an additional opaque pointer at file creation Al Viro
2024-12-29 8:12 ` [PATCH 07/20] carl9170: stop embedding file_operations into their objects Al Viro
2024-12-29 8:12 ` [PATCH 08/20] b43: stop embedding struct " Al Viro
2024-12-29 8:12 ` [PATCH 09/20] b43legacy: make use of debugfs_get_aux() Al Viro
2024-12-29 8:12 ` [PATCH 10/20] netdevsim: don't embed file_operations into your structs Al Viro
2024-12-29 8:12 ` [PATCH 11/20] mediatek: stop messing with ->d_iname Al Viro
2024-12-29 8:12 ` [PATCH 12/20] [not even compile-tested] greybus/camera - " Al Viro
2024-12-29 8:12 ` [PATCH 13/20] mtu3: don't mess wiht ->d_iname Al Viro
2024-12-29 8:12 ` [PATCH 14/20] xhci: don't mess with ->d_iname Al Viro
2024-12-29 8:12 ` [PATCH 15/20] qat: don't mess with ->d_name Al Viro
2024-12-29 8:12 ` [PATCH 16/20] sof-client-ipc-flood-test: " Al Viro
2024-12-29 8:12 ` [PATCH 17/20] slub: " Al Viro
2024-12-29 8:12 ` [PATCH 18/20] arm_scmi: don't mess with ->d_parent->d_name Al Viro
2024-12-29 8:12 ` [PATCH 19/20] octeontx2: don't mess with ->d_parent or ->d_parent->d_name Al Viro
2024-12-29 8:12 ` [PATCH 20/20] saner replacement for debugfs_rename() Al Viro
2024-12-29 16:38 ` Al Viro
2025-01-07 15:20 ` [PATCH 01/20] debugfs: fix missing mutex_destroy() in short_fops case Greg KH
2024-12-29 20:58 ` [PATCHES][RFC][CFT] debugfs cleanups Al Viro
2025-01-07 14:56 ` Greg KH
2025-01-12 8:05 ` [PATCHES v2][RFC][CFT] " Al Viro
2025-01-12 8:06 ` [PATCH v2 01/21] debugfs: separate cache for debugfs inodes Al Viro
2025-01-12 8:06 ` [PATCH v2 02/21] debugfs: move ->automount into debugfs_inode_info Al Viro
2025-01-13 14:49 ` Christian Brauner
2025-01-12 8:06 ` [PATCH v2 03/21] debugfs: get rid of dynamically allocation proxy_ops Al Viro
2025-01-13 14:51 ` Christian Brauner
2025-01-12 8:06 ` [PATCH v2 04/21] debugfs: don't mess with bits in ->d_fsdata Al Viro
2025-01-13 14:55 ` Christian Brauner
2025-01-12 8:06 ` [PATCH v2 05/21] debugfs: allow to store an additional opaque pointer at file creation Al Viro
2025-01-13 14:56 ` Christian Brauner
2025-01-12 8:06 ` [PATCH v2 06/21] debugfs: take debugfs_short_fops definition out of ifdef Al Viro
2025-01-13 14:57 ` Christian Brauner
2025-01-12 8:06 ` [PATCH v2 07/21] carl9170: stop embedding file_operations into their objects Al Viro
2025-01-12 8:06 ` [PATCH v2 08/21] b43: stop embedding struct " Al Viro
2025-01-12 8:06 ` [PATCH v2 09/21] b43legacy: make use of debugfs_get_aux() Al Viro
2025-01-12 8:06 ` [PATCH v2 10/21] netdevsim: don't embed file_operations into your structs Al Viro
2025-01-12 8:06 ` [PATCH v2 11/21] mediatek: stop messing with ->d_iname Al Viro
2025-01-12 8:06 ` [PATCH v2 12/21] [not even compile-tested] greybus/camera - " Al Viro
2025-01-12 8:06 ` [PATCH v2 13/21] mtu3: don't mess wiht ->d_iname Al Viro
2025-01-12 8:06 ` [PATCH v2 14/21] xhci: don't mess with ->d_iname Al Viro
2025-01-12 8:06 ` [PATCH v2 15/21] qat: don't mess with ->d_name Al Viro
2025-01-12 8:07 ` [PATCH v2 16/21] sof-client-ipc-flood-test: " Al Viro
2025-01-12 8:07 ` [PATCH v2 17/21] slub: " Al Viro
2025-01-12 8:07 ` [PATCH v2 18/21] arm_scmi: don't mess with ->d_parent->d_name Al Viro
2025-01-12 8:07 ` [PATCH v2 19/21] octeontx2: don't mess with ->d_parent or ->d_parent->d_name Al Viro
2025-01-12 8:07 ` [PATCH v2 20/21] orangefs-debugfs: don't mess with ->d_name Al Viro
2025-01-12 8:07 ` [PATCH v2 21/21] saner replacement for debugfs_rename() Al Viro
2025-01-13 14:48 ` [PATCH v2 01/21] debugfs: separate cache for debugfs inodes Christian Brauner
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox