* [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; 12+ 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] 12+ 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; 12+ 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] 12+ 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; 12+ 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] 12+ 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
` (2 more replies)
0 siblings, 3 replies; 12+ 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] 12+ 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
2026-09-15 15:29 ` [LTP] [PATCH v2] " Cyril Hrubis
2026-09-24 11:26 ` Cyril Hrubis
2 siblings, 0 replies; 12+ 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] 12+ messages in thread
* Re: [LTP] [PATCH v2] getrusage03: account for percpu RSS counter batching
2026-09-02 16:01 ` [LTP] [PATCH v2] " Nirmoy Das via ltp
2026-09-02 17:42 ` [LTP] " linuxtestproject.agent
@ 2026-09-15 15:29 ` Cyril Hrubis
2026-09-16 15:58 ` Nirmoy Das via ltp
2026-09-24 11:26 ` Cyril Hrubis
2 siblings, 1 reply; 12+ messages in thread
From: Cyril Hrubis @ 2026-09-15 15:29 UTC (permalink / raw)
To: Nirmoy Das; +Cc: ltp
Hi!
> 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);
As long as we pin to a single CPU the whole batch accounting shouldn't
be needed.
FYI Jan send a similar patch that just pins the process to a single CPU:
https://patchwork.kernel.org/project/ltp/patch/a308e12198ce96305761a009858fa4a80c91f932.1788518850.git.jstancek@redhat.com/
As far as I can tell that should be enough to fix the test.
--
Cyril Hrubis
chrubis@suse.cz
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [LTP] [PATCH v2] getrusage03: account for percpu RSS counter batching
2026-09-15 15:29 ` [LTP] [PATCH v2] " Cyril Hrubis
@ 2026-09-16 15:58 ` Nirmoy Das via ltp
2026-09-17 12:36 ` Jan Stancek via ltp
0 siblings, 1 reply; 12+ messages in thread
From: Nirmoy Das via ltp @ 2026-09-16 15:58 UTC (permalink / raw)
To: Cyril Hrubis; +Cc: ltp@lists.linux.it
Hi Cyril,
I tested Jan’s patch on a machine with 352 online CPUs and 64 KiB pages. Pinning was confirmed, but both the
baseline and Jan’s patch failed 10/10 runs:
child.children = 270336, expected 307200
Pinning keeps the allocation updates on one CPU, but get_mm_counter()
still reads only the global count. One batch here is
max(32, 352 * 2) = 704 pages, or 45056 KiB. The 36864 KiB shortfall
fits within that batch but exceeds the existing 20480 KiB DELTA_MAX.
I also tested a small follow-up that increases only the lower allowance
for the 100, 300 and 400 MiB checks. It passed 10/10 runs, with all nine
subtests passing each time.
I will send this follow-up once Jan’s patch is merged.
Regards,
Nirmoy
From: Cyril Hrubis <chrubis@suse.cz>
Date: Tuesday, 15. September 2026 at 17:29
To: Nirmoy Das <nirmoyd@nvidia.com>
Cc: ltp@lists.linux.it <ltp@lists.linux.it>; Jan Stancek <jstancek@redhat.com>
Subject: Re: [PATCH v2] getrusage03: account for percpu RSS counter batching
[You don't often get email from chrubis@suse.cz. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
Hi!
> 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);
As long as we pin to a single CPU the whole batch accounting shouldn't
be needed.
FYI Jan send a similar patch that just pins the process to a single CPU:
https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpatchwork.kernel.org%2Fproject%2Fltp%2Fpatch%2Fa308e12198ce96305761a009858fa4a80c91f932.1788518850.git.jstancek%40redhat.com%2F&data=05%7C02%7Cnirmoyd%40nvidia.com%7C5c88fc4e5490430569b008df133e14f3%7C43083d15727340c1b7db39efd9ccc17a%7C0%7C0%7C639250829531773556%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=qOkWQ7VsVwFS38S1zQgxue5eo8kNqUJ%2BEHl4rN80qIQ%3D&reserved=0<https://patchwork.kernel.org/project/ltp/patch/a308e12198ce96305761a009858fa4a80c91f932.1788518850.git.jstancek@redhat.com/>
As far as I can tell that should be enough to fix the test.
--
Cyril Hrubis
chrubis@suse.cz
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [LTP] [PATCH v2] getrusage03: account for percpu RSS counter batching
2026-09-16 15:58 ` Nirmoy Das via ltp
@ 2026-09-17 12:36 ` Jan Stancek via ltp
2026-09-22 17:36 ` Petr Vorel
0 siblings, 1 reply; 12+ messages in thread
From: Jan Stancek via ltp @ 2026-09-17 12:36 UTC (permalink / raw)
To: Nirmoy Das; +Cc: ltp@lists.linux.it
On Wed, Sep 16, 2026 at 5:59 PM Nirmoy Das <nirmoyd@nvidia.com> wrote:
>
> Hi Cyril,
>
> I tested Jan’s patch on a machine with 352 online CPUs and 64 KiB pages. Pinning was confirmed, but both the
> baseline and Jan’s patch failed 10/10 runs:
>
> child.children = 270336, expected 307200
>
> Pinning keeps the allocation updates on one CPU, but get_mm_counter()
> still reads only the global count. One batch here is
> max(32, 352 * 2) = 704 pages, or 45056 KiB. The 36864 KiB shortfall
> fits within that batch but exceeds the existing 20480 KiB DELTA_MAX.
>
> I also tested a small follow-up that increases only the lower allowance
> for the 100, 300 and 400 MiB checks. It passed 10/10 runs, with all nine
> subtests passing each time.
>
> I will send this follow-up once Jan’s patch is merged.
Based on your tests it does sound like it's an incomplete fix, so
I'd suggest you modify it as you see fit, and send v2.
Thanks,
Jan
>
> Regards,
> Nirmoy
>
> From: Cyril Hrubis <chrubis@suse.cz>
> Date: Tuesday, 15. September 2026 at 17:29
> To: Nirmoy Das <nirmoyd@nvidia.com>
> Cc: ltp@lists.linux.it <ltp@lists.linux.it>; Jan Stancek <jstancek@redhat.com>
> Subject: Re: [PATCH v2] getrusage03: account for percpu RSS counter batching
>
> [You don't often get email from chrubis@suse.cz. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
>
> Hi!
> > 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);
>
> As long as we pin to a single CPU the whole batch accounting shouldn't
> be needed.
>
> FYI Jan send a similar patch that just pins the process to a single CPU:
>
> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpatchwork.kernel.org%2Fproject%2Fltp%2Fpatch%2Fa308e12198ce96305761a009858fa4a80c91f932.1788518850.git.jstancek%40redhat.com%2F&data=05%7C02%7Cnirmoyd%40nvidia.com%7C5c88fc4e5490430569b008df133e14f3%7C43083d15727340c1b7db39efd9ccc17a%7C0%7C0%7C639250829531773556%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=qOkWQ7VsVwFS38S1zQgxue5eo8kNqUJ%2BEHl4rN80qIQ%3D&reserved=0
>
> As far as I can tell that should be enough to fix the test.
>
> --
> Cyril Hrubis
> chrubis@suse.cz
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [LTP] [PATCH v2] getrusage03: account for percpu RSS counter batching
2026-09-17 12:36 ` Jan Stancek via ltp
@ 2026-09-22 17:36 ` Petr Vorel
2026-10-01 18:55 ` Nirmoy Das via ltp
0 siblings, 1 reply; 12+ messages in thread
From: Petr Vorel @ 2026-09-22 17:36 UTC (permalink / raw)
To: Jan Stancek; +Cc: Nirmoy Das, ltp@lists.linux.it
Hi Nirmoy, Jan, all,
would you have time to look on this getrusage03 failure on aarch64?
I guess this one [1] is closer than the one from Jan [2].
I'm not sure if we have time to fix this before LTP release (I guess Cyril plans
it sometimes next week) but it'd be worth to fix it even after the release.
[1] https://patchwork.kernel.org/project/ltp/patch/20260902160113.1207205-1-nirmoyd@nvidia.com/
[2] https://patchwork.kernel.org/project/ltp/patch/a308e12198ce96305761a009858fa4a80c91f932.1788518850.git.jstancek@redhat.com/
Kind regards,
Petr
> On Wed, Sep 16, 2026 at 5:59 PM Nirmoy Das <nirmoyd@nvidia.com> wrote:
> > Hi Cyril,
> > I tested Jan’s patch on a machine with 352 online CPUs and 64 KiB pages. Pinning was confirmed, but both the
> > baseline and Jan’s patch failed 10/10 runs:
> > child.children = 270336, expected 307200
> > Pinning keeps the allocation updates on one CPU, but get_mm_counter()
> > still reads only the global count. One batch here is
> > max(32, 352 * 2) = 704 pages, or 45056 KiB. The 36864 KiB shortfall
> > fits within that batch but exceeds the existing 20480 KiB DELTA_MAX.
> > I also tested a small follow-up that increases only the lower allowance
> > for the 100, 300 and 400 MiB checks. It passed 10/10 runs, with all nine
> > subtests passing each time.
> > I will send this follow-up once Jan’s patch is merged.
> Based on your tests it does sound like it's an incomplete fix, so
> I'd suggest you modify it as you see fit, and send v2.
> Thanks,
> Jan
> > Regards,
> > Nirmoy
> > From: Cyril Hrubis <chrubis@suse.cz>
> > Date: Tuesday, 15. September 2026 at 17:29
> > To: Nirmoy Das <nirmoyd@nvidia.com>
> > Cc: ltp@lists.linux.it <ltp@lists.linux.it>; Jan Stancek <jstancek@redhat.com>
> > Subject: Re: [PATCH v2] getrusage03: account for percpu RSS counter batching
> > [You don't often get email from chrubis@suse.cz. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
> > Hi!
> > > 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);
> > As long as we pin to a single CPU the whole batch accounting shouldn't
> > be needed.
> > FYI Jan send a similar patch that just pins the process to a single CPU:
> > https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpatchwork.kernel.org%2Fproject%2Fltp%2Fpatch%2Fa308e12198ce96305761a009858fa4a80c91f932.1788518850.git.jstancek%40redhat.com%2F&data=05%7C02%7Cnirmoyd%40nvidia.com%7C5c88fc4e5490430569b008df133e14f3%7C43083d15727340c1b7db39efd9ccc17a%7C0%7C0%7C639250829531773556%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=qOkWQ7VsVwFS38S1zQgxue5eo8kNqUJ%2BEHl4rN80qIQ%3D&reserved=0
> > As far as I can tell that should be enough to fix the test.
> > --
> > Cyril Hrubis
> > chrubis@suse.cz
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [LTP] [PATCH v2] getrusage03: account for percpu RSS counter batching
2026-09-22 17:36 ` Petr Vorel
@ 2026-10-01 18:55 ` Nirmoy Das via ltp
0 siblings, 0 replies; 12+ messages in thread
From: Nirmoy Das via ltp @ 2026-10-01 18:55 UTC (permalink / raw)
To: Petr Vorel, Jan Stancek; +Cc: ltp@lists.linux.it
Hi Petr,
Sorry for the late reply; I was on PTO. I'll address Cyril's comments and send the updated patch.
Regards,
Nirmoy
From: Petr Vorel <pvorel@suse.cz>
Date: Tuesday, 22. September 2026 at 19:37
To: Jan Stancek <jstancek@redhat.com>
Cc: Nirmoy Das <nirmoyd@nvidia.com>; ltp@lists.linux.it <ltp@lists.linux.it>; Cyril Hrubis <chrubis@suse.cz>; Li Wang <li.wang@linux.dev>
Subject: Re: [LTP] [PATCH v2] getrusage03: account for percpu RSS counter batching
Hi Nirmoy, Jan, all,
would you have time to look on this getrusage03 failure on aarch64?
I guess this one [1] is closer than the one from Jan [2].
I'm not sure if we have time to fix this before LTP release (I guess Cyril plans
it sometimes next week) but it'd be worth to fix it even after the release.
[1] https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpatchwork.kernel.org%2Fproject%2Fltp%2Fpatch%2F20260902160113.1207205-1-nirmoyd%40nvidia.com%2F&data=05%7C02%7Cnirmoyd%40nvidia.com%7Ca7f3d58e3f464fe9de6d08df18d0261b%7C43083d15727340c1b7db39efd9ccc17a%7C0%7C0%7C639256954742729955%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=dJpWuU%2FPRYQfRhBeQGr1dUy%2But8y0zS%2BcfoIzLdyGOY%3D&reserved=0<https://patchwork.kernel.org/project/ltp/patch/20260902160113.1207205-1-nirmoyd@nvidia.com/>
[2] https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpatchwork.kernel.org%2Fproject%2Fltp%2Fpatch%2Fa308e12198ce96305761a009858fa4a80c91f932.1788518850.git.jstancek%40redhat.com%2F&data=05%7C02%7Cnirmoyd%40nvidia.com%7Ca7f3d58e3f464fe9de6d08df18d0261b%7C43083d15727340c1b7db39efd9ccc17a%7C0%7C0%7C639256954742758548%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=GR1yOwdI3RPk3n8qLtFmzUrndSOKzTFaXVWypvjwBbc%3D&reserved=0<https://patchwork.kernel.org/project/ltp/patch/a308e12198ce96305761a009858fa4a80c91f932.1788518850.git.jstancek@redhat.com/>
Kind regards,
Petr
> On Wed, Sep 16, 2026 at 5:59 PM Nirmoy Das <nirmoyd@nvidia.com> wrote:
> > Hi Cyril,
> > I tested Jan’s patch on a machine with 352 online CPUs and 64 KiB pages. Pinning was confirmed, but both the
> > baseline and Jan’s patch failed 10/10 runs:
> > child.children = 270336, expected 307200
> > Pinning keeps the allocation updates on one CPU, but get_mm_counter()
> > still reads only the global count. One batch here is
> > max(32, 352 * 2) = 704 pages, or 45056 KiB. The 36864 KiB shortfall
> > fits within that batch but exceeds the existing 20480 KiB DELTA_MAX.
> > I also tested a small follow-up that increases only the lower allowance
> > for the 100, 300 and 400 MiB checks. It passed 10/10 runs, with all nine
> > subtests passing each time.
> > I will send this follow-up once Jan’s patch is merged.
> Based on your tests it does sound like it's an incomplete fix, so
> I'd suggest you modify it as you see fit, and send v2.
> Thanks,
> Jan
> > Regards,
> > Nirmoy
> > From: Cyril Hrubis <chrubis@suse.cz>
> > Date: Tuesday, 15. September 2026 at 17:29
> > To: Nirmoy Das <nirmoyd@nvidia.com>
> > Cc: ltp@lists.linux.it <ltp@lists.linux.it>; Jan Stancek <jstancek@redhat.com>
> > Subject: Re: [PATCH v2] getrusage03: account for percpu RSS counter batching
> > [You don't often get email from chrubis@suse.cz. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
> > Hi!
> > > 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);
> > As long as we pin to a single CPU the whole batch accounting shouldn't
> > be needed.
> > FYI Jan send a similar patch that just pins the process to a single CPU:
> > https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpatchwork.kernel.org%2Fproject%2Fltp%2Fpatch%2Fa308e12198ce96305761a009858fa4a80c91f932.1788518850.git.jstancek%40redhat.com%2F&data=05%7C02%7Cnirmoyd%40nvidia.com%7Ca7f3d58e3f464fe9de6d08df18d0261b%7C43083d15727340c1b7db39efd9ccc17a%7C0%7C0%7C639256954742783153%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=AKQQsjSqO3jyBH7spTGfzx7iQ0FmcUv1AQhZtWeEwXc%3D&reserved=0<https://patchwork.kernel.org/project/ltp/patch/a308e12198ce96305761a009858fa4a80c91f932.1788518850.git.jstancek@redhat.com/>
> > As far as I can tell that should be enough to fix the test.
> > --
> > Cyril Hrubis
> > chrubis@suse.cz
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [LTP] [PATCH v2] getrusage03: account for percpu RSS counter batching
2026-09-02 16:01 ` [LTP] [PATCH v2] " Nirmoy Das via ltp
2026-09-02 17:42 ` [LTP] " linuxtestproject.agent
2026-09-15 15:29 ` [LTP] [PATCH v2] " Cyril Hrubis
@ 2026-09-24 11:26 ` Cyril Hrubis
2 siblings, 0 replies; 12+ messages in thread
From: Cyril Hrubis @ 2026-09-24 11:26 UTC (permalink / raw)
To: Nirmoy Das; +Cc: ltp
Hi!
> 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;
> +}
We do have tst_ncpus() in the test library, please use that instead.
> +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);
> +}
I like the funciton from Jan that pins the test to the current CPU
slightly better.
The rest looks good.
--
Cyril Hrubis
chrubis@suse.cz
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 12+ messages in thread
* [LTP] [PATCH v3] getrusage03: account for percpu RSS counter batching
@ 2026-10-02 13:17 Nirmoy Das via ltp
2026-10-02 13:40 ` [LTP] " linuxtestproject.agent
0 siblings, 1 reply; 12+ messages in thread
From: Nirmoy Das via ltp @ 2026-10-02 13:17 UTC (permalink / raw)
To: ltp; +Cc: Nirmoy Das
After f1a7941243c1 ("mm: convert mm's rss stats into percpu_counter"),
the fixed 20 MiB tolerance can be too small on large systems. Pinning
limits pending RSS updates to one CPU, but that CPU can still hold one
batch outside the fast RSS read.
Pin the test to its current CPU and allow one batch of lower-side slack
for the 100, 300 and 400 MiB allocation checks. Keep the existing upper
and inheritance tolerances, and skip if one batch is at least 100 MiB.
On 352 CPUs with 64 KiB pages, one batch is 44 MiB. Pinning alone
reported 270336 KiB for the 300 MiB check, outside the 20 MiB tolerance.
The updated test passed 10/10 runs on the 352-CPU Vera system.
Suggested-by: Cyril Hrubis <chrubis@suse.cz>
Co-developed-by: Jan Stancek <jstancek@redhat.com>
Signed-off-by: Jan Stancek <jstancek@redhat.com>
Assisted-by: ClaudeCode:claude-opus-5-5
Signed-off-by: Nirmoy Das <nirmoyd@nvidia.com>
---
Changes in v3:
- Use tst_ncpus() and pin to the current CPU (Cyril).
- Allocate the CPU mask dynamically and log the allowance.
v2: https://lore.kernel.org/ltp/20260902160113.1207205-1-nirmoyd@nvidia.com/
.../kernel/syscalls/getrusage/getrusage03.c | 87 +++++++++++++++----
1 file changed, 71 insertions(+), 16 deletions(-)
diff --git a/testcases/kernel/syscalls/getrusage/getrusage03.c b/testcases/kernel/syscalls/getrusage/getrusage03.c
index a2cdd6158..6beae130d 100644
--- a/testcases/kernel/syscalls/getrusage/getrusage03.c
+++ b/testcases/kernel/syscalls/getrusage/getrusage03.c
@@ -13,22 +13,88 @@
* this program.
*/
-#include <stdlib.h>
+#define _GNU_SOURCE
#include <stdio.h>
+#include <stdlib.h>
#include "tst_test.h"
+#include "lapi/cpuset.h"
+#include "lapi/sched.h"
#include "getrusage03.h"
#define TESTBIN "getrusage03_child"
static struct rusage ru;
static long maxrss_init;
+static long lower_allowance;
static const char *const resource[] = {
TESTBIN,
NULL,
};
+/*
+ * Pin the test to the CPU it runs on. Every forked or exec'd child inherits
+ * the affinity, so only that CPU can hold RSS counter updates outside the
+ * fast percpu_counter read.
+ */
+static void pin_to_current_cpu(void)
+{
+ unsigned int cpu;
+ cpu_set_t *set;
+ size_t size;
+
+ if (getcpu(&cpu, NULL))
+ tst_brk(TBROK | TERRNO, "getcpu() failed");
+
+ set = CPU_ALLOC(cpu + 1);
+ if (!set)
+ tst_brk(TBROK | TERRNO, "CPU_ALLOC() failed");
+
+ size = CPU_ALLOC_SIZE(cpu + 1);
+ CPU_ZERO_S(size, set);
+ CPU_SET_S(cpu, size, set);
+ if (sched_setaffinity(0, size, set))
+ tst_brk(TBROK | TERRNO, "sched_setaffinity() failed");
+
+ CPU_FREE(set);
+ tst_res(TINFO, "Pinned to CPU %u", cpu);
+}
+
+/*
+ * The pinned CPU can still hold up to one percpu_counter batch,
+ * max(32, 2 * online CPUs) pages, outside the fast RSS read. Count CPUs
+ * before pinning because some libc implementations count only the affinity
+ * mask.
+ */
+static void setup(void)
+{
+ long online_cpus = tst_ncpus();
+ 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);
+
+ tst_res(TINFO, "%li online CPUs, lower RSS allowance %li KiB",
+ online_cpus, lower_allowance);
+
+ pin_to_current_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 +117,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 +140,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 +164,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 +228,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: dca9f0d272b2923256852fc37abd222b533d91e0
--
2.43.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 12+ messages in thread* Re: [LTP] getrusage03: account for percpu RSS counter batching
2026-10-02 13:17 [LTP] [PATCH v3] " Nirmoy Das via ltp
@ 2026-10-02 13:40 ` linuxtestproject.agent
0 siblings, 0 replies; 12+ messages in thread
From: linuxtestproject.agent @ 2026-10-02 13:40 UTC (permalink / raw)
To: Nirmoy Das; +Cc: ltp
Hi Nirmoy,
On 2026-10-02, Nirmoy Das wrote:
> getrusage03: account for percpu RSS counter batching
> long online_cpus = tst_ncpus();
> long batch = MAX(32L, online_cpus * 2);
Medium: On musl, tst_ncpus() counts the calling thread's affinity mask,
so an inherited taskset/cpuset restriction still underestimates the kernel's
global batch even before pinning. With 352 online CPUs, 64 KiB pages and
single-CPU inherited affinity, this chooses 20 MiB rather than 44 MiB and
rejects a valid 270336 KiB result for the 300 MiB allocation. Obtain the
system-wide online count independently of affinity, for example by counting
the CPU ranges in /sys/devices/system/cpu/online.
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] 12+ messages in thread
end of thread, other threads:[~2026-10-02 13:41 UTC | newest]
Thread overview: 12+ 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
2026-09-15 15:29 ` [LTP] [PATCH v2] " Cyril Hrubis
2026-09-16 15:58 ` Nirmoy Das via ltp
2026-09-17 12:36 ` Jan Stancek via ltp
2026-09-22 17:36 ` Petr Vorel
2026-10-01 18:55 ` Nirmoy Das via ltp
2026-09-24 11:26 ` Cyril Hrubis
-- strict thread matches above, loose matches on Subject: below --
2026-10-02 13:17 [LTP] [PATCH v3] " Nirmoy Das via ltp
2026-10-02 13:40 ` [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