* [LTP] [RFC PATCH] getrusage03: account for percpu RSS counter batching
@ 2026-08-25 15:25 Nirmoy Das via ltp
2026-08-25 17:34 ` [LTP] " linuxtestproject.agent
2026-09-02 12:25 ` [LTP] [RFC PATCH] " Cyril Hrubis
0 siblings, 2 replies; 5+ messages in thread
From: Nirmoy Das via ltp @ 2026-08-25 15:25 UTC (permalink / raw)
To: ltp; +Cc: Nirmoy Das
getrusage03 allows ru_maxrss to differ from the expected value by a
fixed 20 MiB. That can be too small on large systems after Linux commit
f1a7941243c1 ("mm: convert mm's rss stats into percpu_counter").
The fast RSS read may miss percpu counter batches, and the batch size
scales with the number of online CPUs. The test child is single threaded,
but it can migrate while faulting memory, so allow two batches worth of
slack based on the online CPU count and page size. Keep the existing
20 MiB floor for smaller systems.
This is sent as RFC because it makes the test tolerate Linux's current
percpu counter batching behavior instead of treating the smaller
ru_maxrss value as a kernel failure.
Signed-off-by: Nirmoy Das <nirmoyd@nvidia.com>
---
.../kernel/syscalls/getrusage/getrusage03.h | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/testcases/kernel/syscalls/getrusage/getrusage03.h b/testcases/kernel/syscalls/getrusage/getrusage03.h
index 58a98b430..9a7d8e8fa 100644
--- a/testcases/kernel/syscalls/getrusage/getrusage03.h
+++ b/testcases/kernel/syscalls/getrusage/getrusage03.h
@@ -7,9 +7,20 @@
#define LTP_GETRUSAGE03_H
#include <sched.h>
+#include "tst_cpu.h"
#include "tst_test.h"
-#define DELTA_MAX 20480
+#define DELTA_MAX 20480L
+#define MAXRSS_BATCHES 2L
+
+static long maxrss_delta(void)
+{
+ long batch = MAX(32L, tst_ncpus() * 2);
+ long delta = MAXRSS_BATCHES * batch * SAFE_SYSCONF(_SC_PAGESIZE) / 1024;
+
+ /* Linux RSS counters can miss percpu counter batches after migration. */
+ return MAX(DELTA_MAX, delta);
+}
static void force_context_switches(int iterations)
{
@@ -40,7 +51,9 @@ static void consume_mb(int consume_nr)
static int is_in_delta(long value)
{
- return (value >= -DELTA_MAX && value <= DELTA_MAX);
+ long delta = maxrss_delta();
+
+ return (value >= -delta && value <= delta);
}
#endif //LTP_GETRUSAGE03_H
--
2.43.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [LTP] getrusage03: account for percpu RSS counter batching
2026-08-25 15:25 [LTP] [RFC PATCH] getrusage03: account for percpu RSS counter batching Nirmoy Das via ltp
@ 2026-08-25 17:34 ` linuxtestproject.agent
2026-09-02 12:25 ` [LTP] [RFC PATCH] " Cyril Hrubis
1 sibling, 0 replies; 5+ messages in thread
From: linuxtestproject.agent @ 2026-08-25 17:34 UTC (permalink / raw)
To: Nirmoy Das; +Cc: ltp
Hi Nirmoy,
On Aug 25, 2026, Nirmoy Das wrote:
> getrusage03: account for percpu RSS counter batching
> + long batch = MAX(32L, tst_ncpus() * 2);
> + long delta = MAXRSS_BATCHES * batch * SAFE_SYSCONF(_SC_PAGESIZE) / 1024;
Could this allowance also scale by the number of online CPUs? An mm's
anonymous RSS counter can retain up to batch - 1 pages on every CPU visited
by the child, and task migration does not flush the previous CPU's local
counter. Linux's own error bound in __percpu_counter_compare() is
batch * num_online_cpus().
For example, with 64 online CPUs and 4 KiB pages, the batch is 128 pages.
This code computes 1 MiB and therefore retains the old 20 MiB floor, while
partial batches on 41 CPUs can already omit more than 20 MiB. The failure
this patch intends to address therefore remains possible.
Verdict - Needs revision
---
Note:
The agent can sometimes produce false positives although often its
findings are genuine. If you find issues with the review, please
comment this email or ignore the suggestions.
Regards,
LTP AI Reviewer
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [LTP] [RFC PATCH] getrusage03: account for percpu RSS counter batching
2026-08-25 15:25 [LTP] [RFC PATCH] getrusage03: account for percpu RSS counter batching Nirmoy Das via ltp
2026-08-25 17:34 ` [LTP] " linuxtestproject.agent
@ 2026-09-02 12:25 ` Cyril Hrubis
2026-09-02 16:01 ` [LTP] [PATCH v2] " Nirmoy Das via ltp
1 sibling, 1 reply; 5+ messages in thread
From: Cyril Hrubis @ 2026-09-02 12:25 UTC (permalink / raw)
To: Nirmoy Das; +Cc: ltp
Hi!
> getrusage03 allows ru_maxrss to differ from the expected value by a
> fixed 20 MiB. That can be too small on large systems after Linux commit
> f1a7941243c1 ("mm: convert mm's rss stats into percpu_counter").
>
> The fast RSS read may miss percpu counter batches, and the batch size
> scales with the number of online CPUs. The test child is single threaded,
> but it can migrate while faulting memory, so allow two batches worth of
> slack based on the online CPU count and page size. Keep the existing
> 20 MiB floor for smaller systems.
>
> This is sent as RFC because it makes the test tolerate Linux's current
> percpu counter batching behavior instead of treating the smaller
> ru_maxrss value as a kernel failure.
Maybe we can pin the whole test to a single CPU instead. Otherwise the
max rss delta can easily get into hundreds of megabytes, which is more
than the test consumes.
--
Cyril Hrubis
chrubis@suse.cz
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 5+ messages in thread
* [LTP] [PATCH v2] getrusage03: account for percpu RSS counter batching
2026-09-02 12:25 ` [LTP] [RFC PATCH] " Cyril Hrubis
@ 2026-09-02 16:01 ` Nirmoy Das via ltp
2026-09-02 17:42 ` [LTP] " linuxtestproject.agent
0 siblings, 1 reply; 5+ messages in thread
From: Nirmoy Das via ltp @ 2026-09-02 16:01 UTC (permalink / raw)
To: ltp
getrusage03 allows ru_maxrss to differ from the expected value by a
fixed 20 MiB. That can be too small on large systems after Linux commit
f1a7941243c1, which converted mm RSS stats into percpu_counter.
Pin the whole test to one CPU during setup, before it forks or execs any
children. Every descendant inherits the affinity, which removes task
migration as a multiplier. One CPU can still retain almost one batch of
the deliberate anonymous allocation outside the fast RSS read.
Use one batch only as lower-side slack for the 100, 300, and 400 MiB
allocation checks. Preserve the fixed 20 MiB tolerance for their upper
side and for all inheritance comparisons. Count online CPUs from
/proc/stat because some libc implementations report only the calling
task affinity. Skip the suite if one batch is at least the smallest
100 MiB allocation and would make that signal non-discriminating.
On a 352-CPU arm64 system with 64 KiB pages, a batch is 704 pages
(44 MiB). With only the pin and fixed 20 MiB tolerance, the 300 MiB
case returned 270336 KiB instead of 307200 KiB and failed 10/10 runs.
The one-batch lower allowance passed 10/10 runs.
Signed-off-by: Nirmoy Das <nirmoyd@nvidia.com>
---
Changes in v2:
- Pin the whole test once in setup so every fork and exec descendant
inherits the singleton CPU affinity.
- Keep one batch only as lower-side slack for the deliberate allocation
checks; pinning with the fixed 20 MiB tolerance failed 10/10 runs on
the 352-CPU, 64 KiB-page system.
- Count kernel-wide online CPUs independently of task affinity and skip
when one batch would make the smallest RSS signal non-discriminating.
.../kernel/syscalls/getrusage/getrusage03.c | 110 +++++++++++++++---
1 file changed, 95 insertions(+), 15 deletions(-)
diff --git a/testcases/kernel/syscalls/getrusage/getrusage03.c b/testcases/kernel/syscalls/getrusage/getrusage03.c
index a2cdd6158..38a100576 100644
--- a/testcases/kernel/syscalls/getrusage/getrusage03.c
+++ b/testcases/kernel/syscalls/getrusage/getrusage03.c
@@ -13,9 +13,13 @@
* this program.
*/
+#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
+#include "lapi/cpuset.h"
+#include "tst_safe_stdio.h"
+#include "tst_cpu.h"
#include "tst_test.h"
#include "getrusage03.h"
@@ -23,12 +27,99 @@
static struct rusage ru;
static long maxrss_init;
+static long lower_allowance;
static const char *const resource[] = {
TESTBIN,
NULL,
};
+static long count_online_cpus(void)
+{
+ FILE *fp = SAFE_FOPEN("/proc/stat", "r");
+ char line[BUFSIZ];
+ long count = 0;
+
+ while (fgets(line, sizeof(line), fp)) {
+ if (line[0] == 'c' && line[1] == 'p' && line[2] == 'u' &&
+ line[3] >= '0' && line[3] <= '9')
+ count++;
+ }
+
+ if (ferror(fp))
+ tst_brk(TBROK | TERRNO, "fgets(/proc/stat)");
+
+ SAFE_FCLOSE(fp);
+
+ if (!count)
+ tst_brk(TBROK, "No online CPUs found in /proc/stat");
+
+ return count;
+}
+
+static void pin_to_cpu(void)
+{
+ long ncpus = tst_ncpus_max();
+ size_t size = CPU_ALLOC_SIZE(ncpus);
+ cpu_set_t *mask = CPU_ALLOC(ncpus);
+ int cpu = -1;
+
+ if (!mask)
+ tst_brk(TBROK | TERRNO, "CPU_ALLOC()");
+
+ CPU_ZERO_S(size, mask);
+ if (sched_getaffinity(0, size, mask) < 0) {
+ CPU_FREE(mask);
+ tst_brk(TBROK | TERRNO, "sched_getaffinity()");
+ }
+
+ for (long i = 0; i < ncpus; i++) {
+ if (CPU_ISSET_S((int)i, size, mask)) {
+ cpu = (int)i;
+ break;
+ }
+ }
+
+ if (cpu < 0) {
+ CPU_FREE(mask);
+ tst_brk(TBROK, "sched_getaffinity() returned an empty CPU mask");
+ }
+
+ CPU_ZERO_S(size, mask);
+ CPU_SET_S(cpu, size, mask);
+ if (sched_setaffinity(0, size, mask) < 0) {
+ CPU_FREE(mask);
+ tst_brk(TBROK | TERRNO, "sched_setaffinity()");
+ }
+
+ CPU_FREE(mask);
+}
+
+static void setup(void)
+{
+ long online_cpus = count_online_cpus();
+ long batch = MAX(32L, online_cpus * 2);
+ long page_size = SAFE_SYSCONF(_SC_PAGESIZE);
+ long batch_kib = batch * page_size / 1024;
+
+ lower_allowance = MAX(20 * 1024L, batch_kib);
+ if (lower_allowance >= 102400L)
+ tst_brk(TCONF, "Per-CPU RSS allowance is too large: %li KiB",
+ lower_allowance);
+
+ pin_to_cpu();
+}
+
+static void check_maxrss(long actual, long expected, const char *name,
+ const char *size)
+{
+ if (actual >= expected - lower_allowance &&
+ actual <= expected + DELTA_MAX)
+ tst_res(TPASS, "%s ~= %s", name, size);
+ else
+ tst_res(TFAIL, "%s = %li, expected %li", name, actual, expected);
+}
+
static void inherit_fork1(void)
{
SAFE_GETRUSAGE(RUSAGE_SELF, &ru);
@@ -51,11 +142,7 @@ static void inherit_fork2(void)
{
SAFE_GETRUSAGE(RUSAGE_CHILDREN, &ru);
- if (is_in_delta(ru.ru_maxrss - 102400))
- tst_res(TPASS, "initial.children ~= 100MB");
- else
- tst_res(TFAIL, "initial.children = %li, expected %i",
- ru.ru_maxrss, 102400);
+ check_maxrss(ru.ru_maxrss, 102400, "initial.children", "100MB");
if (!SAFE_FORK()) {
SAFE_GETRUSAGE(RUSAGE_CHILDREN, &ru);
@@ -78,11 +165,7 @@ static void grandchild_maxrss(void)
tst_reap_children();
SAFE_GETRUSAGE(RUSAGE_CHILDREN, &ru);
- if (is_in_delta(ru.ru_maxrss - 307200))
- tst_res(TPASS, "child.children ~= 300MB");
- else
- tst_res(TFAIL, "child.children = %li, expected %i",
- ru.ru_maxrss, 307200);
+ check_maxrss(ru.ru_maxrss, 307200, "child.children", "300MB");
}
static void zombie(void)
@@ -106,11 +189,7 @@ static void zombie(void)
tst_reap_children();
SAFE_GETRUSAGE(RUSAGE_CHILDREN, &ru);
- if (is_in_delta(ru.ru_maxrss - 409600))
- tst_res(TPASS, "post_wait.children ~= 400MB");
- else
- tst_res(TFAIL, "post_wait.children = %li, expected %i",
- ru.ru_maxrss, 409600);
+ check_maxrss(ru.ru_maxrss, 409600, "post_wait.children", "400MB");
}
static void sig_ign(void)
@@ -174,6 +253,7 @@ static void run(unsigned int i)
static struct tst_test test = {
.forks_child = 1,
.child_needs_reinit = 1,
+ .setup = setup,
.resource_files = resource,
.min_mem_avail = 512,
.tags = (const struct tst_tag[]) {
base-commit: 12724413534a6d4160ff9694ba6f09daa4ccb6bd
--
2.43.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [LTP] getrusage03: account for percpu RSS counter batching
2026-09-02 16:01 ` [LTP] [PATCH v2] " Nirmoy Das via ltp
@ 2026-09-02 17:42 ` linuxtestproject.agent
0 siblings, 0 replies; 5+ messages in thread
From: linuxtestproject.agent @ 2026-09-02 17:42 UTC (permalink / raw)
To: Nirmoy Das; +Cc: ltp
Hi Nirmoy,
On Sep 2, 2026, Nirmoy Das wrote:
> getrusage03: account for percpu RSS counter batching
Verdict - Reviewed
---
Note:
The agent can sometimes produce false positives although often its
findings are genuine. If you find issues with the review, please
comment this email or ignore the suggestions.
Regards,
LTP AI Reviewer
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-09-02 17:43 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-25 15:25 [LTP] [RFC PATCH] getrusage03: account for percpu RSS counter batching Nirmoy Das via ltp
2026-08-25 17:34 ` [LTP] " linuxtestproject.agent
2026-09-02 12:25 ` [LTP] [RFC PATCH] " Cyril Hrubis
2026-09-02 16:01 ` [LTP] [PATCH v2] " Nirmoy Das via ltp
2026-09-02 17:42 ` [LTP] " linuxtestproject.agent
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox