From d98c0893b0a565507af955d4f47e63393ac8e464 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20Anic=CC=81?= Date: Fri, 28 Feb 2025 21:36:02 +0100 Subject: [PATCH] io_uring: probe capabilities function ring.get_probe returns io_uring_probe which can be use to probe capabilities of the current running kernel. Ref: https://unixism.net/loti/ref-liburing/supported_caps.html https://github.com/axboe/liburing/blob/e1003e496e66f9b0ae06674869795edf772d5500/src/setup.c#L454 --- lib/std/os/linux.zig | 26 ++++++++++++++------------ lib/std/os/linux/IoUring.zig | 18 +++++++++++++++--- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index 53424dc547..aff6119cf1 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -6138,26 +6138,28 @@ pub const IO_URING_OP_SUPPORTED = 1 << 0; pub const io_uring_probe_op = extern struct { op: IORING_OP, - resv: u8, - - /// IO_URING_OP_* flags - flags: u16, - + flags: u16, // IO_URING_OP_* flags resv2: u32, + + pub fn is_supported(self: @This()) bool { + return self.flags & IO_URING_OP_SUPPORTED != 0; + } }; pub const io_uring_probe = extern struct { - /// last opcode supported - last_op: IORING_OP, - - /// Number of io_uring_probe_op following - ops_len: u8, - + last_op: IORING_OP, // last opcode supported + ops_len: u8, // length of ops[] array below resv: u16, resv2: [3]u32, + ops: [256]io_uring_probe_op, - // Followed by up to `ops_len` io_uring_probe_op structures + pub fn is_supported(self: @This(), op: IORING_OP) bool { + const i = @intFromEnum(op); + if (i > @intFromEnum(self.last_op) or i >= self.ops_len) + return false; + return self.ops[i].is_supported(); + } }; pub const io_uring_restriction = extern struct { diff --git a/lib/std/os/linux/IoUring.zig b/lib/std/os/linux/IoUring.zig index d100916e81..4e000d6c82 100644 --- a/lib/std/os/linux/IoUring.zig +++ b/lib/std/os/linux/IoUring.zig @@ -1272,6 +1272,16 @@ pub fn unregister_buffers(self: *IoUring) !void { } } +/// Returns a io_uring_probe which is used to probe the capabilities of the +/// io_uring subsystem of the running kernel. The io_uring_probe contains the +/// list of supported operations. +pub fn get_probe(self: *IoUring) !linux.io_uring_probe { + var probe = mem.zeroInit(linux.io_uring_probe, .{}); + const res = linux.io_uring_register(self.fd, .REGISTER_PROBE, &probe, probe.ops.len); + try handle_register_buf_ring_result(res); + return probe; +} + fn handle_registration_result(res: usize) !void { switch (linux.E.init(res)) { .SUCCESS => {}, @@ -4355,9 +4365,7 @@ test "copy_cqes with wrapping sq.cqes buffer" { } } -test "bind" { - try skipKernelLessThan(.{ .major = 6, .minor = 11, .patch = 0 }); - +test "bind/listen/connect" { var ring = IoUring.init(4, 0) catch |err| switch (err) { error.SystemOutdated => return error.SkipZigTest, error.PermissionDenied => return error.SkipZigTest, @@ -4365,6 +4373,10 @@ test "bind" { }; defer ring.deinit(); + const probe = ring.get_probe() catch return error.SkipZigTest; + // LISTEN is higher required operation + if (!probe.is_supported(.LISTEN)) return error.SkipZigTest; + var addr = net.Address.initIp4([4]u8{ 127, 0, 0, 1 }, 0); const proto: u32 = if (addr.any.family == linux.AF.UNIX) 0 else linux.IPPROTO.TCP;