authorgravatar for igor.anic@gmail.comIgor Anić <igor.anic@gmail.com> 2025-02-28 21:36:02+01:00
committergravatar for igor.anic@gmail.comIgor Anić <igor.anic@gmail.com> 2025-03-05 13:35:52+01:00
logd98c0893b0a565507af955d4f47e63393ac8e464
tree8d62241f3d8b7fed7964beb50ebae5eca0179789
parent85e20748785880555f9db3bb3061edbd1bae10e7

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

2 files changed, 29 insertions(+), 15 deletions(-)

lib/std/os/linux.zig+14-12
......@@ -6138,26 +6138,28 @@ pub const IO_URING_OP_SUPPORTED = 1 << 0;
61386138
61396139pub const io_uring_probe_op = extern struct {
61406140 op: IORING_OP,
6141
61426141 resv: u8,
6143
6144 /// IO_URING_OP_* flags
6145 flags: u16,
6146
6142 flags: u16, // IO_URING_OP_* flags
61476143 resv2: u32,
6144
6145 pub fn is_supported(self: @This()) bool {
6146 return self.flags & IO_URING_OP_SUPPORTED != 0;
6147 }
61486148};
61496149
61506150pub const io_uring_probe = extern struct {
6151 /// last opcode supported
6152 last_op: IORING_OP,
6153
6154 /// Number of io_uring_probe_op following
6155 ops_len: u8,
6156
6151 last_op: IORING_OP, // last opcode supported
6152 ops_len: u8, // length of ops[] array below
61576153 resv: u16,
61586154 resv2: [3]u32,
6155 ops: [256]io_uring_probe_op,
61596156
6160 // Followed by up to `ops_len` io_uring_probe_op structures
6157 pub fn is_supported(self: @This(), op: IORING_OP) bool {
6158 const i = @intFromEnum(op);
6159 if (i > @intFromEnum(self.last_op) or i >= self.ops_len)
6160 return false;
6161 return self.ops[i].is_supported();
6162 }
61616163};
61626164
61636165pub const io_uring_restriction = extern struct {
lib/std/os/linux/IoUring.zig+15-3
......@@ -1272,6 +1272,16 @@ pub fn unregister_buffers(self: *IoUring) !void {
12721272 }
12731273}
12741274
1275/// Returns a io_uring_probe which is used to probe the capabilities of the
1276/// io_uring subsystem of the running kernel. The io_uring_probe contains the
1277/// list of supported operations.
1278pub fn get_probe(self: *IoUring) !linux.io_uring_probe {
1279 var probe = mem.zeroInit(linux.io_uring_probe, .{});
1280 const res = linux.io_uring_register(self.fd, .REGISTER_PROBE, &probe, probe.ops.len);
1281 try handle_register_buf_ring_result(res);
1282 return probe;
1283}
1284
12751285fn handle_registration_result(res: usize) !void {
12761286 switch (linux.E.init(res)) {
12771287 .SUCCESS => {},
......@@ -4355,9 +4365,7 @@ test "copy_cqes with wrapping sq.cqes buffer" {
43554365 }
43564366}
43574367
4358test "bind" {
4359 try skipKernelLessThan(.{ .major = 6, .minor = 11, .patch = 0 });
4360
4368test "bind/listen/connect" {
43614369 var ring = IoUring.init(4, 0) catch |err| switch (err) {
43624370 error.SystemOutdated => return error.SkipZigTest,
43634371 error.PermissionDenied => return error.SkipZigTest,
......@@ -4365,6 +4373,10 @@ test "bind" {
43654373 };
43664374 defer ring.deinit();
43674375
4376 const probe = ring.get_probe() catch return error.SkipZigTest;
4377 // LISTEN is higher required operation
4378 if (!probe.is_supported(.LISTEN)) return error.SkipZigTest;
4379
43684380 var addr = net.Address.initIp4([4]u8{ 127, 0, 0, 1 }, 0);
43694381 const proto: u32 = if (addr.any.family == linux.AF.UNIX) 0 else linux.IPPROTO.TCP;
43704382