mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-01 18:55:12 +00:00
Revert "mm: vmscan: make global slab shrink lockless"
This reverts commitf95bdb700b
. Kernel test robot reports -88.8% regression in stress-ng.ramfs.ops_per_sec test case [1], which is caused by commitf95bdb700b
("mm: vmscan: make global slab shrink lockless"). The root cause is that SRCU has to be careful to not frequently check for SRCU read-side critical section exits. Therefore, even if no one is currently in the SRCU read-side critical section, synchronize_srcu() cannot return quickly. That's why unregister_shrinker() has become slower. After discussion, we will try to use the refcount+RCU method [2] proposed by Dave Chinner to continue to re-implement the lockless slab shrink. So revert the shrinker_srcu related changes first. [1]. https://lore.kernel.org/lkml/202305230837.db2c233f-yujie.liu@intel.com/ [2]. https://lore.kernel.org/lkml/ZIJhou1d55d4H1s0@dread.disaster.area/ Link: https://lkml.kernel.org/r/20230609081518.3039120-8-qi.zheng@linux.dev Reported-by: kernel test robot <yujie.liu@intel.com> Closes: https://lore.kernel.org/oe-lkp/202305230837.db2c233f-yujie.liu@intel.com Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com> Cc: Dave Chinner <david@fromorbit.com> Cc: Kirill Tkhai <tkhai@ya.ru> Cc: Muchun Song <muchun.song@linux.dev> Cc: Roman Gushchin <roman.gushchin@linux.dev> Cc: Vlastimil Babka <vbabka@suse.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
parent
7cee360319
commit
71c3ad65fa
28
mm/vmscan.c
28
mm/vmscan.c
@ -57,7 +57,6 @@
|
||||
#include <linux/khugepaged.h>
|
||||
#include <linux/rculist_nulls.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/srcu.h>
|
||||
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm/div64.h>
|
||||
@ -191,7 +190,6 @@ int vm_swappiness = 60;
|
||||
|
||||
LIST_HEAD(shrinker_list);
|
||||
DECLARE_RWSEM(shrinker_rwsem);
|
||||
DEFINE_SRCU(shrinker_srcu);
|
||||
|
||||
#ifdef CONFIG_MEMCG
|
||||
static int shrinker_nr_max;
|
||||
@ -742,7 +740,7 @@ void free_prealloced_shrinker(struct shrinker *shrinker)
|
||||
void register_shrinker_prepared(struct shrinker *shrinker)
|
||||
{
|
||||
down_write(&shrinker_rwsem);
|
||||
list_add_tail_rcu(&shrinker->list, &shrinker_list);
|
||||
list_add_tail(&shrinker->list, &shrinker_list);
|
||||
shrinker->flags |= SHRINKER_REGISTERED;
|
||||
shrinker_debugfs_add(shrinker);
|
||||
up_write(&shrinker_rwsem);
|
||||
@ -797,15 +795,13 @@ void unregister_shrinker(struct shrinker *shrinker)
|
||||
return;
|
||||
|
||||
down_write(&shrinker_rwsem);
|
||||
list_del_rcu(&shrinker->list);
|
||||
list_del(&shrinker->list);
|
||||
shrinker->flags &= ~SHRINKER_REGISTERED;
|
||||
if (shrinker->flags & SHRINKER_MEMCG_AWARE)
|
||||
unregister_memcg_shrinker(shrinker);
|
||||
debugfs_entry = shrinker_debugfs_detach(shrinker, &debugfs_id);
|
||||
up_write(&shrinker_rwsem);
|
||||
|
||||
synchronize_srcu(&shrinker_srcu);
|
||||
|
||||
shrinker_debugfs_remove(debugfs_entry, debugfs_id);
|
||||
|
||||
kfree(shrinker->nr_deferred);
|
||||
@ -825,7 +821,6 @@ void synchronize_shrinkers(void)
|
||||
{
|
||||
down_write(&shrinker_rwsem);
|
||||
up_write(&shrinker_rwsem);
|
||||
synchronize_srcu(&shrinker_srcu);
|
||||
}
|
||||
EXPORT_SYMBOL(synchronize_shrinkers);
|
||||
|
||||
@ -1036,7 +1031,6 @@ static unsigned long shrink_slab(gfp_t gfp_mask, int nid,
|
||||
{
|
||||
unsigned long ret, freed = 0;
|
||||
struct shrinker *shrinker;
|
||||
int srcu_idx;
|
||||
|
||||
/*
|
||||
* The root memcg might be allocated even though memcg is disabled
|
||||
@ -1048,10 +1042,10 @@ static unsigned long shrink_slab(gfp_t gfp_mask, int nid,
|
||||
if (!mem_cgroup_disabled() && !mem_cgroup_is_root(memcg))
|
||||
return shrink_slab_memcg(gfp_mask, nid, memcg, priority);
|
||||
|
||||
srcu_idx = srcu_read_lock(&shrinker_srcu);
|
||||
if (!down_read_trylock(&shrinker_rwsem))
|
||||
goto out;
|
||||
|
||||
list_for_each_entry_srcu(shrinker, &shrinker_list, list,
|
||||
srcu_read_lock_held(&shrinker_srcu)) {
|
||||
list_for_each_entry(shrinker, &shrinker_list, list) {
|
||||
struct shrink_control sc = {
|
||||
.gfp_mask = gfp_mask,
|
||||
.nid = nid,
|
||||
@ -1062,9 +1056,19 @@ static unsigned long shrink_slab(gfp_t gfp_mask, int nid,
|
||||
if (ret == SHRINK_EMPTY)
|
||||
ret = 0;
|
||||
freed += ret;
|
||||
/*
|
||||
* Bail out if someone want to register a new shrinker to
|
||||
* prevent the registration from being stalled for long periods
|
||||
* by parallel ongoing shrinking.
|
||||
*/
|
||||
if (rwsem_is_contended(&shrinker_rwsem)) {
|
||||
freed = freed ? : 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
srcu_read_unlock(&shrinker_srcu, srcu_idx);
|
||||
up_read(&shrinker_rwsem);
|
||||
out:
|
||||
cond_resched();
|
||||
return freed;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user