[Devel] [PATCH RHEL9 COMMIT] mm/vmscan: add rcu_read_lock to replace released shrinker_rwsem
Konstantin Khorenko
khorenko at virtuozzo.com
Mon Feb 19 21:13:16 MSK 2024
The commit is pushed to "branch-rh9-5.14.0-362.8.1.vz9.35.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh9-5.14.0-362.8.1.vz9.35.14
------>
commit 9d5cbd19fa5eeab1fa4857163edf1a5b2cab807d
Author: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
Date: Tue Feb 6 13:08:18 2024 +0800
mm/vmscan: add rcu_read_lock to replace released shrinker_rwsem
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 <ptikhomirov at virtuozzo.com>
Feature: fix mm/nfs
---
mm/vmscan.c | 31 +++++++++++++++++++++++++++----
1 file changed, 27 insertions(+), 4 deletions(-)
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 847fc2354c3d..1f2eacbad84d 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)
More information about the Devel
mailing list