From: Steven Rostedt rostedt@goodmis.org
[ 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 ---
LLM Generated explanations, may be completely bogus:
Based on my analysis of this commit, here is my assessment:
**Backport Status: YES**
This commit should be backported to stable kernel trees for the following reasons:
## Analysis of the commit:
1. **Bug Fix Nature**: This commit fixes a memory leak issue where negative dentries (dentries for non-existent files) in tracefs are not properly cleaned up, leading to unnecessary memory consumption until memory pressure forces their removal.
2. **Small and Contained Change**: The patch adds only 11 lines of code - a single `d_delete` callback function that returns whether a dentry should be immediately deleted based on whether it has `d_fsdata` set or not. This is a minimal, focused fix.
3. **Clear Problem and Solution**: - Problem: Negative dentries in tracefs hang around unnecessarily consuming memory - Solution: Add `d_delete` callback to immediately remove negative dentries that aren't eventfs dentries - The logic is simple: `return dentry->d_fsdata == NULL;`
4. **No Architectural Changes**: This commit doesn't change any fundamental behavior or architecture. It simply adds a cleanup mechanism for negative dentries that should have been there from the beginning.
5. **Low Risk of Regression**: The change is conservative: - It only affects negative dentries (files that don't exist) - It preserves the existing behavior for eventfs dentries (which need to be cached) - The callback is idempotent and constant as required by the VFS documentation
6. **Performance Impact**: This is a performance improvement that reduces memory usage by preventing the accumulation of useless negative dentries in tracefs.
7. **Subsystem Maturity**: The tracefs/eventfs subsystem has been undergoing fixes and improvements, and this appears to be part of cleaning up edge cases that were discovered through usage.
The commit follows the stable kernel rules perfectly - it's a clear bug fix that improves system behavior without introducing new features or making risky changes. The fact that it was reported by Al Viro (a VFS maintainer) and signed off by him adds additional confidence that this is a proper fix.
fs/tracefs/inode.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/fs/tracefs/inode.c b/fs/tracefs/inode.c index 7d389dd5ed51..6b70965063d7 100644 --- a/fs/tracefs/inode.c +++ b/fs/tracefs/inode.c @@ -483,9 +483,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 trace_fill_super(struct super_block *sb, void *data, int silent)