Skip to content

Commit 676540d

Browse files
AnishMulayrostedt
authored andcommitted
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>
1 parent 4d9b262 commit 676540d

1 file changed

Lines changed: 8 additions & 31 deletions

File tree

fs/tracefs/inode.c

Lines changed: 8 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -94,33 +94,14 @@ static struct tracefs_dir_ops {
9494
int (*rmdir)(const char *name);
9595
} tracefs_ops __ro_after_init;
9696

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-
11297
static struct dentry *tracefs_syscall_mkdir(struct mnt_idmap *idmap,
11398
struct inode *inode, struct dentry *dentry,
11499
umode_t mode)
115100
{
116101
struct tracefs_inode *ti;
117-
char *name;
102+
struct name_snapshot name;
118103
int ret;
119104

120-
name = get_dname(dentry);
121-
if (!name)
122-
return ERR_PTR(-ENOMEM);
123-
124105
/*
125106
* This is a new directory that does not take the default of
126107
* the rootfs. It becomes the default permissions for all the
@@ -135,40 +116,36 @@ static struct dentry *tracefs_syscall_mkdir(struct mnt_idmap *idmap,
135116
* the files within the tracefs system. It is up to the individual
136117
* mkdir routine to handle races.
137118
*/
119+
take_dentry_name_snapshot(&name, dentry);
138120
inode_unlock(inode);
139-
ret = tracefs_ops.mkdir(name);
121+
ret = tracefs_ops.mkdir(name.name.name);
140122
inode_lock(inode);
141-
142-
kfree(name);
123+
release_dentry_name_snapshot(&name);
143124

144125
return ERR_PTR(ret);
145126
}
146127

147128
static int tracefs_syscall_rmdir(struct inode *inode, struct dentry *dentry)
148129
{
149-
char *name;
130+
struct name_snapshot name;
150131
int ret;
151132

152-
name = get_dname(dentry);
153-
if (!name)
154-
return -ENOMEM;
155-
156133
/*
157134
* The rmdir call can call the generic functions that create
158135
* the files within the tracefs system. It is up to the individual
159136
* rmdir routine to handle races.
160137
* This time we need to unlock not only the parent (inode) but
161138
* also the directory that is being deleted.
162139
*/
140+
take_dentry_name_snapshot(&name, dentry);
163141
inode_unlock(inode);
164142
inode_unlock(d_inode(dentry));
165143

166-
ret = tracefs_ops.rmdir(name);
144+
ret = tracefs_ops.rmdir(name.name.name);
167145

168146
inode_lock_nested(inode, I_MUTEX_PARENT);
169147
inode_lock(d_inode(dentry));
170-
171-
kfree(name);
148+
release_dentry_name_snapshot(&name);
172149

173150
return ret;
174151
}

0 commit comments

Comments
 (0)