* [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