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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.