From 6fd38ce13f4cff552272fcc33c8a23d735ac0a49 Mon Sep 17 00:00:00 2001 From: Bernard Assan Date: Thu, 16 Apr 2026 11:54:46 +0000 Subject: [PATCH] Use iouring probing over kernel version checks this will enable test passing on all linux kernels (particularly WSL) without version checks and making `skipKernelLessThan` redundant closes https://github.com/ziglang/zig/pull/24042 Signed-off-by: Bernard Assan --- lib/std/os/linux/IoUring/test.zig | 83 ++++++++++--------------------- 1 file changed, 26 insertions(+), 57 deletions(-) diff --git a/lib/std/os/linux/IoUring/test.zig b/lib/std/os/linux/IoUring/test.zig index 070bd4245f12cdcc48723e5db51ac72d5d74f2bf..7cfe8e3ce77af942e321888dbcf3cf3d4f20002a 100644 --- a/lib/std/os/linux/IoUring/test.zig +++ b/lib/std/os/linux/IoUring/test.zig @@ -475,9 +475,6 @@ test "close" { } test "accept/connect/send/recv" { - const io = testing.io; - _ = io; - var ring = IoUring.init(16, 0) catch |err| switch (err) { error.SystemOutdated => return error.SkipZigTest, error.PermissionDenied => return error.SkipZigTest, @@ -620,7 +617,7 @@ test "timeout (after a relative time)" { const ms = 10; const margin = 5; - const ts: linux.kernel_timespec = .{ .sec = 0, .nsec = ms * 1000000 }; + const ts: linux.kernel_timespec = .{ .sec = 0, .nsec = ms * std.time.ns_per_ms }; const started = std.Io.Clock.awake.now(io); const sqe = try ring.timeout(0x55555555, &ts, 0, 0); @@ -730,9 +727,6 @@ test "timeout_remove" { } test "accept/connect/recv/link_timeout" { - const io = testing.io; - _ = io; - var ring = IoUring.init(16, 0) catch |err| switch (err) { error.SystemOutdated => return error.SkipZigTest, error.PermissionDenied => return error.SkipZigTest, @@ -748,7 +742,7 @@ test "accept/connect/recv/link_timeout" { const sqe_recv = try ring.recv(0xffffffff, socket_test_harness.server, .{ .buffer = buffer_recv[0..] }, 0); sqe_recv.flags |= linux.IOSQE_IO_LINK; - const ts = linux.kernel_timespec{ .sec = 0, .nsec = 1000000 }; + const ts: linux.kernel_timespec = .{ .sec = 0, .nsec = std.time.ns_per_ms }; _ = try ring.link_timeout(0x22222222, &ts, 0); const nr_wait = try ring.submit(); @@ -883,9 +877,6 @@ test "statx" { } test "accept/connect/recv/cancel" { - const io = testing.io; - _ = io; - var ring = IoUring.init(16, 0) catch |err| switch (err) { error.SystemOutdated => return error.SkipZigTest, error.PermissionDenied => return error.SkipZigTest, @@ -1568,9 +1559,6 @@ test "remove_buffers" { } test "provide_buffers: accept/connect/send/recv" { - const io = testing.io; - _ = io; - var ring = IoUring.init(16, 0) catch |err| switch (err) { error.SystemOutdated => return error.SkipZigTest, error.PermissionDenied => return error.SkipZigTest, @@ -1777,11 +1765,6 @@ test "accept multishot" { } test "accept/connect/send_zc/recv" { - try skipKernelLessThan(.{ .major = 6, .minor = 0, .patch = 0 }); - - const io = testing.io; - _ = io; - var ring = IoUring.init(16, 0) catch |err| switch (err) { error.SystemOutdated => return error.SkipZigTest, error.PermissionDenied => return error.SkipZigTest, @@ -1789,6 +1772,13 @@ test "accept/connect/send_zc/recv" { }; defer ring.deinit(); + const probe = ring.get_probe() catch return error.SkipZigTest; + const ops_not_supported = !probe.is_supported(.ACCEPT) or + !probe.is_supported(.CONNECT) or + !probe.is_supported(.SEND_ZC) or + !probe.is_supported(.RECV); + if (ops_not_supported) return error.SkipZigTest; + const socket_test_harness = try createSocketTestHarness(&ring); defer socket_test_harness.close(); @@ -1836,14 +1826,16 @@ test "accept/connect/send_zc/recv" { } test "accept_direct" { - try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 }); - var ring = IoUring.init(1, 0) catch |err| switch (err) { error.SystemOutdated => return error.SkipZigTest, error.PermissionDenied => return error.SkipZigTest, else => return err, }; defer ring.deinit(); + + const probe = ring.get_probe() catch return error.SkipZigTest; + if (!probe.is_supported(.ACCEPT)) return error.SkipZigTest; + var address: linux.sockaddr.in = .{ .port = 0, .addr = @as(*align(1) const u32, @ptrCast( @@ -1921,8 +1913,6 @@ test "accept_direct" { } test "accept_multishot_direct" { - try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 }); - var ring = IoUring.init(1, 0) catch |err| switch (err) { error.SystemOutdated => return error.SkipZigTest, error.PermissionDenied => return error.SkipZigTest, @@ -1930,6 +1920,9 @@ test "accept_multishot_direct" { }; defer ring.deinit(); + const probe = ring.get_probe() catch return error.SkipZigTest; + if (!probe.is_supported(.ACCEPT)) return error.SkipZigTest; + var address: linux.sockaddr.in = .{ .port = 0, .addr = @as(*align(1) const u32, @ptrCast( @@ -1984,8 +1977,6 @@ test "accept_multishot_direct" { } test "socket" { - try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 }); - var ring = IoUring.init(1, 0) catch |err| switch (err) { error.SystemOutdated => return error.SkipZigTest, error.PermissionDenied => return error.SkipZigTest, @@ -1993,6 +1984,9 @@ test "socket" { }; defer ring.deinit(); + const probe = ring.get_probe() catch return error.SkipZigTest; + if (!probe.is_supported(.SOCKET)) return error.SkipZigTest; + // prepare, submit socket operation _ = try ring.socket(0, linux.AF.INET, posix.SOCK.STREAM, 0, 0); try testing.expectEqual(@as(u32, 1), try ring.submit()); @@ -2007,8 +2001,6 @@ test "socket" { } test "socket_direct/socket_direct_alloc/close_direct" { - try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 }); - var ring = IoUring.init(2, 0) catch |err| switch (err) { error.SystemOutdated => return error.SkipZigTest, error.PermissionDenied => return error.SkipZigTest, @@ -2016,6 +2008,9 @@ test "socket_direct/socket_direct_alloc/close_direct" { }; defer ring.deinit(); + const probe = ring.get_probe() catch return error.SkipZigTest; + if (!probe.is_supported(.SOCKET) or !probe.is_supported(.CLOSE)) return error.SkipZigTest; + var registered_fds: [3]linux.fd_t = @splat(-1); try ring.register_files(registered_fds[0..]); @@ -2090,8 +2085,6 @@ test "socket_direct/socket_direct_alloc/close_direct" { } test "openat_direct/close_direct" { - try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 }); - var ring = IoUring.init(2, 0) catch |err| switch (err) { error.SystemOutdated => return error.SkipZigTest, error.PermissionDenied => return error.SkipZigTest, @@ -2099,6 +2092,9 @@ test "openat_direct/close_direct" { }; defer ring.deinit(); + const probe = ring.get_probe() catch return error.SkipZigTest; + if (!probe.is_supported(.OPENAT) or !probe.is_supported(.CLOSE)) return error.SkipZigTest; + var registered_fds: [3]linux.fd_t = @splat(-1); try ring.register_files(registered_fds[0..]); @@ -2141,9 +2137,6 @@ test "openat_direct/close_direct" { } test "ring mapped buffers recv" { - const io = testing.io; - _ = io; - var ring = IoUring.init(16, 0) catch |err| switch (err) { error.SystemOutdated => return error.SkipZigTest, error.PermissionDenied => return error.SkipZigTest, @@ -2231,9 +2224,6 @@ test "ring mapped buffers recv" { } test "ring mapped buffers multishot recv" { - const io = testing.io; - _ = io; - var ring = IoUring.init(16, 0) catch |err| switch (err) { error.SystemOutdated => return error.SkipZigTest, error.PermissionDenied => return error.SkipZigTest, @@ -2665,7 +2655,7 @@ pub fn createSocketTestHarness(ring: *IoUring) !SocketTestHarness { // All good - return SocketTestHarness{ + return .{ .listener = listener_socket, .server = cqe_accept.res, .client = client, @@ -2688,27 +2678,6 @@ fn createListenerSocket(address: *linux.sockaddr.in) !posix.socket_t { return listener_socket; } -/// For use in tests. Returns SkipZigTest if kernel version is less than required. -inline fn skipKernelLessThan(required: std.SemanticVersion) !void { - var uts: linux.utsname = undefined; - const res = linux.uname(&uts); - switch (linux.errno(res)) { - .SUCCESS => {}, - else => |errno| return posix.unexpectedErrno(errno), - } - - const release = mem.sliceTo(&uts.release, 0); - // Strips potential extra, as kernel version might not be semver compliant, example "6.8.9-300.fc40.x86_64" - const extra_index = std.mem.findAny(u8, release, "-+"); - const stripped = release[0..(extra_index orelse release.len)]; - // Make sure the input don't rely on the extra we just stripped - try testing.expect(required.pre == null and required.build == null); - - var current = try std.SemanticVersion.parse(stripped); - current.pre = null; // don't check pre field - if (required.order(current) == .gt) return error.SkipZigTest; -} - fn addrAny(addr: *linux.sockaddr.in) *linux.sockaddr { return @ptrCast(addr); } -- 2.54.0