From: <vitaly.prosyak@amd.com>
To: <igt-dev@lists.freedesktop.org>
Cc: <kamil.konieczny@linux.intel.com>, <simona@ffwll.ch>,
<jesse.zhang@amd.com>, <christian.koenig@amd.com>,
<alexander.deucher@amd.com>,
Vitaly Prosyak <vitaly.prosyak@amd.com>
Subject: [PATCH v5 2/2] tests/intel/gem_change_handle_race: Add edge-case and functional subtests
Date: Wed, 5 Aug 2026 22:12:11 -0400 [thread overview]
Message-ID: <20260806021232.200317-3-vitaly.prosyak@amd.com> (raw)
In-Reply-To: <20260806021232.200317-1-vitaly.prosyak@amd.com>
From: Vitaly Prosyak <vitaly.prosyak@amd.com>
Extends gem_change_handle_race test suite with 5 additional subtests
covering edge cases and functional verification of the
DRM_IOCTL_GEM_CHANGE_HANDLE ioctl.
New subtests:
- noop-same-handle: Verifies handle == new_handle is a noop
- invalid-new-handle-exceeds-int-max: new_handle > INT_MAX returns -EINVAL
- invalid-handle-nonexistent: Non-existent handle returns -ENOENT
- edge-new-handle-zero: Documents kernel behavior for new_handle == 0
- functional-rename-verification: Verifies actual rename operation works
These tests complement the race condition testing from the first patch
by validating error handling and functional correctness.
Cc: Kamil Konieczny <kamil.konieczny@linux.intel.com>
Cc: Jesse Zhang <jesse.zhang@amd.com>
Cc: Christian König <christian.koenig@amd.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: Simona Vetter <simona@ffwll.ch>
Signed-off-by: Vitaly Prosyak <vitaly.prosyak@amd.com>
---
v5 changes (addressing Kamil Konieczny's review feedback):
- Moved version changelog to after --- (not in git log)
v4 changes:
- This patch is now completely clean: only adds 5 new test functions
- No modifications to patch 1 code (all fixes moved to patch 1)
v3 changes:
- Sanitized test names and comments per Kamil's feedback
- Added comprehensive edge-case coverage
v2 changes:
- Added these 5 subtests to complement v1's race tests
v1:
- Not present (only 7 race tests in v1)
tests/intel/gem_change_handle_race.c | 173 +++++++++++++++++++++++++++
1 file changed, 173 insertions(+)
diff --git a/tests/intel/gem_change_handle_race.c b/tests/intel/gem_change_handle_race.c
index f4b00c65e..3d85009ee 100644
--- a/tests/intel/gem_change_handle_race.c
+++ b/tests/intel/gem_change_handle_race.c
@@ -1729,6 +1729,159 @@ static void test_race_close_before_lock(struct gpu_ctx *ctx)
race_wins, iterations);
}
+/**
+ * test_noop_same_handle - handle == new_handle should be a noop
+ *
+ * When old handle equals new handle, the ioctl should return success
+ * without modifying anything.
+ */
+static void test_noop_same_handle(struct gpu_ctx *ctx)
+{
+ uint32_t handle;
+
+ handle = gem_create_bo(ctx, 4096);
+
+ /* Renaming to the same handle should succeed (noop) */
+ igt_assert_eq(gem_change_handle(ctx, handle, handle), 0);
+
+ /* Handle should still be valid */
+ igt_assert_eq(gem_close_bo(ctx, handle), 0);
+
+ igt_info(" PASS: handle == new_handle is a noop\n");
+}
+
+/**
+ * test_new_handle_exceeds_int_max - new_handle > INT_MAX should fail
+ *
+ * The kernel enforces idr_alloc() limitation: new_handle must be <= INT_MAX.
+ */
+static void test_new_handle_exceeds_int_max(struct gpu_ctx *ctx)
+{
+ uint32_t handle;
+ int ret;
+
+ handle = gem_create_bo(ctx, 4096);
+
+ /* new_handle > INT_MAX must fail with -EINVAL */
+ ret = gem_change_handle(ctx, handle, (uint32_t)INT_MAX + 1);
+ igt_assert(ret < 0);
+ igt_assert_eq(errno, EINVAL);
+
+ /* Also test 0xFFFFFFFF */
+ ret = gem_change_handle(ctx, handle, 0xFFFFFFFF);
+ igt_assert(ret < 0);
+ igt_assert_eq(errno, EINVAL);
+
+ /* Original handle should still be valid */
+ igt_assert_eq(gem_close_bo(ctx, handle), 0);
+
+ igt_info(" PASS: new_handle > INT_MAX returns -EINVAL\n");
+}
+
+/**
+ * test_invalid_handle - non-existent handle should fail
+ *
+ * Using a handle that doesn't exist should return -ENOENT.
+ */
+static void test_invalid_handle(struct gpu_ctx *ctx)
+{
+ int ret;
+
+ /* Use a handle that was never allocated */
+ ret = gem_change_handle(ctx, 0xDEAD, 0xBEEF);
+ igt_assert(ret < 0);
+ igt_assert_eq(errno, ENOENT);
+
+ /* Handle 0 is also invalid */
+ ret = gem_change_handle(ctx, 0, 100);
+ igt_assert(ret < 0);
+ igt_assert_eq(errno, ENOENT);
+
+ igt_info(" PASS: invalid/non-existent handle returns -ENOENT\n");
+}
+
+/**
+ * test_new_handle_zero - new_handle == 0 (unhandled case)
+ *
+ * Dave got a report that new_handle == 0 is not properly handled.
+ * Document the current kernel behavior.
+ */
+static void test_new_handle_zero(struct gpu_ctx *ctx)
+{
+ uint32_t handle;
+ int ret;
+
+ handle = gem_create_bo(ctx, 4096);
+
+ /*
+ * new_handle == 0: This is an unhandled edge case.
+ * Handle 0 is typically reserved/invalid in DRM.
+ * The kernel should reject this with -EINVAL.
+ */
+ ret = gem_change_handle(ctx, handle, 0);
+ if (ret < 0) {
+ igt_info(" new_handle=0 rejected with errno=%d (%s)\n",
+ errno, strerror(errno));
+ /* Expected: kernel rejects handle 0 */
+ igt_assert(errno == EINVAL || errno == ENOENT || errno == ENOSPC);
+ /* Original handle still valid */
+ igt_assert_eq(gem_close_bo(ctx, handle), 0);
+ } else {
+ /*
+ * If kernel allowed it, the object moved to handle 0.
+ * This is arguably a bug - document it.
+ */
+ igt_warn(" WARNING: kernel allowed new_handle=0 (may be a bug)\n");
+ /* Old handle should be gone */
+ igt_assert(gem_close_bo(ctx, handle) < 0);
+ /* New handle 0 should exist */
+ igt_assert_eq(gem_close_bo(ctx, 0), 0);
+ }
+
+ igt_info(" PASS: new_handle=0 edge case handled\n");
+}
+
+/**
+ * test_functional_rename - verify rename actually works
+ *
+ * After a successful rename:
+ * - GEM_CLOSE(old_handle) must FAIL (handle no longer exists)
+ * - GEM_CLOSE(new_handle) must SUCCEED (object is there)
+ *
+ * Simona suspects the merged version of Francis' patch may have broken
+ * this fundamental behavior.
+ */
+static void test_functional_rename(struct gpu_ctx *ctx)
+{
+ uint32_t handle, new_h;
+ int ret;
+
+ handle = gem_create_bo(ctx, 4096);
+ new_h = handle + 1000; /* Pick a handle far away to avoid collisions */
+
+ /* Perform the rename */
+ ret = gem_change_handle(ctx, handle, new_h);
+ igt_assert_f(ret == 0,
+ "gem_change_handle(%u -> %u) failed: %s\n",
+ handle, new_h, strerror(errno));
+
+ /* Old handle must be invalid now */
+ ret = gem_close_bo(ctx, handle);
+ igt_assert_f(ret < 0 && errno == EINVAL,
+ "GEM_CLOSE(old_handle=%u) should fail with EINVAL, "
+ "got ret=%d errno=%d (%s)\n",
+ handle, ret, errno, strerror(errno));
+
+ /* New handle must be valid */
+ ret = gem_close_bo(ctx, new_h);
+ igt_assert_f(ret == 0,
+ "GEM_CLOSE(new_handle=%u) should succeed, "
+ "got ret=%d errno=%d (%s)\n",
+ new_h, ret, errno, strerror(errno));
+
+ igt_info(" PASS: rename works - old handle invalid, new handle valid\n");
+}
+
int igt_main()
{
struct gpu_ctx ctx = { .fd = -1 };
@@ -1788,6 +1941,26 @@ int igt_main()
igt_subtest("race-close-before-lock")
test_race_close_before_lock(&ctx);
+ igt_describe("Edge case: handle == new_handle should be a noop");
+ igt_subtest("noop-same-handle")
+ test_noop_same_handle(&ctx);
+
+ igt_describe("Edge case: new_handle > INT_MAX must return -EINVAL");
+ igt_subtest("invalid-new-handle-exceeds-int-max")
+ test_new_handle_exceeds_int_max(&ctx);
+
+ igt_describe("Edge case: non-existent handle must return -ENOENT");
+ igt_subtest("invalid-handle-nonexistent")
+ test_invalid_handle(&ctx);
+
+ igt_describe("Edge case: new_handle == 0 (unhandled case reported to Dave)");
+ igt_subtest("edge-new-handle-zero")
+ test_new_handle_zero(&ctx);
+
+ igt_describe("Functional: verify rename moves object from old to new handle");
+ igt_subtest("functional-rename-verification")
+ test_functional_rename(&ctx);
+
igt_fixture() {
#if HAS_AMDGPU
if (ctx.driver == DRIVER_TYPE_AMDGPU && ctx.amdgpu_device)
--
2.54.0
next prev parent reply other threads:[~2026-08-06 2:14 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-06 2:12 [PATCH v5 0/2] IGT tests for DRM_IOCTL_GEM_CHANGE_HANDLE (race conditions + edge cases) vitaly.prosyak
2026-08-06 2:12 ` [PATCH v5 1/2] tests/intel: Add gem_change_handle_race test suite vitaly.prosyak
2026-08-26 10:45 ` Kamil Konieczny
2026-08-27 10:24 ` Sebastian Brzezinka
2026-08-06 2:12 ` vitaly.prosyak [this message]
2026-08-13 16:32 ` [PATCH v5 0/2] IGT tests for DRM_IOCTL_GEM_CHANGE_HANDLE (race conditions + edge cases) vitaly prosyak
2026-08-24 8:15 ` Kamil Konieczny
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=20260806021232.200317-3-vitaly.prosyak@amd.com \
--to=vitaly.prosyak@amd.com \
--cc=alexander.deucher@amd.com \
--cc=christian.koenig@amd.com \
--cc=igt-dev@lists.freedesktop.org \
--cc=jesse.zhang@amd.com \
--cc=kamil.konieczny@linux.intel.com \
--cc=simona@ffwll.ch \
/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