summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteven Rostedt <rostedt@goodmis.org>2025-06-11 12:18:15 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2025-08-20 18:30:21 +0200
commitc51db71fc143a5e0014219deda9cad05c4352e7f (patch)
tree1bde6e13ba4249aac359521e1c13614826122f57
parenta24ed0e8ce7d6213c9a73f86e1f45b41693160df (diff)
tracefs: Add d_delete to remove negative dentries
[ Upstream commit d9b13cdad80dc11d74408cf201939a946e9303a6 ] If a lookup in tracefs is done on a file that does not exist, it leaves a dentry hanging around until memory pressure removes it. But eventfs dentries should hang around as when their ref count goes to zero, it requires more work to recreate it. For the rest of the tracefs dentries, they hang around as their dentry is used as a descriptor for the tracing system. But if a file lookup happens for a file in tracefs that does not exist, it should be deleted. Add a .d_delete callback that checks if dentry->fsdata is set or not. Only eventfs dentries set fsdata so if it has content it should not be deleted and should hang around in the cache. Reported-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--fs/tracefs/inode.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/fs/tracefs/inode.c b/fs/tracefs/inode.c
index cfc614c638da..9f15d606dfde 100644
--- a/fs/tracefs/inode.c
+++ b/fs/tracefs/inode.c
@@ -464,9 +464,20 @@ static int tracefs_d_revalidate(struct dentry *dentry, unsigned int flags)
return !(ei && ei->is_freed);
}
+static int tracefs_d_delete(const struct dentry *dentry)
+{
+ /*
+ * We want to keep eventfs dentries around but not tracefs
+ * ones. eventfs dentries have content in d_fsdata.
+ * Use d_fsdata to determine if it's a eventfs dentry or not.
+ */
+ return dentry->d_fsdata == NULL;
+}
+
static const struct dentry_operations tracefs_dentry_operations = {
.d_revalidate = tracefs_d_revalidate,
.d_release = tracefs_d_release,
+ .d_delete = tracefs_d_delete,
};
static int tracefs_fill_super(struct super_block *sb, struct fs_context *fc)