Skip to content

Commit 7cee360

Browse files
Qi Zhengakpm00
authored andcommitted
Revert "mm: vmscan: make memcg slab shrink lockless"
This reverts commit caa0532. 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 d6ecbcd commit 7cee360

File tree

1 file changed

+19
-26
lines changed

1 file changed

+19
-26
lines changed

mm/vmscan.c

Lines changed: 19 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -210,21 +210,8 @@ static inline int shrinker_defer_size(int nr_items)
210210
static struct shrinker_info *shrinker_info_protected(struct mem_cgroup *memcg,
211211
int nid)
212212
{
213-
return srcu_dereference_check(memcg->nodeinfo[nid]->shrinker_info,
214-
&shrinker_srcu,
215-
lockdep_is_held(&shrinker_rwsem));
216-
}
217-
218-
static struct shrinker_info *shrinker_info_srcu(struct mem_cgroup *memcg,
219-
int nid)
220-
{
221-
return srcu_dereference(memcg->nodeinfo[nid]->shrinker_info,
222-
&shrinker_srcu);
223-
}
224-
225-
static void free_shrinker_info_rcu(struct rcu_head *head)
226-
{
227-
kvfree(container_of(head, struct shrinker_info, rcu));
213+
return rcu_dereference_protected(memcg->nodeinfo[nid]->shrinker_info,
214+
lockdep_is_held(&shrinker_rwsem));
228215
}
229216

230217
static int expand_one_shrinker_info(struct mem_cgroup *memcg,
@@ -265,7 +252,7 @@ static int expand_one_shrinker_info(struct mem_cgroup *memcg,
265252
defer_size - old_defer_size);
266253

267254
rcu_assign_pointer(pn->shrinker_info, new);
268-
call_srcu(&shrinker_srcu, &old->rcu, free_shrinker_info_rcu);
255+
kvfree_rcu(old, rcu);
269256
}
270257

271258
return 0;
@@ -351,16 +338,15 @@ void set_shrinker_bit(struct mem_cgroup *memcg, int nid, int shrinker_id)
351338
{
352339
if (shrinker_id >= 0 && memcg && !mem_cgroup_is_root(memcg)) {
353340
struct shrinker_info *info;
354-
int srcu_idx;
355341

356-
srcu_idx = srcu_read_lock(&shrinker_srcu);
357-
info = shrinker_info_srcu(memcg, nid);
342+
rcu_read_lock();
343+
info = rcu_dereference(memcg->nodeinfo[nid]->shrinker_info);
358344
if (!WARN_ON_ONCE(shrinker_id >= info->map_nr_max)) {
359345
/* Pairs with smp mb in shrink_slab() */
360346
smp_mb__before_atomic();
361347
set_bit(shrinker_id, info->map);
362348
}
363-
srcu_read_unlock(&shrinker_srcu, srcu_idx);
349+
rcu_read_unlock();
364350
}
365351
}
366352

@@ -374,6 +360,7 @@ static int prealloc_memcg_shrinker(struct shrinker *shrinker)
374360
return -ENOSYS;
375361

376362
down_write(&shrinker_rwsem);
363+
/* This may call shrinker, so it must use down_read_trylock() */
377364
id = idr_alloc(&shrinker_idr, shrinker, 0, 0, GFP_KERNEL);
378365
if (id < 0)
379366
goto unlock;
@@ -407,7 +394,7 @@ static long xchg_nr_deferred_memcg(int nid, struct shrinker *shrinker,
407394
{
408395
struct shrinker_info *info;
409396

410-
info = shrinker_info_srcu(memcg, nid);
397+
info = shrinker_info_protected(memcg, nid);
411398
return atomic_long_xchg(&info->nr_deferred[shrinker->id], 0);
412399
}
413400

@@ -416,7 +403,7 @@ static long add_nr_deferred_memcg(long nr, int nid, struct shrinker *shrinker,
416403
{
417404
struct shrinker_info *info;
418405

419-
info = shrinker_info_srcu(memcg, nid);
406+
info = shrinker_info_protected(memcg, nid);
420407
return atomic_long_add_return(nr, &info->nr_deferred[shrinker->id]);
421408
}
422409

@@ -947,14 +934,15 @@ static unsigned long shrink_slab_memcg(gfp_t gfp_mask, int nid,
947934
{
948935
struct shrinker_info *info;
949936
unsigned long ret, freed = 0;
950-
int srcu_idx;
951937
int i;
952938

953939
if (!mem_cgroup_online(memcg))
954940
return 0;
955941

956-
srcu_idx = srcu_read_lock(&shrinker_srcu);
957-
info = shrinker_info_srcu(memcg, nid);
942+
if (!down_read_trylock(&shrinker_rwsem))
943+
return 0;
944+
945+
info = shrinker_info_protected(memcg, nid);
958946
if (unlikely(!info))
959947
goto unlock;
960948

@@ -1004,9 +992,14 @@ static unsigned long shrink_slab_memcg(gfp_t gfp_mask, int nid,
1004992
set_shrinker_bit(memcg, nid, i);
1005993
}
1006994
freed += ret;
995+
996+
if (rwsem_is_contended(&shrinker_rwsem)) {
997+
freed = freed ? : 1;
998+
break;
999+
}
10071000
}
10081001
unlock:
1009-
srcu_read_unlock(&shrinker_srcu, srcu_idx);
1002+
up_read(&shrinker_rwsem);
10101003
return freed;
10111004
}
10121005
#else /* CONFIG_MEMCG */

0 commit comments

Comments
 (0)