[PATCH v2] tracefs: Use dentry name snapshots instead of heap allocation
From: AnishMulay
Date: Fri Feb 27 2026 - 16:15:19 EST
In fs/tracefs/inode.c, tracefs_syscall_mkdir() and tracefs_syscall_rmdir()
previously used a local helper, get_dname(), which allocated a temporary
buffer on the heap via kmalloc() to hold the dentry name. This introduced
unnecessary overhead, an ENOMEM failure path, and required manual memory
cleanup via kfree().
As suggested by Al Viro, replace this heap allocation with the VFS dentry
name snapshot API. By stack-allocating a `struct name_snapshot` and using
take_dentry_name_snapshot() and release_dentry_name_snapshot(), we safely
capture the dentry name locklessly, eliminate the heap allocation entirely,
and remove the now-obsolete error handling paths. The get_dname() helper
is completely removed.
Testing:
Booted a custom kernel natively in virtme-ng (ARM64). Triggered tracefs
inode and dentry allocation by creating and removing a custom directory
under a temporary tracefs mount. Verified that the instance is created
successfully and that no memory errors or warnings are emitted in dmesg.
Signed-off-by: AnishMulay <anishm7030@xxxxxxxxx>
---
fs/tracefs/inode.c | 29 ++++++++---------------------
1 file changed, 8 insertions(+), 21 deletions(-)
diff --git a/fs/tracefs/inode.c b/fs/tracefs/inode.c
index 86ba8dc25aaef..ad322e8f9e2ad 100644
--- a/fs/tracefs/inode.c
+++ b/fs/tracefs/inode.c
@@ -94,23 +94,14 @@ static struct tracefs_dir_ops {
int (*rmdir)(const char *name);
} tracefs_ops __ro_after_init;
-static char *get_dname(struct dentry *dentry)
-{
- return kmemdup_nul(dentry->d_name.name, dentry->d_name.len, GFP_KERNEL);
-}
-
static struct dentry *tracefs_syscall_mkdir(struct mnt_idmap *idmap,
struct inode *inode, struct dentry *dentry,
umode_t mode)
{
struct tracefs_inode *ti;
- char *name;
+ struct name_snapshot name;
int ret;
- name = get_dname(dentry);
- if (!name)
- return ERR_PTR(-ENOMEM);
-
/*
* This is a new directory that does not take the default of
* the rootfs. It becomes the default permissions for all the
@@ -125,24 +116,20 @@ static struct dentry *tracefs_syscall_mkdir(struct mnt_idmap *idmap,
* the files within the tracefs system. It is up to the individual
* mkdir routine to handle races.
*/
+ take_dentry_name_snapshot(&name, dentry);
inode_unlock(inode);
- ret = tracefs_ops.mkdir(name);
+ ret = tracefs_ops.mkdir(name.name.name);
inode_lock(inode);
-
- kfree(name);
+ release_dentry_name_snapshot(&name);
return ERR_PTR(ret);
}
static int tracefs_syscall_rmdir(struct inode *inode, struct dentry *dentry)
{
- char *name;
+ struct name_snapshot name;
int ret;
- name = get_dname(dentry);
- if (!name)
- return -ENOMEM;
-
/*
* The rmdir call can call the generic functions that create
* the files within the tracefs system. It is up to the individual
@@ -150,15 +137,15 @@ static int tracefs_syscall_rmdir(struct inode *inode, struct dentry *dentry)
* This time we need to unlock not only the parent (inode) but
* also the directory that is being deleted.
*/
+ take_dentry_name_snapshot(&name, dentry);
inode_unlock(inode);
inode_unlock(d_inode(dentry));
- ret = tracefs_ops.rmdir(name);
+ ret = tracefs_ops.rmdir(name.name.name);
inode_lock_nested(inode, I_MUTEX_PARENT);
inode_lock(d_inode(dentry));
-
- kfree(name);
+ release_dentry_name_snapshot(&name);
return ret;
}
--
2.51.0