From: Thomas Hellström <[email protected]> Add write_eviction_nonblock to exercise the O_NONBLOCK path of the dmem cgroup max interface. After filling VRAM to the cgroup limit, each limit-lowering step writes dmem.max with O_NONBLOCK so that synchronous eviction is skipped. The test then verifies that usage has not yet dropped below the new limit, allocates a small BO to trigger eviction explicitly, and finally confirms that usage falls within bounds.
Assisted-by: GitHub Copilot:claude-sonnet-4.6 Signed-off-by: Thomas Hellström <[email protected]> Signed-off-by: Thadeu Lima de Souza Cascardo <[email protected]> --- tests/cgroup_dmem.c | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/tests/cgroup_dmem.c b/tests/cgroup_dmem.c index 0d3b415acd54..ee6345c17878 100644 --- a/tests/cgroup_dmem.c +++ b/tests/cgroup_dmem.c @@ -41,6 +41,7 @@ #define USAGE_DROP_TIMEOUT_MS 1000 #define TEST_INTERRUPTIBLE (1 << 0) +#define TEST_NONBLOCK (1 << 1) /** * SUBTEST: simple @@ -90,6 +91,18 @@ * REQUIREMENTS: must run as root; xe device with at least one VRAM region */ +/** + * SUBTEST: write_eviction_nonblock + * DESCRIPTION: + * Same fill phase as write_eviction. In the limit-lowering phase dmem.max + * is written with O_NONBLOCK, which causes the kernel to skip synchronous + * eviction. After each nonblock write the test verifies that usage has not + * yet dropped below the new limit, then triggers eviction explicitly by + * allocating a small BO. Finally verifies that usage falls within bounds + * after the forced eviction. + * REQUIREMENTS: must run as root; xe device with at least one VRAM region + */ + static atomic_int signal_count; static struct sigaction sigcont_oldact; @@ -277,7 +290,7 @@ static void test_write_eviction(int fd, char *cg_region, unsigned int flags, con struct igt_cgroup *cg; void **handles; int max_bo; - uint64_t current, capacity, cg_max, limit, after; + uint64_t current, capacity, cg_max, limit, after, before; int err; igt_cgroup_dmem_get_capacity(cg_region, &capacity); @@ -322,14 +335,31 @@ static void test_write_eviction(int fd, char *cg_region, unsigned int flags, con while (limit >= EVICT_STEP) { limit -= EVICT_STEP; - igt_cgroup_dmem_set_max(cg, cg_region, limit, false); + + if (flags & TEST_NONBLOCK) + igt_cgroup_dmem_get_current(cg, cg_region, &before); + + igt_cgroup_dmem_set_max(cg, cg_region, limit, + !!(flags & TEST_NONBLOCK)); igt_cgroup_dmem_get_current(cg, cg_region, &after); igt_debug("Lowered max to %"PRIu64" MiB: usage = %"PRIu64" MiB\n", limit / SZ_1M, after / SZ_1M); + if (flags & TEST_NONBLOCK) { + /* + * O_NONBLOCK skips eviction: verify usage has not + * dropped below the new limit yet. + */ + igt_assert_f(after == before, + "Expected no eviction with O_NONBLOCK, but " + "usage dropped from %"PRIu64" MiB to %"PRIu64" MiB " + "(limit %"PRIu64" MiB)\n", + before / SZ_1M, after / SZ_1M, limit / SZ_1M); + } + if (limit > EVICT_STEP) { - if ((flags & TEST_INTERRUPTIBLE) && after > limit) { + if ((flags & (TEST_INTERRUPTIBLE | TEST_NONBLOCK)) && after > limit) { /* Let a new bo creation trigger eviction. */ void *handle; err = drv->allocate_vram(ctx, BO_SIZE / 8, &handle); @@ -368,6 +398,7 @@ static const struct { { "current", test_current, 0 }, { "write_eviction", test_write_eviction, 0 }, { "write_eviction_interruptible", test_write_eviction, TEST_INTERRUPTIBLE }, + { "write_eviction_nonblock", test_write_eviction, TEST_NONBLOCK }, { } }; -- 2.47.3
