From: sashiko-bot@kernel.org
To: "Mathieu Desnoyers" <mathieu.desnoyers@efficios.com>,
"David Hildenbrand" <david@kernel.org>
Cc: "Paul E. McKenney" <paulmck@kernel.org>,
"Steven Rostedt" <rostedt@goodmis.org>,
"Masami Hiramatsu" <mhiramat@kernel.org>,
"Dennis Zhou" <dennis@kernel.org>, "Tejun Heo" <tj@kernel.org>,
"Christoph Lameter" <cl@gentwo.org>,
"Martin Liu" <liumartin@google.com>,
"David Rientjes" <rientjes@google.com>,
christian.koenig@amd.com, "Shakeel Butt" <shakeel.butt@linux.dev>,
"SeongJae Park" <sj@kernel.org>, "Michal Hocko" <mhocko@suse.com>,
"Johannes Weiner" <hannes@cmpxchg.org>,
"Sweet Tea Dorminy" <sweettea-kernel@dorminy.me>,
"Lorenzo Stoakes" <ljs@kernel.org>,
"Liam R. Howlett" <liam@infradead.org>,
"Mike Rapoport" <rppt@kernel.org>,
"Suren Baghdasaryan" <surenb@google.com>,
"Vlastimil Babka" <vbabka@kernel.org>,
"Christian Brauner" <brauner@kernel.org>,
"Wei Yang" <richard.weiyang@gmail.com>,
"Miaohe Lin" <linmiaohe@huawei.com>,
"Al Viro" <viro@zeniv.linux.org.uk>,
"Yu Zhao" <yuzhao@google.com>,
"Roman Gushchin" <roman.gushchin@linux.dev>,
"Mateusz Guzik" <mjguzik@gmail.com>,
"Matthew Wilcox" <willy@infradead.org>,
"Baolin Wang" <baolin.wang@linux.alibaba.com>,
"Aboorva Devarajan" <aboorvad@linux.ibm.com>,
"David Carlier" <devnexen@gmail.com>,
"Andrew Morton" <akpm@linux-foundation.org>,
linux-mm@kvack.org, "Jonathan Corbet" <corbet@lwn.net>,
"Shuah Khan" <skhan@linuxfoundation.org>,
"Randy Dunlap" <rdunlap@infradead.org>,
"Harry Yoo" <harry@kernel.org>, "Hao Li" <hao.li@linux.dev>,
"Kees Cook" <kees@kernel.org>, "Ingo Molnar" <mingo@redhat.com>,
"Peter Zijlstra" <peterz@infradead.org>,
"Juri Lelli" <juri.lelli@redhat.com>,
"Vincent Guittot" <vincent.guittot@linaro.org>,
"Dietmar Eggemann" <dietmar.eggemann@arm.com>,
"Ben Segall" <bsegall@google.com>, "Mel Gorman" <mgorman@suse.de>,
"Valentin Schneider" <vschneid@redhat.com>,
"K Prateek Nayak" <kprateek.nayak@amd.com>,
linux-trace-kernel@vger.kernel.org, "Jan Kara" <jack@suse.cz>,
"Oleg Nesterov" <oleg@redhat.com>,
"Alan Stern" <stern@rowland.harvard.edu>,
"Andrea Parri" <parri.andrea@gmail.com>,
"Will Deacon" <will@kernel.org>, "Boqun Feng" <boqun@kernel.org>,
"Hugh Dickins" <hughd@google.com>
Subject: Re: [RFC PATCH v25 09/14] lib: percpu_counter_tree: test the limit counters
Date: Thu, 12 Nov 2026 20:37:47 +0000 [thread overview]
Message-ID: <sashiko-outbox-211804@kernel.org> (raw)
In-Reply-To: <20261111203626.95838-10-mathieu.desnoyers@efficios.com>
Thank you for your contribution! Sashiko AI review found 2 potential
issues to consider:
- [Medium] lib: percpu_counter_tree: unreachable subtraction in
limit_worker_fn()
- [Low] lib: percpu_counter_tree: unordered sh->charged sub in
limit_worker_fn()
--
commit ffee3ed89eb2ac6dc7c1033ea104470f2a5faf4e
Author: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
lib: percpu_counter_tree: test the limit counters
This commit adds KUnit and userspace hpcc harness tests for
percpu_counter_tree_limit, along with a stall hook in the userspace shim
to simulate concurrent updates while an addition carry is in flight.
> diff --git a/lib/tests/percpu_counter_tree_kunit.c b/lib/tests/percpu_counter_tree_kunit.c
> index 12bd5a4bbb459..bd99ab7ca1c07 100644
> --- a/lib/tests/percpu_counter_tree_kunit.c
> +++ b/lib/tests/percpu_counter_tree_kunit.c
> @@ -612,6 +612,177 @@ static void hpcc_test_contended_carries(struct kunit *test)
> do_hpcc_test_contended_carries(test, 1UL << batch_size_order);
> }
>
> +#define LIMIT_NR_OPS 100000
[ ... ]
> +static int limit_worker_fn(void *data)
> +{
> + struct limit_data *ld = data;
> + struct limit_shared *sh = ld->sh;
> + unsigned int i;
> +
> + /* Pairs with the release of started: max, target and nr_workers are set. */
> + wait_event(limit_wq, smp_load_acquire(&sh->started));
> + /* Start together, so that the workers hold their amounts at the same time. */
> + atomic_inc(&sh->nr_ready);
> + while (atomic_read(&sh->nr_ready) < sh->nr_workers)
> + cpu_relax();
> + for (i = 0; i < LIMIT_NR_OPS; i++) {
> + u32 x = limit_rnd(ld);
> + unsigned long amount;
> +
> + if (ld->held < sh->target) {
> + /* Mostly small amounts, and one in 16 of a huge page. */
> + if ((x >> 4) & 15)
> + amount = 1 + (x >> 8) % (4 * sh->batch_size);
> + else
> + amount = 512;
> + if (percpu_counter_tree_limit_add(&sh->limit, sh->max, amount)) {
> + unsigned long charged;
> +
> + charged = atomic_long_add_return(amount, &sh->charged);
> + if (charged > sh->max)
> + atomic_long_inc(&sh->nr_over);
> + ld->held += amount;
> + atomic_long_inc(&sh->nr_added);
> + } else {
> + atomic_long_inc(&sh->nr_failed);
> + }
> + } else if (ld->held) {
> + amount = 1 + (x >> 8) % ld->held;
> + atomic_long_sub(amount, &sh->charged);
> + percpu_counter_tree_limit_sub(&sh->limit, amount);
> + ld->held -= amount;
> + }
> + if (!(i & 63))
> + cond_resched();
> + }
> + atomic_long_sub(ld->held, &sh->charged);
> + percpu_counter_tree_limit_sub(&sh->limit, ld->held);
[Severity: Low]
Can the relaxed atomic_long_sub() on sh->charged be reordered after
percpu_counter_tree_limit_sub() on weakly ordered architectures?
The comment above limit_worker_fn() notes that a free subtracts from
sh->charged before it reaches the limit counter so sh->charged never
exceeds the limit counter. However, non-value-returning atomic_long_sub()
is unordered, and percpu_counter_tree_limit_sub() updates the per-CPU
level 0 counter via this_cpu_try_cmpxchg() without a barrier when there is
no carry:
CPU0 CPU1
limit_worker_fn() limit_worker_fn()
atomic_long_sub(..., &sh->charged) (reordered)
percpu_counter_tree_limit_sub()
percpu_counter_tree_limit_add() -> true
charged = atomic_long_add_return(...,
&sh->charged)
if (charged > sh->max)
atomic_long_inc(&sh->nr_over);
/* sh->charged sub becomes visible */
This can cause a false-positive KUnit failure on sh->nr_over. Using
atomic_long_sub_return() or smp_mb__after_atomic() before
percpu_counter_tree_limit_sub() in both the loop and the final cleanup
would enforce the intended ordering.
> + ld->held = 0;
> + complete_work();
> + return 0;
> +}
> +
> +static void do_hpcc_test_limit(struct kunit *test, unsigned long batch_size)
> +{
[ ... ]
> + accuracy = percpu_counter_tree_approximate_accuracy(&sh->limit.counters[0]);
> + /* A limit of twice the accuracy, oversubscribed twice: mostly within its accuracy. */
> + sh->max = 2 * accuracy + 1;
> + sh->batch_size = batch_size;
> + init_kthreads();
> + cpus_read_lock();
> + cpus = select_worker_cpus();
> + sh->target = 2 * sh->max / cpumask_weight(cpus) + 512;
[Severity: Medium]
Does setting sh->target to 2 * sh->max / cpumask_weight(cpus) + 512 prevent
limit_worker_fn() from reaching its in-loop subtraction branch?
In limit_worker_fn(), a worker only subtracts when ld->held >= sh->target
and never frees any held amount when percpu_counter_tree_limit_add()
fails. Because the total held across all workers cannot exceed sh->max,
no single worker can ever reach ld->held >= sh->target when
sh->target > sh->max (which holds on 2 to 8 CPUs for both batch sizes, and
up to 64 CPUs for batch_size = 2 due to the + 512 offset). Even with more
CPUs where sh->target <= sh->max, all workers start together at
sh->nr_ready and average sh->max / nr_workers each when the counter fills,
so once total held reaches sh->max with every worker below sh->target, no
further addition can succeed and no worker can subtract for the rest of
LIMIT_NR_OPS.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261111203626.95838-1-mathieu.desnoyers@efficios.com?part=9
next prev parent reply other threads:[~2026-11-12 20:37 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-11 20:36 [RFC PATCH v25 00/14] Hierarchical Percpu Counters for RSS and tmpfs Mathieu Desnoyers
2026-11-11 20:36 ` [RFC PATCH v25 01/14] lib: introduce hierarchical per-cpu counters Mathieu Desnoyers
2026-11-11 20:36 ` [RFC PATCH v25 02/14] lib: test " Mathieu Desnoyers
2026-11-11 20:36 ` [RFC PATCH v25 03/14] mm: use hierarchical per-cpu counters for the RSS counters Mathieu Desnoyers
2026-11-11 20:36 ` [RFC PATCH v25 04/14] tools/testing/hpcc: add userspace test of hierarchical per-CPU counters Mathieu Desnoyers
2026-11-11 20:36 ` [RFC PATCH v25 05/14] mm: report the approximate RSS in the rss_stat tracepoint Mathieu Desnoyers
2026-11-11 20:36 ` [RFC PATCH v25 06/14] lib: percpu_counter_tree: add lazy tree activation Mathieu Desnoyers
2026-11-12 20:37 ` sashiko-bot
2026-11-11 20:36 ` [RFC PATCH v25 07/14] mm: keep the RSS counters of single-threaded processes exact Mathieu Desnoyers
2026-11-12 20:37 ` sashiko-bot
2026-11-11 20:36 ` [RFC PATCH v25 08/14] lib: percpu_counter_tree: add limit counters Mathieu Desnoyers
2026-11-11 20:36 ` [RFC PATCH v25 09/14] lib: percpu_counter_tree: test the " Mathieu Desnoyers
2026-11-12 20:37 ` sashiko-bot [this message]
2026-11-11 20:36 ` [RFC PATCH v25 10/14] tools/testing/hpcc: add litmus tests of the memory ordering Mathieu Desnoyers
2026-11-11 20:36 ` [RFC PATCH v25 11/14] mm: shmem: use a limit counter for the tmpfs size limit Mathieu Desnoyers
2026-11-11 20:36 ` [RFC PATCH v25 12/14] lib: percpu_counter_tree: add the arity boot parameter Mathieu Desnoyers
2026-11-11 20:36 ` [RFC PATCH v25 13/14] mm: add the rss_stat_batch " Mathieu Desnoyers
2026-11-11 20:36 ` [RFC PATCH v25 14/14] lib: add a benchmark of hierarchical per-cpu counters Mathieu Desnoyers
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=sashiko-outbox-211804@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=aboorvad@linux.ibm.com \
--cc=akpm@linux-foundation.org \
--cc=baolin.wang@linux.alibaba.com \
--cc=boqun@kernel.org \
--cc=brauner@kernel.org \
--cc=bsegall@google.com \
--cc=christian.koenig@amd.com \
--cc=cl@gentwo.org \
--cc=corbet@lwn.net \
--cc=david@kernel.org \
--cc=dennis@kernel.org \
--cc=devnexen@gmail.com \
--cc=dietmar.eggemann@arm.com \
--cc=hannes@cmpxchg.org \
--cc=hao.li@linux.dev \
--cc=harry@kernel.org \
--cc=hughd@google.com \
--cc=jack@suse.cz \
--cc=juri.lelli@redhat.com \
--cc=kees@kernel.org \
--cc=kprateek.nayak@amd.com \
--cc=liam@infradead.org \
--cc=linmiaohe@huawei.com \
--cc=linux-mm@kvack.org \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=liumartin@google.com \
--cc=ljs@kernel.org \
--cc=mathieu.desnoyers@efficios.com \
--cc=mgorman@suse.de \
--cc=mhiramat@kernel.org \
--cc=mhocko@suse.com \
--cc=mingo@redhat.com \
--cc=mjguzik@gmail.com \
--cc=oleg@redhat.com \
--cc=parri.andrea@gmail.com \
--cc=paulmck@kernel.org \
--cc=peterz@infradead.org \
--cc=rdunlap@infradead.org \
--cc=richard.weiyang@gmail.com \
--cc=rientjes@google.com \
--cc=roman.gushchin@linux.dev \
--cc=rostedt@goodmis.org \
--cc=rppt@kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=shakeel.butt@linux.dev \
--cc=sj@kernel.org \
--cc=skhan@linuxfoundation.org \
--cc=stern@rowland.harvard.edu \
--cc=surenb@google.com \
--cc=sweettea-kernel@dorminy.me \
--cc=tj@kernel.org \
--cc=vbabka@kernel.org \
--cc=vincent.guittot@linaro.org \
--cc=viro@zeniv.linux.org.uk \
--cc=vschneid@redhat.com \
--cc=will@kernel.org \
--cc=willy@infradead.org \
--cc=yuzhao@google.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.