From: Samir Mulani <samir@linux.ibm.com>
To: ltp@lists.linux.it
Cc: Samir Mulani <samir@linux.ibm.com>
Subject: [LTP] [PATCH v1 1/4] sched/psi: Add psi_invalid_trigger01 test
Date: Sat, 24 Oct 2026 04:30:41 +0200 [thread overview]
Message-ID: <20261024023044.80055-2-samir@linux.ibm.com> (raw)
In-Reply-To: <20261024023044.80055-1-samir@linux.ibm.com>
Add a test case to verify trigger input validation in /proc/pressure/memory.
In the kernel (kernel/sched/psi.c), the trigger parsing logic (psi_trigger_create)
is identical and shared across /proc/pressure/{cpu,memory,io}. Therefore,
testing /proc/pressure/memory validates the parser for all PSI interfaces.
The test checks that invalid trigger strings return -EINVAL:
- Invalid trigger state (not "some" or "full")
- Missing threshold or window values
- Non-numeric or negative numbers
- Zero threshold or zero window
- Threshold larger than window
- Window larger than the 10 second maximum
It also checks that valid boundary values succeed:
- Smallest threshold (1us)
- Threshold equal to window
- Valid windows of 500ms, 2s, and 10s
- Valid "full" state
Note: The kernel overwrites the last byte of the input buffer with '\0',
so we write strlen() + 1 bytes to prevent losing the last character.
Requires CAP_SYS_RESOURCE for custom window sizes. Reports TCONF if
CONFIG_PSI is not enabled or disabled with psi=0.
This patch also adds the testcases/kernel/sched/psi directory, Makefile,
and .gitignore.
Signed-off-by: Samir Mulani <samir@linux.ibm.com>
---
runtest/sched | 2 +
testcases/kernel/sched/psi/.gitignore | 1 +
testcases/kernel/sched/psi/Makefile | 7 +
.../kernel/sched/psi/psi_invalid_trigger01.c | 135 ++++++++++++++++++
4 files changed, 145 insertions(+)
create mode 100644 testcases/kernel/sched/psi/.gitignore
create mode 100644 testcases/kernel/sched/psi/Makefile
create mode 100644 testcases/kernel/sched/psi/psi_invalid_trigger01.c
diff --git a/runtest/sched b/runtest/sched
index ecedd1a92..cc6e703d7 100644
--- a/runtest/sched
+++ b/runtest/sched
@@ -20,3 +20,5 @@ sched_stress sched_stress.sh
autogroup01 autogroup01
sched_football sched_football
+
+psi_invalid_trigger01 psi_invalid_trigger01
diff --git a/testcases/kernel/sched/psi/.gitignore b/testcases/kernel/sched/psi/.gitignore
new file mode 100644
index 000000000..1d615553a
--- /dev/null
+++ b/testcases/kernel/sched/psi/.gitignore
@@ -0,0 +1 @@
+/psi_invalid_trigger01
diff --git a/testcases/kernel/sched/psi/Makefile b/testcases/kernel/sched/psi/Makefile
new file mode 100644
index 000000000..18896b6f2
--- /dev/null
+++ b/testcases/kernel/sched/psi/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+top_srcdir ?= ../../../..
+
+include $(top_srcdir)/include/mk/testcases.mk
+
+include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/sched/psi/psi_invalid_trigger01.c b/testcases/kernel/sched/psi/psi_invalid_trigger01.c
new file mode 100644
index 000000000..c532d1ae4
--- /dev/null
+++ b/testcases/kernel/sched/psi/psi_invalid_trigger01.c
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 IBM Corp.
+ * Author: Samir Mulani <samir@linux.ibm.com>
+ */
+
+/*\
+ * Verify that the PSI trigger parser rejects invalid trigger definitions
+ * written to /proc/pressure/memory with EINVAL and accepts valid ones.
+ *
+ * Each sub-case opens a fresh file descriptor, because only one trigger can
+ * be registered per open file description (a second write fails with EBUSY).
+ *
+ * Rejected with EINVAL:
+ *
+ * - Invalid state keyword: "invalid 100000 1000000"
+ * - Only state keyword: "some"
+ * - Missing window value: "some 100000"
+ * - Non-numeric threshold: "some abc 1000000"
+ * - Non-numeric window: "some 100000 abc"
+ * - Negative threshold: "some -1 1000000"
+ * - Zero threshold: "some 0 1000000"
+ * - Zero window: "some 100000 0"
+ * - Threshold greater than window: "some 1000001 1000000"
+ * - Window greater than the 10s maximum: "some 100000 10000001"
+ * - Window far above the maximum: "some 100000 4294967295"
+ *
+ * Accepted, the write returns the number of bytes written:
+ *
+ * - Smallest threshold: "some 1 1000000"
+ * - Documented minimum window of 500ms: "some 100000 500000"
+ * - Window of 2s: "some 100000 2000000"
+ * - Threshold equal to window: "some 1000000 1000000"
+ * - Window equal to the 10s maximum: "some 100000 10000000"
+ * - The "full" state: "full 100000 1000000"
+ *
+ * The documentation says that windows below 500ms are not accepted, but the
+ * kernel does not enforce a lower limit, so the test does not check for it.
+ */
+
+#include <string.h>
+
+#include "tst_test.h"
+
+#define PSI_MEM "/proc/pressure/memory"
+
+static struct tcase {
+ const char *desc;
+ const char *input;
+ int exp_errno; /* 0 = expect success */
+} tcases[] = {
+ {"invalid state keyword", "invalid 100000 1000000", EINVAL},
+ {"only state keyword", "some", EINVAL},
+ {"missing window value", "some 100000", EINVAL},
+ {"non-numeric threshold", "some abc 1000000", EINVAL},
+ {"non-numeric window", "some 100000 abc", EINVAL},
+ {"negative threshold", "some -1 1000000", EINVAL},
+ {"zero threshold", "some 0 1000000", EINVAL},
+ {"zero window", "some 100000 0", EINVAL},
+ {"threshold greater than window", "some 1000001 1000000", EINVAL},
+ {"window greater than 10s maximum", "some 100000 10000001", EINVAL},
+ {"window far above 10s maximum", "some 100000 4294967295", EINVAL},
+ {"smallest threshold", "some 1 1000000", 0},
+ {"500ms window", "some 100000 500000", 0},
+ {"2s window", "some 100000 2000000", 0},
+ {"threshold equal to window", "some 1000000 1000000", 0},
+ {"window equal to 10s maximum", "some 100000 10000000", 0},
+ {"full state", "full 100000 1000000", 0},
+};
+
+static void run(unsigned int n)
+{
+ struct tcase *tc = &tcases[n];
+ /*
+ * The kernel overwrites the last byte of the written buffer with
+ * a NUL, so the terminating '\0' has to be part of the write.
+ */
+ size_t len = strlen(tc->input) + 1;
+ int fd;
+
+ fd = SAFE_OPEN(PSI_MEM, O_RDWR);
+
+ if (tc->exp_errno) {
+ TST_EXP_FAIL2(write(fd, tc->input, len), tc->exp_errno,
+ "%s", tc->desc);
+ } else {
+ TEST(write(fd, tc->input, len));
+
+ if (TST_RET == (long)len)
+ tst_res(TPASS, "%s: trigger accepted", tc->desc);
+ else if (TST_RET == -1)
+ tst_res(TFAIL | TTERRNO, "%s: write failed", tc->desc);
+ else
+ tst_res(TFAIL, "%s: wrote %ld bytes, expected %zu",
+ tc->desc, TST_RET, len);
+ }
+
+ SAFE_CLOSE(fd);
+}
+
+static void setup(void)
+{
+ char buf[64];
+ int fd;
+
+ if (access(PSI_MEM, F_OK))
+ tst_brk(TCONF, "%s not available (CONFIG_PSI not set)", PSI_MEM);
+
+ fd = SAFE_OPEN(PSI_MEM, O_RDONLY);
+
+ /* psi=0 on the kernel command line makes the interface return EOPNOTSUPP */
+ if (read(fd, buf, sizeof(buf)) < 0) {
+ if (errno == EOPNOTSUPP)
+ tst_brk(TCONF, "PSI is disabled (psi=0 on kernel command line)");
+
+ tst_brk(TBROK | TERRNO, "read(%s) failed", PSI_MEM);
+ }
+
+ SAFE_CLOSE(fd);
+}
+
+static struct tst_test test = {
+ .tcnt = ARRAY_SIZE(tcases),
+ .test = run,
+ .setup = setup,
+ .needs_root = 1,
+ .caps = (struct tst_cap []) {
+ TST_CAP(TST_CAP_REQ, CAP_SYS_RESOURCE),
+ {}
+ },
+ .needs_kconfigs = (const char *const[]) {
+ "CONFIG_PSI=y",
+ NULL
+ },
+};
--
2.53.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
next prev parent reply other threads:[~2026-10-23 13:45 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-24 2:30 [LTP] [PATCH v1 0/4] sched/psi: Add tests for PSI interface Samir Mulani
2026-10-24 2:30 ` Samir Mulani [this message]
2026-10-23 17:55 ` [LTP] sched/psi: Add psi_invalid_trigger01 test linuxtestproject.agent
2026-10-24 2:30 ` [LTP] [PATCH v1 2/4] sched/psi: Add psi_multiple_trigger01 test Samir Mulani
2026-10-24 2:30 ` [LTP] [PATCH v1 3/4] sched/psi: Add psi_proc_format01 test Samir Mulani
2026-10-24 2:30 ` [LTP] [PATCH v1 4/4] sched/psi: Add psi_accounting01 test Samir Mulani
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261024023044.80055-2-samir@linux.ibm.com \
--to=samir@linux.ibm.com \
--cc=ltp@lists.linux.it \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox