After commit [1] we release shrinker_rwsem for nfs while processing do_shrink_slab, we need this to mitigate blocked shrinker_rwsem due to a hang in nfs shrinker.
After that we lack shrinker_rwsem and rcu_read_lock in these stacks: +-< rcu_dereference_protected(ockdep_is_held(&shrinker_rwsem)) +-< shrinker_info_protected +-< xchg_nr_deferred_memcg +-< xchg_nr_deferred +-< do_shrink_slab +-< add_nr_deferred_memcg +-< add_nr_deferred +-< do_shrink_slab As these stacks only use info for read, we can switch to rcu_read_lock, also need to switch rcu_dereference_protected -> rcu_dereference_check. https://virtuozzo.atlassian.net/browse/PSBM-153973 Fixes: c0efc56a8f844 ("mm: fix hanging shrinker management on long do_shrink_slab") [1] Signed-off-by: Pavel Tikhomirov <ptikhomi...@virtuozzo.com> --- note: In vz7 we don't need it. --- mm/vmscan.c | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index 847fc2354c3dc..1f2eacbad84d4 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -218,6 +218,13 @@ static struct shrinker_info *shrinker_info_protected(struct mem_cgroup *memcg, lockdep_is_held(&shrinker_rwsem)); } +static struct shrinker_info *shrinker_info_check(struct mem_cgroup *memcg, + int nid) +{ + return rcu_dereference_check(memcg->nodeinfo[nid]->shrinker_info, + lockdep_is_held(&shrinker_rwsem)); +} + static int expand_one_shrinker_info(struct mem_cgroup *memcg, int map_size, int defer_size, int old_map_size, int old_defer_size) @@ -411,18 +418,34 @@ static long xchg_nr_deferred_memcg(int nid, struct shrinker *shrinker, struct mem_cgroup *memcg) { struct shrinker_info *info; + long ret; - info = shrinker_info_protected(memcg, nid); - return atomic_long_xchg(&info->nr_deferred[shrinker->id], 0); + /* + * Need rcu lock here in case we've released shrinker_rwsem to prevent + * hang on nfs before calling do_shrink_slab(). + */ + rcu_read_lock(); + info = shrinker_info_check(memcg, nid); + ret = atomic_long_xchg(&info->nr_deferred[shrinker->id], 0); + rcu_read_unlock(); + return ret; } static long add_nr_deferred_memcg(long nr, int nid, struct shrinker *shrinker, struct mem_cgroup *memcg) { struct shrinker_info *info; + long ret; - info = shrinker_info_protected(memcg, nid); - return atomic_long_add_return(nr, &info->nr_deferred[shrinker->id]); + /* + * Need rcu lock here in case we've released shrinker_rwsem to prevent + * hang on nfs before calling do_shrink_slab(). + */ + rcu_read_lock(); + info = shrinker_info_check(memcg, nid); + ret = atomic_long_add_return(nr, &info->nr_deferred[shrinker->id]); + rcu_read_unlock(); + return ret; } void reparent_shrinker_deferred(struct mem_cgroup *memcg) -- 2.43.0 _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel