Skip to content

Commit 47c58cb

Browse files
authored
Fix io_uring tests (#12134)
* io_uring: fix the timeout_remove test The test does a IORING_OP_TIMEOUT followed with a IORING_OP_TIMEOUT_REMOVE and assumed we would get the CQEs in the same order. Linux v5.18 changed how this works and we now get them in the reverse order. The documentation doesn't explicitly say which CQE we should get first so just make the test work with both cases. * io_uring: fix the remove_buffers test The original test was buggy but accidentally worked with kernels < 5.18 The test assumed that IORING_OP_REMOVE_BUFFERS removed from the start of but in fact the documentation doesn't specify which buffer is removed, only that a certain number of buffers are removed. Starting with the kernel 5.18 the check for the `used_buffer_id` fails. Turns out that previous kernels removed buffers in such a way that the remaining buffer for this read would always be 0, however this isn't true anymore. Instead of checking a specific value just check that the `used_buffer_id` corresponds to a valid ID.
1 parent 9c66fda commit 47c58cb

File tree

1 file changed

+36
-24
lines changed

1 file changed

+36
-24
lines changed

lib/std/os/linux/io_uring.zig

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2181,29 +2181,41 @@ test "timeout_remove" {
21812181

21822182
try testing.expectEqual(@as(u32, 2), try ring.submit());
21832183

2184-
const cqe_timeout = try ring.copy_cqe();
2185-
// IORING_OP_TIMEOUT_REMOVE is not supported by this kernel version:
2186-
// Timeout remove operations set the fd to -1, which results in EBADF before EINVAL.
2187-
// We use IORING_FEAT_RW_CUR_POS as a safety check here to make sure we are at least pre-5.6.
2188-
// We don't want to skip this test for newer kernels.
2189-
if (cqe_timeout.user_data == 0x99999999 and
2190-
cqe_timeout.err() == .BADF and
2191-
(ring.features & linux.IORING_FEAT_RW_CUR_POS) == 0)
2192-
{
2193-
return error.SkipZigTest;
2194-
}
2195-
try testing.expectEqual(linux.io_uring_cqe{
2196-
.user_data = 0x88888888,
2197-
.res = -@as(i32, @enumToInt(linux.E.CANCELED)),
2198-
.flags = 0,
2199-
}, cqe_timeout);
2184+
// The order in which the CQE arrive is not clearly documented and it changed with kernel 5.18:
2185+
// * kernel 5.10 gives user data 0x88888888 first, 0x99999999 second
2186+
// * kernel 5.18 gives user data 0x99999999 first, 0x88888888 second
2187+
2188+
var cqes: [2]os.linux.io_uring_cqe = undefined;
2189+
try testing.expectEqual(@as(u32, 2), try ring.copy_cqes(cqes[0..], 2));
2190+
2191+
for (cqes) |cqe| {
2192+
// IORING_OP_TIMEOUT_REMOVE is not supported by this kernel version:
2193+
// Timeout remove operations set the fd to -1, which results in EBADF before EINVAL.
2194+
// We use IORING_FEAT_RW_CUR_POS as a safety check here to make sure we are at least pre-5.6.
2195+
// We don't want to skip this test for newer kernels.
2196+
if (cqe.user_data == 0x99999999 and
2197+
cqe.err() == .BADF and
2198+
(ring.features & linux.IORING_FEAT_RW_CUR_POS) == 0)
2199+
{
2200+
return error.SkipZigTest;
2201+
}
22002202

2201-
const cqe_timeout_remove = try ring.copy_cqe();
2202-
try testing.expectEqual(linux.io_uring_cqe{
2203-
.user_data = 0x99999999,
2204-
.res = 0,
2205-
.flags = 0,
2206-
}, cqe_timeout_remove);
2203+
try testing.expect(cqe.user_data == 0x88888888 or cqe.user_data == 0x99999999);
2204+
2205+
if (cqe.user_data == 0x88888888) {
2206+
try testing.expectEqual(linux.io_uring_cqe{
2207+
.user_data = 0x88888888,
2208+
.res = -@as(i32, @enumToInt(linux.E.CANCELED)),
2209+
.flags = 0,
2210+
}, cqe);
2211+
} else if (cqe.user_data == 0x99999999) {
2212+
try testing.expectEqual(linux.io_uring_cqe{
2213+
.user_data = 0x99999999,
2214+
.res = 0,
2215+
.flags = 0,
2216+
}, cqe);
2217+
}
2218+
}
22072219
}
22082220

22092221
test "accept/connect/recv/link_timeout" {
@@ -2989,7 +3001,7 @@ test "remove_buffers" {
29893001
try testing.expectEqual(@as(u64, 0xcccccccc), cqe.user_data);
29903002
}
29913003

2992-
// Remove the first 3 buffers
3004+
// Remove 3 buffers
29933005

29943006
{
29953007
var sqe = try ring.remove_buffers(0xbababababa, 3, group_id);
@@ -3021,7 +3033,7 @@ test "remove_buffers" {
30213033

30223034
try testing.expect(cqe.flags & linux.IORING_CQE_F_BUFFER == linux.IORING_CQE_F_BUFFER);
30233035
const used_buffer_id = cqe.flags >> 16;
3024-
try testing.expectEqual(used_buffer_id, 0);
3036+
try testing.expect(used_buffer_id >= 0 and used_buffer_id < 4);
30253037
try testing.expectEqual(@as(i32, buffer_len), cqe.res);
30263038
try testing.expectEqual(@as(u64, 0xdfdfdfdf), cqe.user_data);
30273039
try testing.expectEqualSlices(u8, &([_]u8{0} ** buffer_len), buffers[used_buffer_id][0..@intCast(usize, cqe.res)]);

0 commit comments

Comments
 (0)