Skip to content

Commit 71c3ad6

Browse files
Qi Zhengakpm00
authored andcommitted
Revert "mm: vmscan: make global slab shrink lockless"
This reverts commit f95bdb7. Kernel test robot reports -88.8% regression in stress-ng.ramfs.ops_per_sec test case [1], which is caused by commit f95bdb7 ("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/[email protected]/ [2]. https://lore.kernel.org/lkml/[email protected]/ Link: https://lkml.kernel.org/r/[email protected] Reported-by: kernel test robot <[email protected]> Closes: https://lore.kernel.org/oe-lkp/[email protected] Signed-off-by: Qi Zheng <[email protected]> Cc: Dave Chinner <[email protected]> Cc: Kirill Tkhai <[email protected]> Cc: Muchun Song <[email protected]> Cc: Roman Gushchin <[email protected]> Cc: Vlastimil Babka <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 7cee360 commit 71c3ad6

File tree

1 file changed

+16
-12
lines changed

1 file changed

+16
-12
lines changed

mm/vmscan.c

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@
5757
#include <linux/khugepaged.h>
5858
#include <linux/rculist_nulls.h>
5959
#include <linux/random.h>
60-
#include <linux/srcu.h>
6160

6261
#include <asm/tlbflush.h>
6362
#include <asm/div64.h>
@@ -191,7 +190,6 @@ int vm_swappiness = 60;
191190

192191
LIST_HEAD(shrinker_list);
193192
DECLARE_RWSEM(shrinker_rwsem);
194-
DEFINE_SRCU(shrinker_srcu);
195193

196194
#ifdef CONFIG_MEMCG
197195
static int shrinker_nr_max;
@@ -742,7 +740,7 @@ void free_prealloced_shrinker(struct shrinker *shrinker)
742740
void register_shrinker_prepared(struct shrinker *shrinker)
743741
{
744742
down_write(&shrinker_rwsem);
745-
list_add_tail_rcu(&shrinker->list, &shrinker_list);
743+
list_add_tail(&shrinker->list, &shrinker_list);
746744
shrinker->flags |= SHRINKER_REGISTERED;
747745
shrinker_debugfs_add(shrinker);
748746
up_write(&shrinker_rwsem);
@@ -797,15 +795,13 @@ void unregister_shrinker(struct shrinker *shrinker)
797795
return;
798796

799797
down_write(&shrinker_rwsem);
800-
list_del_rcu(&shrinker->list);
798+
list_del(&shrinker->list);
801799
shrinker->flags &= ~SHRINKER_REGISTERED;
802800
if (shrinker->flags & SHRINKER_MEMCG_AWARE)
803801
unregister_memcg_shrinker(shrinker);
804802
debugfs_entry = shrinker_debugfs_detach(shrinker, &debugfs_id);
805803
up_write(&shrinker_rwsem);
806804

807-
synchronize_srcu(&shrinker_srcu);
808-
809805
shrinker_debugfs_remove(debugfs_entry, debugfs_id);
810806

811807
kfree(shrinker->nr_deferred);
@@ -825,7 +821,6 @@ void synchronize_shrinkers(void)
825821
{
826822
down_write(&shrinker_rwsem);
827823
up_write(&shrinker_rwsem);
828-
synchronize_srcu(&shrinker_srcu);
829824
}
830825
EXPORT_SYMBOL(synchronize_shrinkers);
831826

@@ -1036,7 +1031,6 @@ static unsigned long shrink_slab(gfp_t gfp_mask, int nid,
10361031
{
10371032
unsigned long ret, freed = 0;
10381033
struct shrinker *shrinker;
1039-
int srcu_idx;
10401034

10411035
/*
10421036
* 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,
10481042
if (!mem_cgroup_disabled() && !mem_cgroup_is_root(memcg))
10491043
return shrink_slab_memcg(gfp_mask, nid, memcg, priority);
10501044

1051-
srcu_idx = srcu_read_lock(&shrinker_srcu);
1045+
if (!down_read_trylock(&shrinker_rwsem))
1046+
goto out;
10521047

1053-
list_for_each_entry_srcu(shrinker, &shrinker_list, list,
1054-
srcu_read_lock_held(&shrinker_srcu)) {
1048+
list_for_each_entry(shrinker, &shrinker_list, list) {
10551049
struct shrink_control sc = {
10561050
.gfp_mask = gfp_mask,
10571051
.nid = nid,
@@ -1062,9 +1056,19 @@ static unsigned long shrink_slab(gfp_t gfp_mask, int nid,
10621056
if (ret == SHRINK_EMPTY)
10631057
ret = 0;
10641058
freed += ret;
1059+
/*
1060+
* Bail out if someone want to register a new shrinker to
1061+
* prevent the registration from being stalled for long periods
1062+
* by parallel ongoing shrinking.
1063+
*/
1064+
if (rwsem_is_contended(&shrinker_rwsem)) {
1065+
freed = freed ? : 1;
1066+
break;
1067+
}
10651068
}
10661069

1067-
srcu_read_unlock(&shrinker_srcu, srcu_idx);
1070+
up_read(&shrinker_rwsem);
1071+
out:
10681072
cond_resched();
10691073
return freed;
10701074
}

0 commit comments

Comments
 (0)