On 15/09/2026 15:42, Thadeu Lima de Souza Cascardo wrote:
On Fri, Sep 04, 2026 at 03:51:33PM +0100, Tvrtko Ursulin wrote:

On 03/09/2026 23:00, Thadeu Lima de Souza Cascardo wrote:
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.
+                        */

Is this userspace ABI contract or happens to be? It feels odd - even if we
ask for non block for the write why would kernel not be allowed to do stuff
behind the covers?


You bring up an interesting perspective. So maybe the test below might
fail. But we are assuming the test is running with no other users, so this
would be unexpected. Unless we setup dmem.min, there is no guarantee that
eviction won't happen. However, I think the test is still useful as it is.
We are checking that nonblocking behavior will not trigger eviction right
away. We risk not catching up such regression if we leave it out. If we end
up noticing on CI that this happens, we can investigate and revisit.

I looked at the commit which added it:

commit 747c4bb450adcd8b99d3543448419e1952755832
Author: Thomas Hellström <[email protected]>
Date:   Sat Jul 25 12:00:33 2026 +0200

    cgroup/dmem: Add reclaim callback for lowering max below current usage

...

    Also honor O_NONBLOCK so that if that flag is set during the
    max value write, no reclaim is initiated. The idea is to avoid
    charging the reclaim cost to the writer of the max value.

So it was by design. I assume the charging avoidance is for the case when eviction needs to allocate in a different placement. Perhaps a bit of a kludge but perhaps I also miss some historical conversations about it.

Either way, the test itself is a-okay.

Regards,

Tvrtko

+                       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 },
        { }
   };



Reply via email to