Patch "vfs: don't mod negative dentry count when on shrinker list" has been added to the 6.9-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    vfs: don't mod negative dentry count when on shrinker list

to the 6.9-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     vfs-don-t-mod-negative-dentry-count-when-on-shrinker.patch
and it can be found in the queue-6.9 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 36c99593ef5931337d41da7919778d9813ae8357
Author: Brian Foster <bfoster@xxxxxxxxxx>
Date:   Wed Jul 3 08:13:01 2024 -0400

    vfs: don't mod negative dentry count when on shrinker list
    
    [ Upstream commit aabfe57ebaa75841db47ea59091ec3c5a06d2f52 ]
    
    The nr_dentry_negative counter is intended to only account negative
    dentries that are present on the superblock LRU. Therefore, the LRU
    add, remove and isolate helpers modify the counter based on whether
    the dentry is negative, but the shrinker list related helpers do not
    modify the counter, and the paths that change a dentry between
    positive and negative only do so if DCACHE_LRU_LIST is set.
    
    The problem with this is that a dentry on a shrinker list still has
    DCACHE_LRU_LIST set to indicate ->d_lru is in use. The additional
    DCACHE_SHRINK_LIST flag denotes whether the dentry is on LRU or a
    shrink related list. Therefore if a relevant operation (i.e. unlink)
    occurs while a dentry is present on a shrinker list, and the
    associated codepath only checks for DCACHE_LRU_LIST, then it is
    technically possible to modify the negative dentry count for a
    dentry that is off the LRU. Since the shrinker list related helpers
    do not modify the negative dentry count (because non-LRU dentries
    should not be included in the count) when the dentry is ultimately
    removed from the shrinker list, this can cause the negative dentry
    count to become permanently inaccurate.
    
    This problem can be reproduced via a heavy file create/unlink vs.
    drop_caches workload. On an 80xcpu system, I start 80 tasks each
    running a 1k file create/delete loop, and one task spinning on
    drop_caches. After 10 minutes or so of runtime, the idle/clean cache
    negative dentry count increases from somewhere in the range of 5-10
    entries to several hundred (and increasingly grows beyond
    nr_dentry_unused).
    
    Tweak the logic in the paths that turn a dentry negative or positive
    to filter out the case where the dentry is present on a shrink
    related list. This allows the above workload to maintain an accurate
    negative dentry count.
    
    Fixes: af0c9af1b3f6 ("fs/dcache: Track & report number of negative dentries")
    Signed-off-by: Brian Foster <bfoster@xxxxxxxxxx>
    Link: https://lore.kernel.org/r/20240703121301.247680-1-bfoster@xxxxxxxxxx
    Acked-by: Ian Kent <ikent@xxxxxxxxxx>
    Reviewed-by: Josef Bacik <josef@xxxxxxxxxxxxxx>
    Reviewed-by: Waiman Long <longman@xxxxxxxxxx>
    Signed-off-by: Christian Brauner <brauner@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/fs/dcache.c b/fs/dcache.c
index 407095188f83a..66515fbc9dd70 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -355,7 +355,11 @@ static inline void __d_clear_type_and_inode(struct dentry *dentry)
 	flags &= ~DCACHE_ENTRY_TYPE;
 	WRITE_ONCE(dentry->d_flags, flags);
 	dentry->d_inode = NULL;
-	if (flags & DCACHE_LRU_LIST)
+	/*
+	 * The negative counter only tracks dentries on the LRU. Don't inc if
+	 * d_lru is on another list.
+	 */
+	if ((flags & (DCACHE_LRU_LIST|DCACHE_SHRINK_LIST)) == DCACHE_LRU_LIST)
 		this_cpu_inc(nr_dentry_negative);
 }
 
@@ -1844,9 +1848,11 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode)
 
 	spin_lock(&dentry->d_lock);
 	/*
-	 * Decrement negative dentry count if it was in the LRU list.
+	 * The negative counter only tracks dentries on the LRU. Don't dec if
+	 * d_lru is on another list.
 	 */
-	if (dentry->d_flags & DCACHE_LRU_LIST)
+	if ((dentry->d_flags &
+	     (DCACHE_LRU_LIST|DCACHE_SHRINK_LIST)) == DCACHE_LRU_LIST)
 		this_cpu_dec(nr_dentry_negative);
 	hlist_add_head(&dentry->d_u.d_alias, &inode->i_dentry);
 	raw_write_seqcount_begin(&dentry->d_seq);




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux