[LTP] [PATCH] mem/min_free_kbytes: Fix incorrect pass/fail accounting
Sachin Sant
sachinp@linux.ibm.com
Wed Jul 8 14:42:05 CEST 2026
When check_monitor() detected a violation (MemFree < min_free_kbytes) it
called tst_res(TFAIL, ...) from the child process, which atomically
incremented the shared results->failed counter, and then the child exited
with status 0. Back in the parent, min_free_kbytes_test() checked the
child exit status, found it was 0, and fell through to the unconditional
tst_res(TPASS, ...) at the end of the function.
This produced a misleading summary of 'passed 1 / failed 1' on violation:
the TFAIL from the monitor child was correctly counted, but the
unconditional TPASS that followed also added to the pass count regardless
of the violation.
Fix this by:
- Removing the tst_res(TFAIL, ...) from check_monitor() and replacing it
with a local 'violated' flag; the TINFO diagnostic is kept so the exact
MemFree and tune values are still logged.
- Returning 'violated' from check_monitor() and passing it directly to
exit(), so the child exits non-zero when a violation was detected.
- Restructuring the parent's wait-result check so that TPASS is only
emitted when the monitor child exited normally with status 0; any other
termination (signal death, unexpected non-zero exit) maps to TFAIL.
A violation exit (status == 1) emits a semantically accurate message;
all other abnormal exits fall back to tst_strstatus() for diagnostics.
After the fix the summary correctly reflects the outcome:
- No violation: passed 1 / failed 0
- Violation: passed 0 / failed 1
Signed-off-by: Sachin Sant <sachinp@linux.ibm.com>
---
.../kernel/mem/tunable/min_free_kbytes.c | 28 +++++++++++--------
1 file changed, 17 insertions(+), 11 deletions(-)
diff --git a/testcases/kernel/mem/tunable/min_free_kbytes.c b/testcases/kernel/mem/tunable/min_free_kbytes.c
index bdc9126c2..5bed61db5 100644
--- a/testcases/kernel/mem/tunable/min_free_kbytes.c
+++ b/testcases/kernel/mem/tunable/min_free_kbytes.c
@@ -41,7 +41,7 @@ static unsigned long total_mem;
static void test_tune(unsigned long overcommit_policy);
static int eatup_mem(unsigned long overcommit_policy);
-static void check_monitor(void);
+static int check_monitor(void);
static void sighandler(int signo LTP_ATTRIBUTE_UNUSED);
static void min_free_kbytes_test(void)
@@ -57,8 +57,7 @@ static void min_free_kbytes_test(void)
pid = SAFE_FORK();
if (pid == 0) {
/* startup the check monitor */
- check_monitor();
- exit(0);
+ exit(check_monitor());
}
test_tune(2);
@@ -68,11 +67,15 @@ static void min_free_kbytes_test(void)
SAFE_KILL(pid, SIGUSR1);
SAFE_WAITPID(pid, &status, WUNTRACED | WCONTINUED);
- if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
- tst_res(TFAIL, "check_monitor child exit with status: %s",
- tst_strstatus(status));
-
- tst_res(TPASS, "min_free_kbytes test pass");
+ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+ if (WIFEXITED(status) && WEXITSTATUS(status) == 1)
+ tst_res(TFAIL, "MemFree dropped below min_free_kbytes");
+ else
+ tst_res(TFAIL, "check_monitor child failed: %s",
+ tst_strstatus(status));
+ } else {
+ tst_res(TPASS, "min_free_kbytes test pass");
+ }
}
static void test_tune(unsigned long overcommit_policy)
@@ -171,8 +174,9 @@ static int eatup_mem(unsigned long overcommit_policy)
return ret;
}
-static void check_monitor(void)
+static int check_monitor(void)
{
+ int violated = 0;
unsigned long tune;
unsigned long memfree;
@@ -182,12 +186,14 @@ static void check_monitor(void)
if (memfree < tune) {
tst_res(TINFO, "MemFree is %lu kB, "
- "min_free_kbytes is %lu kB", memfree, tune);
- tst_res(TFAIL, "MemFree < min_free_kbytes");
+ "min_free_kbytes is %lu kB", memfree, tune);
+ violated = 1;
}
sleep(2);
}
+
+ return violated;
}
static void sighandler(int signo LTP_ATTRIBUTE_UNUSED)
--
2.39.1
More information about the ltp
mailing list