Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

tracefs: Use dentry name snapshots instead of heap allocation

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.

Link: https://patch.msgid.link/20260306200458.2264-1-anishm7030@gmail.com
Suggested-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: AnishMulay <anishm7030@gmail.com>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>

authored by

AnishMulay and committed by
Steven Rostedt (Google)
676540d0 4d9b2620

+8 -31
+8 -31
fs/tracefs/inode.c
··· 94 94 int (*rmdir)(const char *name); 95 95 } tracefs_ops __ro_after_init; 96 96 97 - static char *get_dname(struct dentry *dentry) 98 - { 99 - const char *dname; 100 - char *name; 101 - int len = dentry->d_name.len; 102 - 103 - dname = dentry->d_name.name; 104 - name = kmalloc(len + 1, GFP_KERNEL); 105 - if (!name) 106 - return NULL; 107 - memcpy(name, dname, len); 108 - name[len] = 0; 109 - return name; 110 - } 111 - 112 97 static struct dentry *tracefs_syscall_mkdir(struct mnt_idmap *idmap, 113 98 struct inode *inode, struct dentry *dentry, 114 99 umode_t mode) 115 100 { 116 101 struct tracefs_inode *ti; 117 - char *name; 102 + struct name_snapshot name; 118 103 int ret; 119 - 120 - name = get_dname(dentry); 121 - if (!name) 122 - return ERR_PTR(-ENOMEM); 123 104 124 105 /* 125 106 * This is a new directory that does not take the default of ··· 116 135 * the files within the tracefs system. It is up to the individual 117 136 * mkdir routine to handle races. 118 137 */ 138 + take_dentry_name_snapshot(&name, dentry); 119 139 inode_unlock(inode); 120 - ret = tracefs_ops.mkdir(name); 140 + ret = tracefs_ops.mkdir(name.name.name); 121 141 inode_lock(inode); 122 - 123 - kfree(name); 142 + release_dentry_name_snapshot(&name); 124 143 125 144 return ERR_PTR(ret); 126 145 } 127 146 128 147 static int tracefs_syscall_rmdir(struct inode *inode, struct dentry *dentry) 129 148 { 130 - char *name; 149 + struct name_snapshot name; 131 150 int ret; 132 - 133 - name = get_dname(dentry); 134 - if (!name) 135 - return -ENOMEM; 136 151 137 152 /* 138 153 * The rmdir call can call the generic functions that create ··· 137 160 * This time we need to unlock not only the parent (inode) but 138 161 * also the directory that is being deleted. 139 162 */ 163 + take_dentry_name_snapshot(&name, dentry); 140 164 inode_unlock(inode); 141 165 inode_unlock(d_inode(dentry)); 142 166 143 - ret = tracefs_ops.rmdir(name); 167 + ret = tracefs_ops.rmdir(name.name.name); 144 168 145 169 inode_lock_nested(inode, I_MUTEX_PARENT); 146 170 inode_lock(d_inode(dentry)); 147 - 148 - kfree(name); 171 + release_dentry_name_snapshot(&name); 149 172 150 173 return ret; 151 174 }