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" {
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
22092221test "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)]);