From: Kirill Tkhai <tkhai@ya.ru>
To: Qi Zheng <zhengqi.arch@bytedance.com>
Cc: sultan@kerneltoast.com, dave@stgolabs.net,
penguin-kernel@I-love.SAKURA.ne.jp, paulmck@kernel.org,
linux-mm@kvack.org, linux-kernel@vger.kernel.org,
Andrew Morton <akpm@linux-foundation.org>,
Johannes Weiner <hannes@cmpxchg.org>,
Shakeel Butt <shakeelb@google.com>,
Michal Hocko <mhocko@kernel.org>,
Roman Gushchin <roman.gushchin@linux.dev>,
Muchun Song <muchun.song@linux.dev>,
David Hildenbrand <david@redhat.com>,
Yang Shi <shy828301@gmail.com>
Subject: Re: [PATCH v2 1/7] mm: vmscan: add a map_nr_max field to shrinker_info
Date: Sat, 25 Feb 2023 18:14:46 +0300 [thread overview]
Message-ID: <ea1c5d49-1efa-cce8-8750-e19c56187a7c@ya.ru> (raw)
In-Reply-To: <6f8f01b5-d802-db64-7725-8481c67c13a2@bytedance.com>
Hi Qi,
On 25.02.2023 11:18, Qi Zheng wrote:
>
>
> On 2023/2/23 21:27, Qi Zheng wrote:
>> To prepare for the subsequent lockless memcg slab shrink,
>> add a map_nr_max field to struct shrinker_info to records
>> its own real shrinker_nr_max.
>>
>> No functional changes.
>>
>> Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
>
> I missed Suggested-by here, hi Kirill, can I add it?
>
> Suggested-by: Kirill Tkhai <tkhai@ya.ru>
Yes, feel free to add this tag.
There is a comment below.
>> ---
>> include/linux/memcontrol.h | 1 +
>> mm/vmscan.c | 29 ++++++++++++++++++-----------
>> 2 files changed, 19 insertions(+), 11 deletions(-)
>>
>> diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
>> index b6eda2ab205d..aa69ea98e2d8 100644
>> --- a/include/linux/memcontrol.h
>> +++ b/include/linux/memcontrol.h
>> @@ -97,6 +97,7 @@ struct shrinker_info {
>> struct rcu_head rcu;
>> atomic_long_t *nr_deferred;
>> unsigned long *map;
>> + int map_nr_max;
>> };
>> struct lruvec_stats_percpu {
>> diff --git a/mm/vmscan.c b/mm/vmscan.c
>> index 9c1c5e8b24b8..9f895ca6216c 100644
>> --- a/mm/vmscan.c
>> +++ b/mm/vmscan.c
>> @@ -224,9 +224,16 @@ static struct shrinker_info *shrinker_info_protected(struct mem_cgroup *memcg,
>> lockdep_is_held(&shrinker_rwsem));
>> }
>> +static inline bool need_expand(int new_nr_max, int old_nr_max)
>> +{
>> + return round_up(new_nr_max, BITS_PER_LONG) >
>> + round_up(old_nr_max, BITS_PER_LONG);
>> +}
>> +
>> static int expand_one_shrinker_info(struct mem_cgroup *memcg,
>> int map_size, int defer_size,
>> - int old_map_size, int old_defer_size)
>> + int old_map_size, int old_defer_size,
>> + int new_nr_max)
>> {
>> struct shrinker_info *new, *old;
>> struct mem_cgroup_per_node *pn;
>> @@ -240,12 +247,16 @@ static int expand_one_shrinker_info(struct mem_cgroup *memcg,
>> if (!old)
>> return 0;
>> + if (!need_expand(new_nr_max, old->map_nr_max))
>> + return 0;
>> +
>> new = kvmalloc_node(sizeof(*new) + size, GFP_KERNEL, nid);
>> if (!new)
>> return -ENOMEM;
>> new->nr_deferred = (atomic_long_t *)(new + 1);
>> new->map = (void *)new->nr_deferred + defer_size;
>> + new->map_nr_max = new_nr_max;
>> /* map: set all old bits, clear all new bits */
>> memset(new->map, (int)0xff, old_map_size);
>> @@ -295,6 +306,7 @@ int alloc_shrinker_info(struct mem_cgroup *memcg)
>> }
>> info->nr_deferred = (atomic_long_t *)(info + 1);
>> info->map = (void *)info->nr_deferred + defer_size;
>> + info->map_nr_max = shrinker_nr_max;
>> rcu_assign_pointer(memcg->nodeinfo[nid]->shrinker_info, info);
>> }
>> up_write(&shrinker_rwsem);
>> @@ -302,12 +314,6 @@ int alloc_shrinker_info(struct mem_cgroup *memcg)
>> return ret;
>> }
>> -static inline bool need_expand(int nr_max)
>> -{
>> - return round_up(nr_max, BITS_PER_LONG) >
>> - round_up(shrinker_nr_max, BITS_PER_LONG);
>> -}
>> -
>> static int expand_shrinker_info(int new_id)
>> {
>> int ret = 0;
>> @@ -316,7 +322,7 @@ static int expand_shrinker_info(int new_id)
>> int old_map_size, old_defer_size = 0;
>> struct mem_cgroup *memcg;
>> - if (!need_expand(new_nr_max))
>> + if (!need_expand(new_nr_max, shrinker_nr_max))
>> goto out;
>> if (!root_mem_cgroup)
>> @@ -332,7 +338,8 @@ static int expand_shrinker_info(int new_id)
>> memcg = mem_cgroup_iter(NULL, NULL, NULL);
>> do {
>> ret = expand_one_shrinker_info(memcg, map_size, defer_size,
>> - old_map_size, old_defer_size);
>> + old_map_size, old_defer_size,
>> + new_nr_max);
>> if (ret) {
>> mem_cgroup_iter_break(NULL, memcg);
>> goto out;
>> @@ -432,7 +439,7 @@ void reparent_shrinker_deferred(struct mem_cgroup *memcg)
>> for_each_node(nid) {
>> child_info = shrinker_info_protected(memcg, nid);
>> parent_info = shrinker_info_protected(parent, nid);
>> - for (i = 0; i < shrinker_nr_max; i++) {
>> + for (i = 0; i < child_info->map_nr_max; i++) {
>> nr = atomic_long_read(&child_info->nr_deferred[i]);
>> atomic_long_add(nr, &parent_info->nr_deferred[i]);
>> }
>> @@ -899,7 +906,7 @@ static unsigned long shrink_slab_memcg(gfp_t gfp_mask, int nid,
>> if (unlikely(!info))
>> goto unlock;
>> - for_each_set_bit(i, info->map, shrinker_nr_max) {
>> + for_each_set_bit(i, info->map, info->map_nr_max) {
>> struct shrink_control sc = {
>> .gfp_mask = gfp_mask,
>> .nid = nid,
The patch as whole thing won't work as expected. It won't ever call shrinker with ids from [round_down(shrinker_nr_max, sizeof(unsigned long)) + 1, shrinker_nr_max - 1]
Just replay the sequence we add new shrinkers:
1)We add shrinker #0:
shrinker_nr_max = 0;
prealloc_memcg_shrinker()
id = 0;
expand_shrinker_info(0)
new_nr_max = 1;
expand_one_shrinker_info(new_nr_max = 1)
new->map_nr_max = 1;
shrinker_nr_max = 1;
2)We add shrinker #1:
prealloc_memcg_shrinker()
id = 1;
expand_shrinker_info(1)
new_nr_max = 2;
need_expand(2, 1) => false => ignore expand
shrinker_nr_max = 2;
3)Then we call shrinker:
shrink_slab_memcg()
for_each_set_bit(i, info->map, 1/* info->map_nr_max */ ) {
} => ignore shrinker #1
I'd fixed this patch by something like the below:
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 9f895ca6216c..bb617a3871f1 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -224,12 +224,6 @@ static struct shrinker_info *shrinker_info_protected(struct mem_cgroup *memcg,
lockdep_is_held(&shrinker_rwsem));
}
-static inline bool need_expand(int new_nr_max, int old_nr_max)
-{
- return round_up(new_nr_max, BITS_PER_LONG) >
- round_up(old_nr_max, BITS_PER_LONG);
-}
-
static int expand_one_shrinker_info(struct mem_cgroup *memcg,
int map_size, int defer_size,
int old_map_size, int old_defer_size,
@@ -247,9 +241,6 @@ static int expand_one_shrinker_info(struct mem_cgroup *memcg,
if (!old)
return 0;
- if (!need_expand(new_nr_max, old->map_nr_max))
- return 0;
-
new = kvmalloc_node(sizeof(*new) + size, GFP_KERNEL, nid);
if (!new)
return -ENOMEM;
@@ -317,14 +308,11 @@ int alloc_shrinker_info(struct mem_cgroup *memcg)
static int expand_shrinker_info(int new_id)
{
int ret = 0;
- int new_nr_max = new_id + 1;
+ int new_nr_max = round_up(new_id + 1, BITS_PER_LONG);
int map_size, defer_size = 0;
int old_map_size, old_defer_size = 0;
struct mem_cgroup *memcg;
- if (!need_expand(new_nr_max, shrinker_nr_max))
- goto out;
-
if (!root_mem_cgroup)
goto out;
@@ -359,9 +347,11 @@ void set_shrinker_bit(struct mem_cgroup *memcg, int nid, int shrinker_id)
rcu_read_lock();
info = rcu_dereference(memcg->nodeinfo[nid]->shrinker_info);
- /* Pairs with smp mb in shrink_slab() */
- smp_mb__before_atomic();
- set_bit(shrinker_id, info->map);
+ if (!WARN_ON_ONCE(shrinker_id >= info->map_nr_max)) {
+ /* Pairs with smp mb in shrink_slab() */
+ smp_mb__before_atomic();
+ set_bit(shrinker_id, info->map);
+ }
rcu_read_unlock();
}
}
(I also added a new check into set_shrinker_bit() for safety).
Kirill
next prev parent reply other threads:[~2023-02-25 15:14 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-02-23 13:27 [PATCH v2 0/7] make slab shrink lockless Qi Zheng
2023-02-23 13:27 ` [PATCH v2 1/7] mm: vmscan: add a map_nr_max field to shrinker_info Qi Zheng
2023-02-25 8:18 ` Qi Zheng
2023-02-25 15:14 ` Kirill Tkhai [this message]
2023-02-25 15:52 ` Qi Zheng
2023-02-26 13:54 ` Qi Zheng
2023-02-23 13:27 ` [PATCH v2 2/7] mm: vmscan: make global slab shrink lockless Qi Zheng
2023-02-23 15:26 ` Rafael Aquini
2023-02-23 15:37 ` Rafael Aquini
2023-02-24 4:09 ` Qi Zheng
2023-02-23 18:24 ` Sultan Alsawaf
2023-02-23 18:39 ` Paul E. McKenney
2023-02-23 19:18 ` Sultan Alsawaf
2023-02-24 4:00 ` Qi Zheng
2023-02-24 4:16 ` Qi Zheng
2023-02-24 8:20 ` Sultan Alsawaf
2023-02-24 10:12 ` Qi Zheng
2023-02-24 21:02 ` Kirill Tkhai
2023-02-24 21:14 ` Kirill Tkhai
2023-02-25 8:08 ` Qi Zheng
2023-02-25 15:30 ` Kirill Tkhai
2023-02-25 15:57 ` Qi Zheng
2023-02-25 16:17 ` Kirill Tkhai
2023-02-25 16:37 ` Qi Zheng
2023-02-25 21:28 ` Kirill Tkhai
2023-02-26 13:56 ` Qi Zheng
2023-02-23 13:27 ` [PATCH v2 3/7] mm: vmscan: make memcg " Qi Zheng
2023-02-23 13:27 ` [PATCH v2 4/7] mm: shrinkers: make count and scan in shrinker debugfs lockless Qi Zheng
2023-02-23 13:27 ` [PATCH v2 5/7] mm: vmscan: hold write lock to reparent shrinker nr_deferred Qi Zheng
2023-02-23 13:27 ` [PATCH v2 6/7] mm: vmscan: remove shrinker_rwsem from synchronize_shrinkers() Qi Zheng
2023-02-23 13:27 ` [PATCH v2 7/7] mm: shrinkers: convert shrinker_rwsem to mutex Qi Zheng
2023-02-23 18:19 ` [PATCH v2 0/7] make slab shrink lockless Paul E. McKenney
2023-02-24 4:08 ` Qi Zheng
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ea1c5d49-1efa-cce8-8750-e19c56187a7c@ya.ru \
--to=tkhai@ya.ru \
--cc=akpm@linux-foundation.org \
--cc=dave@stgolabs.net \
--cc=david@redhat.com \
--cc=hannes@cmpxchg.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=mhocko@kernel.org \
--cc=muchun.song@linux.dev \
--cc=paulmck@kernel.org \
--cc=penguin-kernel@I-love.SAKURA.ne.jp \
--cc=roman.gushchin@linux.dev \
--cc=shakeelb@google.com \
--cc=shy828301@gmail.com \
--cc=sultan@kerneltoast.com \
--cc=zhengqi.arch@bytedance.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.