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
e1003e496e/src/setup.c (L454)
This commit is contained in:
Igor Anić 2025-02-28 21:36:02 +01:00
parent 85e2074878
commit d98c0893b0
2 changed files with 29 additions and 15 deletions

View File

@ -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 {

View File

@ -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;