authorgravatar for vincent@rischmann.frVincent Rischmann <vincent@rischmann.fr> 2022-07-16 17:05:11+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-07-16 10:05:11-05:00
log47c58cba595a8e1eddf6c87086d52691d180a103
tree84ed8e541eaf92bf1d98d5849e89203fa0cf6974
parent9c66fdadc709ca4c00b08aa8fa4dc6312cb559c3
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

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 files changed, 36 insertions(+), 24 deletions(-)

lib/std/os/linux/io_uring.zig+36-24
...@@ -2181,29 +2181,41 @@ test "timeout_remove" {...@@ -2181,29 +2181,41 @@ test "timeout_remove" {
21812181
2182 try testing.expectEqual(@as(u32, 2), try ring.submit());2182 try testing.expectEqual(@as(u32, 2), try ring.submit());
21832183
2184 const cqe_timeout = try ring.copy_cqe();2184 // The order in which the CQE arrive is not clearly documented and it changed with kernel 5.18:
2185 // IORING_OP_TIMEOUT_REMOVE is not supported by this kernel version:2185 // * kernel 5.10 gives user data 0x88888888 first, 0x99999999 second
2186 // Timeout remove operations set the fd to -1, which results in EBADF before EINVAL.2186 // * kernel 5.18 gives user data 0x99999999 first, 0x88888888 second
2187 // We use IORING_FEAT_RW_CUR_POS as a safety check here to make sure we are at least pre-5.6.2187
2188 // We don't want to skip this test for newer kernels.2188 var cqes: [2]os.linux.io_uring_cqe = undefined;
2189 if (cqe_timeout.user_data == 0x99999999 and2189 try testing.expectEqual(@as(u32, 2), try ring.copy_cqes(cqes[0..], 2));
2190 cqe_timeout.err() == .BADF and2190
2191 (ring.features & linux.IORING_FEAT_RW_CUR_POS) == 0)2191 for (cqes) |cqe| {
2192 {2192 // IORING_OP_TIMEOUT_REMOVE is not supported by this kernel version:
2193 return error.SkipZigTest;2193 // Timeout remove operations set the fd to -1, which results in EBADF before EINVAL.
2194 }2194 // We use IORING_FEAT_RW_CUR_POS as a safety check here to make sure we are at least pre-5.6.
2195 try testing.expectEqual(linux.io_uring_cqe{2195 // We don't want to skip this test for newer kernels.
2196 .user_data = 0x88888888,2196 if (cqe.user_data == 0x99999999 and
2197 .res = -@as(i32, @enumToInt(linux.E.CANCELED)),2197 cqe.err() == .BADF and
2198 .flags = 0,2198 (ring.features & linux.IORING_FEAT_RW_CUR_POS) == 0)
2199 }, cqe_timeout);2199 {
2200 return error.SkipZigTest;
2201 }
22002202
2201 const cqe_timeout_remove = try ring.copy_cqe();2203 try testing.expect(cqe.user_data == 0x88888888 or cqe.user_data == 0x99999999);
2202 try testing.expectEqual(linux.io_uring_cqe{2204
2203 .user_data = 0x99999999,2205 if (cqe.user_data == 0x88888888) {
2204 .res = 0,2206 try testing.expectEqual(linux.io_uring_cqe{
2205 .flags = 0,2207 .user_data = 0x88888888,
2206 }, cqe_timeout_remove);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 }
2207}2219}
22082220
2209test "accept/connect/recv/link_timeout" {2221test "accept/connect/recv/link_timeout" {
...@@ -2989,7 +3001,7 @@ test "remove_buffers" {...@@ -2989,7 +3001,7 @@ test "remove_buffers" {
2989 try testing.expectEqual(@as(u64, 0xcccccccc), cqe.user_data);3001 try testing.expectEqual(@as(u64, 0xcccccccc), cqe.user_data);
2990 }3002 }
29913003
2992 // Remove the first 3 buffers3004 // Remove 3 buffers
29933005
2994 {3006 {
2995 var sqe = try ring.remove_buffers(0xbababababa, 3, group_id);3007 var sqe = try ring.remove_buffers(0xbababababa, 3, group_id);
...@@ -3021,7 +3033,7 @@ test "remove_buffers" {...@@ -3021,7 +3033,7 @@ test "remove_buffers" {
30213033
3022 try testing.expect(cqe.flags & linux.IORING_CQE_F_BUFFER == linux.IORING_CQE_F_BUFFER);3034 try testing.expect(cqe.flags & linux.IORING_CQE_F_BUFFER == linux.IORING_CQE_F_BUFFER);
3023 const used_buffer_id = cqe.flags >> 16;3035 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);
3025 try testing.expectEqual(@as(i32, buffer_len), cqe.res);3037 try testing.expectEqual(@as(i32, buffer_len), cqe.res);
3026 try testing.expectEqual(@as(u64, 0xdfdfdfdf), cqe.user_data);3038 try testing.expectEqual(@as(u64, 0xdfdfdfdf), cqe.user_data);
3027 try testing.expectEqualSlices(u8, &([_]u8{0} ** buffer_len), buffers[used_buffer_id][0..@intCast(usize, cqe.res)]);3039 try testing.expectEqualSlices(u8, &([_]u8{0} ** buffer_len), buffers[used_buffer_id][0..@intCast(usize, cqe.res)]);