The overcommit test uses sum_total, the sum (memory and swap) to test the overcommit settings.
This fixes two problems on 32-bit systems. The first is seen with a integer overflow can occur when calculating sum_total * 2, if the sum_total is larger than 2GB. The second is limited virtual address space (2-3GB) means the test can fail from address space exhaustion before overcommit has been tested.
Now the test runs correctly on low-memory 32-bit systems while avoiding both the overflow bug and virtual address space issues.
Signed-off-by: Ben Copeland ben.copeland@linaro.org Acked-by: Arnd Bergmann arnd@arndb.de Reviewed-by: Petr Vorel pvorel@suse.cz --- .../kernel/mem/tunable/overcommit_memory.c | 33 +++++++++++++++---- 1 file changed, 27 insertions(+), 6 deletions(-)
diff --git a/testcases/kernel/mem/tunable/overcommit_memory.c b/testcases/kernel/mem/tunable/overcommit_memory.c index 9b2cb479d..7ff5a98d0 100644 --- a/testcases/kernel/mem/tunable/overcommit_memory.c +++ b/testcases/kernel/mem/tunable/overcommit_memory.c @@ -131,24 +131,45 @@ static void overcommit_memory_test(void) TST_SYS_CONF_LONG_SET(OVERCOMMIT_MEMORY, 2, 1);
update_mem_commit(); - alloc_and_check(commit_left * 2, EXPECT_FAIL); - alloc_and_check(commit_limit + total_batch_size, EXPECT_FAIL); + /* Skip tests that would overflow or exceed 32-bit address space */ + if (tst_kernel_bits() == 64 || (unsigned long)commit_left <= TST_GB / TST_KB) { + alloc_and_check(commit_left * 2, EXPECT_FAIL); + alloc_and_check(commit_limit + total_batch_size, EXPECT_FAIL); + } else { + tst_res(TCONF, "Skipping large allocation tests due to address space limits"); + } update_mem_commit(); - alloc_and_check(commit_left / 2, EXPECT_PASS); + if (tst_kernel_bits() == 64 || (unsigned long)commit_left <= TST_GB / TST_KB) { + alloc_and_check(commit_left / 2, EXPECT_PASS); + } else { + tst_res(TCONF, "Skipping commit_left/2 allocation test due to address space limits"); + }
/* start to test overcommit_memory=0 */ TST_SYS_CONF_LONG_SET(OVERCOMMIT_MEMORY, 0, 1);
update_mem(); alloc_and_check(free_total / 2, EXPECT_PASS); - alloc_and_check(sum_total * 2, EXPECT_FAIL); + /* Skip if sum_total * 2 would exceed address space. + * On 32-bit, skip when sum_total > ULONG_MAX/4 (~1GB). + * Most 32-bit systems with <=1GB RAM can map 2x that in 3GB vaddr space. + * Systems with 2GB+ RAM likely cannot fit allocations in vaddr space. */ + if (tst_kernel_bits() == 64 || (unsigned long)sum_total <= TST_GB / TST_KB) { + alloc_and_check(sum_total * 2, EXPECT_FAIL); + } else { + tst_res(TCONF, "Skipping large allocation test due to address space limits"); + }
/* start to test overcommit_memory=1 */ TST_SYS_CONF_LONG_SET(OVERCOMMIT_MEMORY, 1, 1);
alloc_and_check(sum_total / 2, EXPECT_PASS); - alloc_and_check(sum_total, EXPECT_PASS); - alloc_and_check(sum_total * 2, EXPECT_PASS); + if (tst_kernel_bits() == 64 || (unsigned long)sum_total <= TST_GB / TST_KB) { + alloc_and_check(sum_total, EXPECT_PASS); + alloc_and_check(sum_total * 2, EXPECT_PASS); + } else { + tst_res(TCONF, "Skipping large allocation tests due to address space limits"); + }
}
The overcommit test uses sum_total, the sum (memory and swap) to test the overcommit settings.
This fixes two problems on 32-bit systems. The first is seen with a integer overflow can occur when calculating sum_total * 2, if the sum_total is larger than 2GB. The second is limited virtual address
You still mention GB ...
space (2-3GB) means the test can fail from address space exhaustion before overcommit has been tested.
Now the test runs correctly on low-memory 32-bit systems while avoiding both the overflow bug and virtual address space issues.
Signed-off-by: Ben Copeland ben.copeland@linaro.org Acked-by: Arnd Bergmann arnd@arndb.de Reviewed-by: Petr Vorel pvorel@suse.cz
.../kernel/mem/tunable/overcommit_memory.c | 33 +++++++++++++++---- 1 file changed, 27 insertions(+), 6 deletions(-)
diff --git a/testcases/kernel/mem/tunable/overcommit_memory.c b/testcases/kernel/mem/tunable/overcommit_memory.c index 9b2cb479d..7ff5a98d0 100644 --- a/testcases/kernel/mem/tunable/overcommit_memory.c +++ b/testcases/kernel/mem/tunable/overcommit_memory.c @@ -131,24 +131,45 @@ static void overcommit_memory_test(void) TST_SYS_CONF_LONG_SET(OVERCOMMIT_MEMORY, 2, 1);
update_mem_commit();
- alloc_and_check(commit_left * 2, EXPECT_FAIL);
- alloc_and_check(commit_limit + total_batch_size, EXPECT_FAIL);
- /* Skip tests that would overflow or exceed 32-bit address space */
- if (tst_kernel_bits() == 64 || (unsigned long)commit_left <= TST_GB / TST_KB) {
... but TST_GB / TST_KB is actually MB (you could use TST_MB).
Yes, this fixes the problem on i686 as the tests are skipped as sum_total is smaller than 1MB.
Kind regards, Petr
tst_kernel.c:90: TINFO: uname.machine=i686 kernel is 32bit tst_test.c:2021: TINFO: LTP version: 20250930 tst_test.c:2024: TINFO: Tested kernel: 6.17.1-1-default #1 SMP PREEMPT_DYNAMIC Tue Oct 7 04:26:30 UTC 2025 (1bf5c2e) i686 tst_kconfig.c:88: TINFO: Parsing kernel config '/proc/config.gz' tst_kconfig.c:676: TINFO: CONFIG_FAULT_INJECTION kernel option detected which might slow the execution tst_test.c:1842: TINFO: Overall timeout per run is 0h 02m 00s overcommit_memory.c:104: TINFO: MemTotal is 2050308 kB overcommit_memory.c:106: TINFO: SwapTotal is 2098152 kB overcommit_memory.c:110: TINFO: CommitLimit is 3121256 kB overcommit_memory.c:123: TINFO: Setting /proc/sys/vm/overcommit_ratio to 30 overcommit_memory.c:126: TINFO: TotalBatchSize is 8008 kB overcommit_memory.c:132: TINFO: Setting /proc/sys/vm/overcommit_memory to 2 overcommit_memory.c:140: TCONF: Skipping large allocation tests due to address space limits overcommit_memory.c:146: TCONF: Skipping commit_left/2 allocation test due to address space limits overcommit_memory.c:150: TINFO: Setting /proc/sys/vm/overcommit_memory to 0 overcommit_memory.c:152: TINFO: ONE_GB: 1073741824 overcommit_memory.c:153: TINFO: TST_GB: 1073741824 overcommit_memory.c:154: TINFO: TST_MB: 1048576 overcommit_memory.c:155: TINFO: TST_GB / TST_KB: 1048576 overcommit_memory.c:156: TINFO: TST_MB * 1024: 1073741824 overcommit_memory.c:157: TINFO: tst_kernel_bits(): 32 overcommit_memory.c:158: TINFO: (unsigned long)sum_total <= ONE_GB: 1 overcommit_memory.c:159: TINFO: (unsigned long)sum_total <= TST_GB: 1 overcommit_memory.c:160: TINFO: condition: 1 overcommit_memory.c:193: TINFO: malloc 1669706 kB successfully overcommit_memory.c:212: TPASS: alloc passed as expected overcommit_memory.c:171: TCONF: Skipping large allocation test due to address space limits overcommit_memory.c:175: TINFO: Setting /proc/sys/vm/overcommit_memory to 1 overcommit_memory.c:193: TINFO: malloc 2074230 kB successfully overcommit_memory.c:212: TPASS: alloc passed as expected overcommit_memory.c:182: TCONF: Skipping large allocation tests due to address space limits
alloc_and_check(commit_left * 2, EXPECT_FAIL);alloc_and_check(commit_limit + total_batch_size, EXPECT_FAIL);- } else {
tst_res(TCONF, "Skipping large allocation tests due to address space limits");- } update_mem_commit();
- alloc_and_check(commit_left / 2, EXPECT_PASS);
- if (tst_kernel_bits() == 64 || (unsigned long)commit_left <= TST_GB / TST_KB) {
alloc_and_check(commit_left / 2, EXPECT_PASS);- } else {
tst_res(TCONF, "Skipping commit_left/2 allocation test due to address space limits");- }
/* start to test overcommit_memory=0 */ TST_SYS_CONF_LONG_SET(OVERCOMMIT_MEMORY, 0, 1);
update_mem(); alloc_and_check(free_total / 2, EXPECT_PASS);
- alloc_and_check(sum_total * 2, EXPECT_FAIL);
- /* Skip if sum_total * 2 would exceed address space.
* On 32-bit, skip when sum_total > ULONG_MAX/4 (~1GB).* Most 32-bit systems with <=1GB RAM can map 2x that in 3GB vaddr space.* Systems with 2GB+ RAM likely cannot fit allocations in vaddr space. */- if (tst_kernel_bits() == 64 || (unsigned long)sum_total <= TST_GB / TST_KB) {
alloc_and_check(sum_total * 2, EXPECT_FAIL);- } else {
tst_res(TCONF, "Skipping large allocation test due to address space limits");- }
/* start to test overcommit_memory=1 */ TST_SYS_CONF_LONG_SET(OVERCOMMIT_MEMORY, 1, 1);
alloc_and_check(sum_total / 2, EXPECT_PASS);
- alloc_and_check(sum_total, EXPECT_PASS);
- alloc_and_check(sum_total * 2, EXPECT_PASS);
- if (tst_kernel_bits() == 64 || (unsigned long)sum_total <= TST_GB / TST_KB) {
alloc_and_check(sum_total, EXPECT_PASS);alloc_and_check(sum_total * 2, EXPECT_PASS);- } else {
tst_res(TCONF, "Skipping large allocation tests due to address space limits");- }
}
On Wed, Oct 15, 2025 at 04:42:47PM +0200, Petr Vorel wrote:
The overcommit test uses sum_total, the sum (memory and swap) to test the overcommit settings.
This fixes two problems on 32-bit systems. The first is seen with a integer overflow can occur when calculating sum_total * 2, if the sum_total is larger than 2GB. The second is limited virtual address
You still mention GB ...
Yep. It is GB.
space (2-3GB) means the test can fail from address space exhaustion before overcommit has been tested.
Now the test runs correctly on low-memory 32-bit systems while avoiding both the overflow bug and virtual address space issues.
Signed-off-by: Ben Copeland ben.copeland@linaro.org Acked-by: Arnd Bergmann arnd@arndb.de Reviewed-by: Petr Vorel pvorel@suse.cz
.../kernel/mem/tunable/overcommit_memory.c | 33 +++++++++++++++---- 1 file changed, 27 insertions(+), 6 deletions(-)
diff --git a/testcases/kernel/mem/tunable/overcommit_memory.c b/testcases/kernel/mem/tunable/overcommit_memory.c index 9b2cb479d..7ff5a98d0 100644 --- a/testcases/kernel/mem/tunable/overcommit_memory.c +++ b/testcases/kernel/mem/tunable/overcommit_memory.c @@ -131,24 +131,45 @@ static void overcommit_memory_test(void) TST_SYS_CONF_LONG_SET(OVERCOMMIT_MEMORY, 2, 1);
update_mem_commit();
- alloc_and_check(commit_left * 2, EXPECT_FAIL);
- alloc_and_check(commit_limit + total_batch_size, EXPECT_FAIL);
- /* Skip tests that would overflow or exceed 32-bit address space */
- if (tst_kernel_bits() == 64 || (unsigned long)commit_left <= TST_GB / TST_KB) {
... but TST_GB / TST_KB is actually MB (you could use TST_MB).
The sizes in this test are measured in KB, so it's 1GB but measured in terms of KB not bytes. Using TST_MB would work mathematically but it's misleading.
regards, dan carpenter
On Wed, Oct 15, 2025 at 04:42:47PM +0200, Petr Vorel wrote:
The overcommit test uses sum_total, the sum (memory and swap) to test the overcommit settings.
This fixes two problems on 32-bit systems. The first is seen with a integer overflow can occur when calculating sum_total * 2, if the sum_total is larger than 2GB. The second is limited virtual address
You still mention GB ...
Yep. It is GB.
space (2-3GB) means the test can fail from address space exhaustion before overcommit has been tested.
Now the test runs correctly on low-memory 32-bit systems while avoiding both the overflow bug and virtual address space issues.
Signed-off-by: Ben Copeland ben.copeland@linaro.org Acked-by: Arnd Bergmann arnd@arndb.de Reviewed-by: Petr Vorel pvorel@suse.cz
.../kernel/mem/tunable/overcommit_memory.c | 33 +++++++++++++++---- 1 file changed, 27 insertions(+), 6 deletions(-)
diff --git a/testcases/kernel/mem/tunable/overcommit_memory.c b/testcases/kernel/mem/tunable/overcommit_memory.c index 9b2cb479d..7ff5a98d0 100644 --- a/testcases/kernel/mem/tunable/overcommit_memory.c +++ b/testcases/kernel/mem/tunable/overcommit_memory.c @@ -131,24 +131,45 @@ static void overcommit_memory_test(void) TST_SYS_CONF_LONG_SET(OVERCOMMIT_MEMORY, 2, 1);
update_mem_commit();
- alloc_and_check(commit_left * 2, EXPECT_FAIL);
- alloc_and_check(commit_limit + total_batch_size, EXPECT_FAIL);
- /* Skip tests that would overflow or exceed 32-bit address space */
- if (tst_kernel_bits() == 64 || (unsigned long)commit_left <= TST_GB / TST_KB) {
... but TST_GB / TST_KB is actually MB (you could use TST_MB).
The sizes in this test are measured in KB, so it's 1GB but measured in terms of KB not bytes. Using TST_MB would work mathematically but it's misleading.
Ah, I'm sorry to overlook an obvious point.
Implementation details: thinking about the code twice, shouldn't be the check for overflow in alloc_and_check() instead of outside (to keep the condition on single place)?
Also, if kept outside the 1st and 2nd if could be joined:
/* Skip tests that would overflow or exceed 32-bit address space */ if (tst_kernel_bits() == 64 || (unsigned long)commit_left <= TST_GB / TST_KB) { alloc_and_check(commit_left * 2, EXPECT_FAIL); alloc_and_check(commit_limit + total_batch_size, EXPECT_FAIL); update_mem_commit(); alloc_and_check(commit_left / 2, EXPECT_PASS); } else { tst_res(TCONF, "Skipping large allocation tests due to address space limits"); }
instead of your proposal:
update_mem_commit(); /* Skip tests that would overflow or exceed 32-bit address space */ if (tst_kernel_bits() == 64 || (unsigned long)commit_left <= TST_GB / TST_KB) { alloc_and_check(commit_left * 2, EXPECT_FAIL); alloc_and_check(commit_limit + total_batch_size, EXPECT_FAIL); } else { tst_res(TCONF, "Skipping large allocation tests due to address space limits"); } update_mem_commit(); if (tst_kernel_bits() == 64 || (unsigned long)commit_left <= TST_GB / TST_KB) { alloc_and_check(commit_left / 2, EXPECT_PASS); } else { tst_res(TCONF, "Skipping commit_left/2 allocation test due to address space limits"); }
because update_mem_commit() IMHO just evaluates /proc/meminfo values, but when alloc_and_check() is skipped nothing has changed.
Kind regards, Petr
regards, dan carpenter
Hello Petr,
On Wed, 15 Oct 2025 at 17:02, Petr Vorel pvorel@suse.cz wrote:
On Wed, Oct 15, 2025 at 04:42:47PM +0200, Petr Vorel wrote:
The overcommit test uses sum_total, the sum (memory and swap) to test the overcommit settings.
This fixes two problems on 32-bit systems. The first is seen with a integer overflow can occur when calculating sum_total * 2, if the sum_total is larger than 2GB. The second is limited virtual address
You still mention GB ...
Yep. It is GB.
space (2-3GB) means the test can fail from address space exhaustion before overcommit has been tested.
Now the test runs correctly on low-memory 32-bit systems while avoiding both the overflow bug and virtual address space issues.
Signed-off-by: Ben Copeland ben.copeland@linaro.org Acked-by: Arnd Bergmann arnd@arndb.de Reviewed-by: Petr Vorel pvorel@suse.cz
.../kernel/mem/tunable/overcommit_memory.c | 33 +++++++++++++++---- 1 file changed, 27 insertions(+), 6 deletions(-)
diff --git a/testcases/kernel/mem/tunable/overcommit_memory.c b/testcases/kernel/mem/tunable/overcommit_memory.c index 9b2cb479d..7ff5a98d0 100644 --- a/testcases/kernel/mem/tunable/overcommit_memory.c +++ b/testcases/kernel/mem/tunable/overcommit_memory.c @@ -131,24 +131,45 @@ static void overcommit_memory_test(void) TST_SYS_CONF_LONG_SET(OVERCOMMIT_MEMORY, 2, 1);
update_mem_commit();
- alloc_and_check(commit_left * 2, EXPECT_FAIL);
- alloc_and_check(commit_limit + total_batch_size, EXPECT_FAIL);
- /* Skip tests that would overflow or exceed 32-bit address space */
- if (tst_kernel_bits() == 64 || (unsigned long)commit_left <= TST_GB / TST_KB) {
... but TST_GB / TST_KB is actually MB (you could use TST_MB).
The sizes in this test are measured in KB, so it's 1GB but measured in terms of KB not bytes. Using TST_MB would work mathematically but it's misleading.
Ah, I'm sorry to overlook an obvious point.
Implementation details: thinking about the code twice, shouldn't be the check for overflow in alloc_and_check() instead of outside (to keep the condition on single place)?
Excellent suggestion. It makes sense to simplify it like that. I will spin up a v3 patch with those changes.
Ben
Also, if kept outside the 1st and 2nd if could be joined:
/* Skip tests that would overflow or exceed 32-bit address space */ if (tst_kernel_bits() == 64 || (unsigned long)commit_left <= TST_GB / TST_KB) { alloc_and_check(commit_left * 2, EXPECT_FAIL); alloc_and_check(commit_limit + total_batch_size, EXPECT_FAIL); update_mem_commit(); alloc_and_check(commit_left / 2, EXPECT_PASS); } else { tst_res(TCONF, "Skipping large allocation tests due to address space limits"); }instead of your proposal:
update_mem_commit(); /* Skip tests that would overflow or exceed 32-bit address space */ if (tst_kernel_bits() == 64 || (unsigned long)commit_left <= TST_GB / TST_KB) { alloc_and_check(commit_left * 2, EXPECT_FAIL); alloc_and_check(commit_limit + total_batch_size, EXPECT_FAIL); } else { tst_res(TCONF, "Skipping large allocation tests due to address space limits"); } update_mem_commit(); if (tst_kernel_bits() == 64 || (unsigned long)commit_left <= TST_GB / TST_KB) { alloc_and_check(commit_left / 2, EXPECT_PASS); } else { tst_res(TCONF, "Skipping commit_left/2 allocation test due to address space limits"); }because update_mem_commit() IMHO just evaluates /proc/meminfo values, but when alloc_and_check() is skipped nothing has changed.
Kind regards, Petr
regards, dan carpenter