1 /* SPDX-License-Identifier: MIT */
2 /*
3 * Description: run various timeout tests
4 *
5 */
6 #include <errno.h>
7 #include <stdio.h>
8 #include <unistd.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <fcntl.h>
12 #include <sys/time.h>
13 #include <sys/wait.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16
17 #include "helpers.h"
18 #include "liburing.h"
19 #include "../src/syscall.h"
20
21 #define TIMEOUT_MSEC 200
22 static int not_supported;
23 static int no_modify;
24 static int no_multishot;
25
msec_to_ts(struct __kernel_timespec * ts,unsigned int msec)26 static void msec_to_ts(struct __kernel_timespec *ts, unsigned int msec)
27 {
28 ts->tv_sec = msec / 1000;
29 ts->tv_nsec = (msec % 1000) * 1000000;
30 }
31
mtime_since(const struct timeval * s,const struct timeval * e)32 static unsigned long long mtime_since(const struct timeval *s,
33 const struct timeval *e)
34 {
35 long long sec, usec;
36
37 sec = e->tv_sec - s->tv_sec;
38 usec = (e->tv_usec - s->tv_usec);
39 if (sec > 0 && usec < 0) {
40 sec--;
41 usec += 1000000;
42 }
43
44 sec *= 1000;
45 usec /= 1000;
46 return sec + usec;
47 }
48
mtime_since_now(struct timeval * tv)49 static unsigned long long mtime_since_now(struct timeval *tv)
50 {
51 struct timeval end;
52
53 gettimeofday(&end, NULL);
54 return mtime_since(tv, &end);
55 }
56
57 /*
58 * Test that we return to userspace if a timeout triggers, even if we
59 * don't satisfy the number of events asked for.
60 */
test_single_timeout_many(struct io_uring * ring)61 static int test_single_timeout_many(struct io_uring *ring)
62 {
63 struct io_uring_cqe *cqe;
64 struct io_uring_sqe *sqe;
65 unsigned long long exp;
66 struct __kernel_timespec ts;
67 struct timeval tv;
68 int ret;
69
70 sqe = io_uring_get_sqe(ring);
71 if (!sqe) {
72 fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
73 goto err;
74 }
75
76 msec_to_ts(&ts, TIMEOUT_MSEC);
77 io_uring_prep_timeout(sqe, &ts, 0, 0);
78
79 ret = io_uring_submit(ring);
80 if (ret <= 0) {
81 fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
82 goto err;
83 }
84
85 gettimeofday(&tv, NULL);
86 ret = __sys_io_uring_enter(ring->ring_fd, 0, 4, IORING_ENTER_GETEVENTS,
87 NULL);
88 if (ret < 0) {
89 fprintf(stderr, "%s: io_uring_enter %d\n", __FUNCTION__, ret);
90 goto err;
91 }
92
93 ret = io_uring_wait_cqe(ring, &cqe);
94 if (ret < 0) {
95 fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
96 goto err;
97 }
98 ret = cqe->res;
99 io_uring_cqe_seen(ring, cqe);
100 if (ret == -EINVAL) {
101 fprintf(stdout, "Timeout not supported, ignored\n");
102 not_supported = 1;
103 return 0;
104 } else if (ret != -ETIME) {
105 fprintf(stderr, "Timeout: %s\n", strerror(-ret));
106 goto err;
107 }
108
109 exp = mtime_since_now(&tv);
110 if (exp >= TIMEOUT_MSEC / 2 && exp <= (TIMEOUT_MSEC * 3) / 2)
111 return 0;
112 fprintf(stderr, "%s: Timeout seems wonky (got %llu)\n", __FUNCTION__, exp);
113 err:
114 return 1;
115 }
116
117 /*
118 * Test numbered trigger of timeout
119 */
test_single_timeout_nr(struct io_uring * ring,int nr)120 static int test_single_timeout_nr(struct io_uring *ring, int nr)
121 {
122 struct io_uring_cqe *cqe;
123 struct io_uring_sqe *sqe;
124 struct __kernel_timespec ts;
125 int i, ret;
126
127 sqe = io_uring_get_sqe(ring);
128 if (!sqe) {
129 fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
130 goto err;
131 }
132
133 msec_to_ts(&ts, TIMEOUT_MSEC);
134 io_uring_prep_timeout(sqe, &ts, nr, 0);
135
136 sqe = io_uring_get_sqe(ring);
137 io_uring_prep_nop(sqe);
138 io_uring_sqe_set_data(sqe, (void *) 1);
139 sqe = io_uring_get_sqe(ring);
140 io_uring_prep_nop(sqe);
141 io_uring_sqe_set_data(sqe, (void *) 1);
142
143 ret = io_uring_submit_and_wait(ring, 3);
144 if (ret <= 0) {
145 fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
146 goto err;
147 }
148
149 i = 0;
150 while (i < 3) {
151 ret = io_uring_wait_cqe(ring, &cqe);
152 if (ret < 0) {
153 fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
154 goto err;
155 }
156
157 ret = cqe->res;
158
159 /*
160 * NOP commands have user_data as 1. Check that we get the
161 * at least 'nr' NOPs first, then the successfully removed timeout.
162 */
163 if (io_uring_cqe_get_data(cqe) == NULL) {
164 if (i < nr) {
165 fprintf(stderr, "%s: timeout received too early\n", __FUNCTION__);
166 goto err;
167 }
168 if (ret) {
169 fprintf(stderr, "%s: timeout triggered by passage of"
170 " time, not by events completed\n", __FUNCTION__);
171 goto err;
172 }
173 }
174
175 io_uring_cqe_seen(ring, cqe);
176 if (ret) {
177 fprintf(stderr, "res: %d\n", ret);
178 goto err;
179 }
180 i++;
181 }
182
183 return 0;
184 err:
185 return 1;
186 }
187
test_single_timeout_wait(struct io_uring * ring,struct io_uring_params * p)188 static int test_single_timeout_wait(struct io_uring *ring,
189 struct io_uring_params *p)
190 {
191 struct io_uring_cqe *cqe;
192 struct io_uring_sqe *sqe;
193 struct __kernel_timespec ts;
194 int i, ret;
195
196 sqe = io_uring_get_sqe(ring);
197 io_uring_prep_nop(sqe);
198 io_uring_sqe_set_data(sqe, (void *) 1);
199
200 sqe = io_uring_get_sqe(ring);
201 io_uring_prep_nop(sqe);
202 io_uring_sqe_set_data(sqe, (void *) 1);
203
204 /* no implied submit for newer kernels */
205 if (p->features & IORING_FEAT_EXT_ARG) {
206 ret = io_uring_submit(ring);
207 if (ret != 2) {
208 fprintf(stderr, "%s: submit %d\n", __FUNCTION__, ret);
209 return 1;
210 }
211 }
212
213 msec_to_ts(&ts, 1000);
214
215 i = 0;
216 do {
217 ret = io_uring_wait_cqes(ring, &cqe, 2, &ts, NULL);
218 if (ret == -ETIME)
219 break;
220 if (ret < 0) {
221 fprintf(stderr, "%s: wait timeout failed: %d\n", __FUNCTION__, ret);
222 goto err;
223 }
224
225 ret = cqe->res;
226 io_uring_cqe_seen(ring, cqe);
227 if (ret < 0) {
228 fprintf(stderr, "res: %d\n", ret);
229 goto err;
230 }
231 i++;
232 } while (1);
233
234 if (i != 2) {
235 fprintf(stderr, "got %d completions\n", i);
236 goto err;
237 }
238 return 0;
239 err:
240 return 1;
241 }
242
243 /*
244 * Test single timeout waking us up
245 */
test_single_timeout(struct io_uring * ring)246 static int test_single_timeout(struct io_uring *ring)
247 {
248 struct io_uring_cqe *cqe;
249 struct io_uring_sqe *sqe;
250 unsigned long long exp;
251 struct __kernel_timespec ts;
252 struct timeval tv;
253 int ret;
254
255 sqe = io_uring_get_sqe(ring);
256 if (!sqe) {
257 fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
258 goto err;
259 }
260
261 msec_to_ts(&ts, TIMEOUT_MSEC);
262 io_uring_prep_timeout(sqe, &ts, 0, 0);
263
264 ret = io_uring_submit(ring);
265 if (ret <= 0) {
266 fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
267 goto err;
268 }
269
270 gettimeofday(&tv, NULL);
271 ret = io_uring_wait_cqe(ring, &cqe);
272 if (ret < 0) {
273 fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
274 goto err;
275 }
276 ret = cqe->res;
277 io_uring_cqe_seen(ring, cqe);
278 if (ret == -EINVAL) {
279 fprintf(stdout, "%s: Timeout not supported, ignored\n", __FUNCTION__);
280 not_supported = 1;
281 return 0;
282 } else if (ret != -ETIME) {
283 fprintf(stderr, "%s: Timeout: %s\n", __FUNCTION__, strerror(-ret));
284 goto err;
285 }
286
287 exp = mtime_since_now(&tv);
288 if (exp >= TIMEOUT_MSEC / 2 && exp <= (TIMEOUT_MSEC * 3) / 2)
289 return 0;
290 fprintf(stderr, "%s: Timeout seems wonky (got %llu)\n", __FUNCTION__, exp);
291 err:
292 return 1;
293 }
294
test_single_timeout_remove_notfound(struct io_uring * ring)295 static int test_single_timeout_remove_notfound(struct io_uring *ring)
296 {
297 struct io_uring_cqe *cqe;
298 struct io_uring_sqe *sqe;
299 struct __kernel_timespec ts;
300 int ret, i;
301
302 if (no_modify)
303 return 0;
304
305 sqe = io_uring_get_sqe(ring);
306 if (!sqe) {
307 fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
308 goto err;
309 }
310
311 msec_to_ts(&ts, TIMEOUT_MSEC);
312 io_uring_prep_timeout(sqe, &ts, 2, 0);
313 sqe->user_data = 1;
314
315 ret = io_uring_submit(ring);
316 if (ret <= 0) {
317 fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
318 goto err;
319 }
320
321 sqe = io_uring_get_sqe(ring);
322 if (!sqe) {
323 fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
324 goto err;
325 }
326
327 io_uring_prep_timeout_remove(sqe, 2, 0);
328 sqe->user_data = 2;
329
330 ret = io_uring_submit(ring);
331 if (ret <= 0) {
332 fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
333 goto err;
334 }
335
336 /*
337 * We should get two completions. One is our modify request, which should
338 * complete with -ENOENT. The other is the timeout that will trigger after
339 * TIMEOUT_MSEC.
340 */
341 for (i = 0; i < 2; i++) {
342 ret = io_uring_wait_cqe(ring, &cqe);
343 if (ret < 0) {
344 fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
345 goto err;
346 }
347 if (cqe->user_data == 2) {
348 if (cqe->res != -ENOENT) {
349 fprintf(stderr, "%s: modify ret %d, wanted ENOENT\n", __FUNCTION__, cqe->res);
350 break;
351 }
352 } else if (cqe->user_data == 1) {
353 if (cqe->res != -ETIME) {
354 fprintf(stderr, "%s: timeout ret %d, wanted -ETIME\n", __FUNCTION__, cqe->res);
355 break;
356 }
357 }
358 io_uring_cqe_seen(ring, cqe);
359 }
360 return 0;
361 err:
362 return 1;
363 }
364
test_single_timeout_remove(struct io_uring * ring)365 static int test_single_timeout_remove(struct io_uring *ring)
366 {
367 struct io_uring_cqe *cqe;
368 struct io_uring_sqe *sqe;
369 struct __kernel_timespec ts;
370 int ret, i;
371
372 sqe = io_uring_get_sqe(ring);
373 if (!sqe) {
374 fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
375 goto err;
376 }
377
378 msec_to_ts(&ts, TIMEOUT_MSEC);
379 io_uring_prep_timeout(sqe, &ts, 0, 0);
380 sqe->user_data = 1;
381
382 ret = io_uring_submit(ring);
383 if (ret <= 0) {
384 fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
385 goto err;
386 }
387
388 sqe = io_uring_get_sqe(ring);
389 if (!sqe) {
390 fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
391 goto err;
392 }
393
394 io_uring_prep_timeout_remove(sqe, 1, 0);
395 sqe->user_data = 2;
396
397 ret = io_uring_submit(ring);
398 if (ret <= 0) {
399 fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
400 goto err;
401 }
402
403 /*
404 * We should have two completions ready. One is for the original timeout
405 * request, user_data == 1, that should have a ret of -ECANCELED. The other
406 * is for our modify request, user_data == 2, that should have a ret of 0.
407 */
408 for (i = 0; i < 2; i++) {
409 ret = io_uring_wait_cqe(ring, &cqe);
410 if (ret < 0) {
411 fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
412 goto err;
413 }
414 if (no_modify)
415 goto seen;
416 if (cqe->res == -EINVAL && cqe->user_data == 2) {
417 fprintf(stdout, "Timeout modify not supported, ignoring\n");
418 no_modify = 1;
419 goto seen;
420 }
421 if (cqe->user_data == 1) {
422 if (cqe->res != -ECANCELED) {
423 fprintf(stderr, "%s: timeout ret %d, wanted canceled\n", __FUNCTION__, cqe->res);
424 break;
425 }
426 } else if (cqe->user_data == 2) {
427 if (cqe->res) {
428 fprintf(stderr, "%s: modify ret %d, wanted 0\n", __FUNCTION__, cqe->res);
429 break;
430 }
431 }
432 seen:
433 io_uring_cqe_seen(ring, cqe);
434 }
435 return 0;
436 err:
437 return 1;
438 }
439
440 /*
441 * Test single absolute timeout waking us up
442 */
test_single_timeout_abs(struct io_uring * ring)443 static int test_single_timeout_abs(struct io_uring *ring)
444 {
445 struct io_uring_cqe *cqe;
446 struct io_uring_sqe *sqe;
447 unsigned long long exp;
448 struct __kernel_timespec ts;
449 struct timespec abs_ts;
450 struct timeval tv;
451 int ret;
452
453 sqe = io_uring_get_sqe(ring);
454 if (!sqe) {
455 fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
456 goto err;
457 }
458
459 clock_gettime(CLOCK_MONOTONIC, &abs_ts);
460 ts.tv_sec = abs_ts.tv_sec + 1;
461 ts.tv_nsec = abs_ts.tv_nsec;
462 io_uring_prep_timeout(sqe, &ts, 0, IORING_TIMEOUT_ABS);
463
464 ret = io_uring_submit(ring);
465 if (ret <= 0) {
466 fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
467 goto err;
468 }
469
470 gettimeofday(&tv, NULL);
471 ret = io_uring_wait_cqe(ring, &cqe);
472 if (ret < 0) {
473 fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
474 goto err;
475 }
476 ret = cqe->res;
477 io_uring_cqe_seen(ring, cqe);
478 if (ret == -EINVAL) {
479 fprintf(stdout, "Absolute timeouts not supported, ignored\n");
480 return 0;
481 } else if (ret != -ETIME) {
482 fprintf(stderr, "Timeout: %s\n", strerror(-ret));
483 goto err;
484 }
485
486 exp = mtime_since_now(&tv);
487 if (exp >= 1000 / 2 && exp <= (1000 * 3) / 2)
488 return 0;
489 fprintf(stderr, "%s: Timeout seems wonky (got %llu)\n", __FUNCTION__, exp);
490 err:
491 return 1;
492 }
493
494 /*
495 * Test that timeout is canceled on exit
496 */
test_single_timeout_exit(struct io_uring * ring)497 static int test_single_timeout_exit(struct io_uring *ring)
498 {
499 struct io_uring_sqe *sqe;
500 struct __kernel_timespec ts;
501 int ret;
502
503 sqe = io_uring_get_sqe(ring);
504 if (!sqe) {
505 fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
506 goto err;
507 }
508
509 msec_to_ts(&ts, 30000);
510 io_uring_prep_timeout(sqe, &ts, 0, 0);
511
512 ret = io_uring_submit(ring);
513 if (ret <= 0) {
514 fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
515 goto err;
516 }
517
518 io_uring_queue_exit(ring);
519 return 0;
520 err:
521 io_uring_queue_exit(ring);
522 return 1;
523 }
524
525 /*
526 * Test multi timeouts waking us up
527 */
test_multi_timeout(struct io_uring * ring)528 static int test_multi_timeout(struct io_uring *ring)
529 {
530 struct io_uring_sqe *sqe;
531 struct io_uring_cqe *cqe;
532 struct __kernel_timespec ts[2];
533 unsigned int timeout[2];
534 unsigned long long exp;
535 struct timeval tv;
536 int ret, i;
537
538 /* req_1: timeout req, count = 1, time = (TIMEOUT_MSEC * 2) */
539 timeout[0] = TIMEOUT_MSEC * 2;
540 msec_to_ts(&ts[0], timeout[0]);
541 sqe = io_uring_get_sqe(ring);
542 if (!sqe) {
543 fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
544 goto err;
545 }
546 io_uring_prep_timeout(sqe, &ts[0], 1, 0);
547 sqe->user_data = 1;
548
549 /* req_2: timeout req, count = 1, time = TIMEOUT_MSEC */
550 timeout[1] = TIMEOUT_MSEC;
551 msec_to_ts(&ts[1], timeout[1]);
552 sqe = io_uring_get_sqe(ring);
553 if (!sqe) {
554 fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
555 goto err;
556 }
557 io_uring_prep_timeout(sqe, &ts[1], 1, 0);
558 sqe->user_data = 2;
559
560 ret = io_uring_submit(ring);
561 if (ret <= 0) {
562 fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
563 goto err;
564 }
565
566 gettimeofday(&tv, NULL);
567 for (i = 0; i < 2; i++) {
568 unsigned int time = 0;
569 __u64 user_data = 0;
570
571 ret = io_uring_wait_cqe(ring, &cqe);
572 if (ret < 0) {
573 fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
574 goto err;
575 }
576
577 /*
578 * Both of these two reqs should timeout, but req_2 should
579 * return before req_1.
580 */
581 switch (i) {
582 case 0:
583 user_data = 2;
584 time = timeout[1];
585 break;
586 case 1:
587 user_data = 1;
588 time = timeout[0];
589 break;
590 }
591
592 if (cqe->user_data != user_data) {
593 fprintf(stderr, "%s: unexpected timeout req %d sequence\n",
594 __FUNCTION__, i+1);
595 goto err;
596 }
597 if (cqe->res != -ETIME) {
598 fprintf(stderr, "%s: Req %d timeout: %s\n",
599 __FUNCTION__, i+1, strerror(cqe->res));
600 goto err;
601 }
602 exp = mtime_since_now(&tv);
603 if (exp < time / 2 || exp > (time * 3) / 2) {
604 fprintf(stderr, "%s: Req %d timeout seems wonky (got %llu)\n",
605 __FUNCTION__, i+1, exp);
606 goto err;
607 }
608 io_uring_cqe_seen(ring, cqe);
609 }
610
611 return 0;
612 err:
613 return 1;
614 }
615
616 /*
617 * Test multi timeout req with different count
618 */
test_multi_timeout_nr(struct io_uring * ring)619 static int test_multi_timeout_nr(struct io_uring *ring)
620 {
621 struct io_uring_sqe *sqe;
622 struct io_uring_cqe *cqe;
623 struct __kernel_timespec ts;
624 int ret, i;
625
626 msec_to_ts(&ts, TIMEOUT_MSEC);
627
628 /* req_1: timeout req, count = 2 */
629 sqe = io_uring_get_sqe(ring);
630 if (!sqe) {
631 fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
632 goto err;
633 }
634 io_uring_prep_timeout(sqe, &ts, 2, 0);
635 sqe->user_data = 1;
636
637 /* req_2: timeout req, count = 1 */
638 sqe = io_uring_get_sqe(ring);
639 if (!sqe) {
640 fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
641 goto err;
642 }
643 io_uring_prep_timeout(sqe, &ts, 1, 0);
644 sqe->user_data = 2;
645
646 /* req_3: nop req */
647 sqe = io_uring_get_sqe(ring);
648 if (!sqe) {
649 fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
650 goto err;
651 }
652 io_uring_prep_nop(sqe);
653 io_uring_sqe_set_data(sqe, (void *) 1);
654
655 ret = io_uring_submit(ring);
656 if (ret <= 0) {
657 fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
658 goto err;
659 }
660
661 /*
662 * req_2 (count=1) should return without error and req_1 (count=2)
663 * should timeout.
664 */
665 for (i = 0; i < 3; i++) {
666 ret = io_uring_wait_cqe(ring, &cqe);
667 if (ret < 0) {
668 fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
669 goto err;
670 }
671
672 switch (i) {
673 case 0:
674 /* Should be nop req */
675 if (io_uring_cqe_get_data(cqe) != (void *) 1) {
676 fprintf(stderr, "%s: nop not seen as 1 or 2\n", __FUNCTION__);
677 goto err;
678 }
679 break;
680 case 1:
681 /* Should be timeout req_2 */
682 if (cqe->user_data != 2) {
683 fprintf(stderr, "%s: unexpected timeout req %d sequence\n",
684 __FUNCTION__, i+1);
685 goto err;
686 }
687 if (cqe->res < 0) {
688 fprintf(stderr, "%s: Req %d res %d\n",
689 __FUNCTION__, i+1, cqe->res);
690 goto err;
691 }
692 break;
693 case 2:
694 /* Should be timeout req_1 */
695 if (cqe->user_data != 1) {
696 fprintf(stderr, "%s: unexpected timeout req %d sequence\n",
697 __FUNCTION__, i+1);
698 goto err;
699 }
700 if (cqe->res != -ETIME) {
701 fprintf(stderr, "%s: Req %d timeout: %s\n",
702 __FUNCTION__, i+1, strerror(cqe->res));
703 goto err;
704 }
705 break;
706 }
707 io_uring_cqe_seen(ring, cqe);
708 }
709
710 return 0;
711 err:
712 return 1;
713 }
714
715 /*
716 * Test timeout <link> timeout <drain> timeout
717 */
test_timeout_flags1(struct io_uring * ring)718 static int test_timeout_flags1(struct io_uring *ring)
719 {
720 struct io_uring_sqe *sqe;
721 struct io_uring_cqe *cqe;
722 struct __kernel_timespec ts;
723 int ret, i;
724
725 msec_to_ts(&ts, TIMEOUT_MSEC);
726
727 sqe = io_uring_get_sqe(ring);
728 if (!sqe) {
729 fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
730 goto err;
731 }
732 io_uring_prep_timeout(sqe, &ts, 0, 0);
733 sqe->user_data = 1;
734 sqe->flags |= IOSQE_IO_LINK;
735
736 sqe = io_uring_get_sqe(ring);
737 if (!sqe) {
738 fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
739 goto err;
740 }
741 io_uring_prep_timeout(sqe, &ts, 0, 0);
742 sqe->user_data = 2;
743 sqe->flags |= IOSQE_IO_DRAIN;
744
745 sqe = io_uring_get_sqe(ring);
746 if (!sqe) {
747 fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
748 goto err;
749 }
750 io_uring_prep_timeout(sqe, &ts, 0, 0);
751 sqe->user_data = 3;
752
753 ret = io_uring_submit(ring);
754 if (ret <= 0) {
755 fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
756 goto err;
757 }
758
759 for (i = 0; i < 3; i++) {
760 ret = io_uring_wait_cqe(ring, &cqe);
761 if (ret < 0) {
762 fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
763 goto err;
764 }
765
766 if (cqe->res == -EINVAL) {
767 if (!i)
768 fprintf(stdout, "%s: timeout flags not supported\n",
769 __FUNCTION__);
770 io_uring_cqe_seen(ring, cqe);
771 continue;
772 }
773
774 switch (cqe->user_data) {
775 case 1:
776 if (cqe->res != -ETIME) {
777 fprintf(stderr, "%s: got %d, wanted %d\n",
778 __FUNCTION__, cqe->res, -ETIME);
779 goto err;
780 }
781 break;
782 case 2:
783 if (cqe->res != -ECANCELED) {
784 fprintf(stderr, "%s: got %d, wanted %d\n",
785 __FUNCTION__, cqe->res,
786 -ECANCELED);
787 goto err;
788 }
789 break;
790 case 3:
791 if (cqe->res != -ETIME) {
792 fprintf(stderr, "%s: got %d, wanted %d\n",
793 __FUNCTION__, cqe->res, -ETIME);
794 goto err;
795 }
796 break;
797 }
798 io_uring_cqe_seen(ring, cqe);
799 }
800
801 return 0;
802 err:
803 return 1;
804 }
805
806 /*
807 * Test timeout <link> timeout <link> timeout
808 */
test_timeout_flags2(struct io_uring * ring)809 static int test_timeout_flags2(struct io_uring *ring)
810 {
811 struct io_uring_sqe *sqe;
812 struct io_uring_cqe *cqe;
813 struct __kernel_timespec ts;
814 int ret, i;
815
816 msec_to_ts(&ts, TIMEOUT_MSEC);
817
818 sqe = io_uring_get_sqe(ring);
819 if (!sqe) {
820 fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
821 goto err;
822 }
823 io_uring_prep_timeout(sqe, &ts, 0, 0);
824 sqe->user_data = 1;
825 sqe->flags |= IOSQE_IO_LINK;
826
827 sqe = io_uring_get_sqe(ring);
828 if (!sqe) {
829 fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
830 goto err;
831 }
832 io_uring_prep_timeout(sqe, &ts, 0, 0);
833 sqe->user_data = 2;
834 sqe->flags |= IOSQE_IO_LINK;
835
836 sqe = io_uring_get_sqe(ring);
837 if (!sqe) {
838 fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
839 goto err;
840 }
841 io_uring_prep_timeout(sqe, &ts, 0, 0);
842 sqe->user_data = 3;
843
844 ret = io_uring_submit(ring);
845 if (ret <= 0) {
846 fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
847 goto err;
848 }
849
850 for (i = 0; i < 3; i++) {
851 ret = io_uring_wait_cqe(ring, &cqe);
852 if (ret < 0) {
853 fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
854 goto err;
855 }
856
857 if (cqe->res == -EINVAL) {
858 if (!i)
859 fprintf(stdout, "%s: timeout flags not supported\n",
860 __FUNCTION__);
861 io_uring_cqe_seen(ring, cqe);
862 continue;
863 }
864
865 switch (cqe->user_data) {
866 case 1:
867 if (cqe->res != -ETIME) {
868 fprintf(stderr, "%s: got %d, wanted %d\n",
869 __FUNCTION__, cqe->res, -ETIME);
870 goto err;
871 }
872 break;
873 case 2:
874 case 3:
875 if (cqe->res != -ECANCELED) {
876 fprintf(stderr, "%s: got %d, wanted %d\n",
877 __FUNCTION__, cqe->res,
878 -ECANCELED);
879 goto err;
880 }
881 break;
882 }
883 io_uring_cqe_seen(ring, cqe);
884 }
885
886 return 0;
887 err:
888 return 1;
889 }
890
891 /*
892 * Test timeout <drain> timeout <link> timeout
893 */
test_timeout_flags3(struct io_uring * ring)894 static int test_timeout_flags3(struct io_uring *ring)
895 {
896 struct io_uring_sqe *sqe;
897 struct io_uring_cqe *cqe;
898 struct __kernel_timespec ts;
899 int ret, i;
900
901 msec_to_ts(&ts, TIMEOUT_MSEC);
902
903 sqe = io_uring_get_sqe(ring);
904 if (!sqe) {
905 fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
906 goto err;
907 }
908 io_uring_prep_timeout(sqe, &ts, 0, 0);
909 sqe->user_data = 1;
910 sqe->flags |= IOSQE_IO_DRAIN;
911
912 sqe = io_uring_get_sqe(ring);
913 if (!sqe) {
914 fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
915 goto err;
916 }
917 io_uring_prep_timeout(sqe, &ts, 0, 0);
918 sqe->user_data = 2;
919 sqe->flags |= IOSQE_IO_LINK;
920
921 sqe = io_uring_get_sqe(ring);
922 if (!sqe) {
923 fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
924 goto err;
925 }
926 io_uring_prep_timeout(sqe, &ts, 0, 0);
927 sqe->user_data = 3;
928
929 ret = io_uring_submit(ring);
930 if (ret <= 0) {
931 fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
932 goto err;
933 }
934
935 for (i = 0; i < 3; i++) {
936 ret = io_uring_wait_cqe(ring, &cqe);
937 if (ret < 0) {
938 fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
939 goto err;
940 }
941
942 if (cqe->res == -EINVAL) {
943 if (!i)
944 fprintf(stdout, "%s: timeout flags not supported\n",
945 __FUNCTION__);
946 io_uring_cqe_seen(ring, cqe);
947 continue;
948 }
949
950 switch (cqe->user_data) {
951 case 1:
952 case 2:
953 if (cqe->res != -ETIME) {
954 fprintf(stderr, "%s: got %d, wanted %d\n",
955 __FUNCTION__, cqe->res, -ETIME);
956 goto err;
957 }
958 break;
959 case 3:
960 if (cqe->res != -ECANCELED) {
961 fprintf(stderr, "%s: got %d, wanted %d\n",
962 __FUNCTION__, cqe->res,
963 -ECANCELED);
964 goto err;
965 }
966 break;
967 }
968 io_uring_cqe_seen(ring, cqe);
969 }
970
971 return 0;
972 err:
973 return 1;
974 }
975
test_update_timeout(struct io_uring * ring,unsigned long ms,bool abs,bool async,bool linked)976 static int test_update_timeout(struct io_uring *ring, unsigned long ms,
977 bool abs, bool async, bool linked)
978 {
979 struct io_uring_sqe *sqe;
980 struct io_uring_cqe *cqe;
981 struct __kernel_timespec ts, ts_upd;
982 unsigned long long exp_ms, base_ms = 10000;
983 struct timeval tv;
984 int ret, i, nr = 2;
985 __u32 mode = abs ? IORING_TIMEOUT_ABS : 0;
986
987 msec_to_ts(&ts_upd, ms);
988 gettimeofday(&tv, NULL);
989
990 sqe = io_uring_get_sqe(ring);
991 if (!sqe) {
992 fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
993 goto err;
994 }
995 msec_to_ts(&ts, base_ms);
996 io_uring_prep_timeout(sqe, &ts, 0, 0);
997 sqe->user_data = 1;
998
999 if (linked) {
1000 sqe = io_uring_get_sqe(ring);
1001 if (!sqe) {
1002 fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
1003 goto err;
1004 }
1005 io_uring_prep_nop(sqe);
1006 sqe->user_data = 3;
1007 sqe->flags = IOSQE_IO_LINK;
1008 if (async)
1009 sqe->flags |= IOSQE_ASYNC;
1010 nr++;
1011 }
1012
1013 sqe = io_uring_get_sqe(ring);
1014 if (!sqe) {
1015 fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
1016 goto err;
1017 }
1018 io_uring_prep_timeout_update(sqe, &ts_upd, 1, mode);
1019 sqe->user_data = 2;
1020 if (async)
1021 sqe->flags |= IOSQE_ASYNC;
1022
1023 ret = io_uring_submit(ring);
1024 if (ret != nr) {
1025 fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
1026 goto err;
1027 }
1028
1029 for (i = 0; i < nr; i++) {
1030 ret = io_uring_wait_cqe(ring, &cqe);
1031 if (ret < 0) {
1032 fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
1033 goto err;
1034 }
1035
1036 switch (cqe->user_data) {
1037 case 1:
1038 if (cqe->res != -ETIME) {
1039 fprintf(stderr, "%s: got %d, wanted %d\n",
1040 __FUNCTION__, cqe->res, -ETIME);
1041 goto err;
1042 }
1043 break;
1044 case 2:
1045 if (cqe->res != 0) {
1046 fprintf(stderr, "%s: got %d, wanted %d\n",
1047 __FUNCTION__, cqe->res,
1048 0);
1049 goto err;
1050 }
1051 break;
1052 case 3:
1053 if (cqe->res != 0) {
1054 fprintf(stderr, "nop failed\n");
1055 goto err;
1056 }
1057 break;
1058 default:
1059 goto err;
1060 }
1061 io_uring_cqe_seen(ring, cqe);
1062 }
1063
1064 exp_ms = mtime_since_now(&tv);
1065 if (exp_ms >= base_ms / 2) {
1066 fprintf(stderr, "too long, timeout wasn't updated\n");
1067 goto err;
1068 }
1069 if (ms >= 1000 && !abs && exp_ms < ms / 2) {
1070 fprintf(stderr, "fired too early, potentially updated to 0 ms"
1071 "instead of %lu\n", ms);
1072 goto err;
1073 }
1074 return 0;
1075 err:
1076 return 1;
1077 }
1078
test_update_nonexistent_timeout(struct io_uring * ring)1079 static int test_update_nonexistent_timeout(struct io_uring *ring)
1080 {
1081 struct io_uring_sqe *sqe;
1082 struct io_uring_cqe *cqe;
1083 struct __kernel_timespec ts;
1084 int ret;
1085
1086 sqe = io_uring_get_sqe(ring);
1087 if (!sqe) {
1088 fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
1089 goto err;
1090 }
1091 msec_to_ts(&ts, 0);
1092 io_uring_prep_timeout_update(sqe, &ts, 42, 0);
1093
1094 ret = io_uring_submit(ring);
1095 if (ret != 1) {
1096 fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
1097 goto err;
1098 }
1099
1100 ret = io_uring_wait_cqe(ring, &cqe);
1101 if (ret < 0) {
1102 fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
1103 goto err;
1104 }
1105
1106 ret = cqe->res;
1107 if (ret == -ENOENT)
1108 ret = 0;
1109 io_uring_cqe_seen(ring, cqe);
1110 return ret;
1111 err:
1112 return 1;
1113 }
1114
test_update_invalid_flags(struct io_uring * ring)1115 static int test_update_invalid_flags(struct io_uring *ring)
1116 {
1117 struct io_uring_sqe *sqe;
1118 struct io_uring_cqe *cqe;
1119 struct __kernel_timespec ts;
1120 int ret;
1121
1122 sqe = io_uring_get_sqe(ring);
1123 if (!sqe) {
1124 fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
1125 goto err;
1126 }
1127 io_uring_prep_timeout_remove(sqe, 0, IORING_TIMEOUT_ABS);
1128
1129 ret = io_uring_submit(ring);
1130 if (ret != 1) {
1131 fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
1132 goto err;
1133 }
1134
1135 ret = io_uring_wait_cqe(ring, &cqe);
1136 if (ret < 0) {
1137 fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
1138 goto err;
1139 }
1140 if (cqe->res != -EINVAL) {
1141 fprintf(stderr, "%s: got %d, wanted %d\n",
1142 __FUNCTION__, cqe->res, -EINVAL);
1143 goto err;
1144 }
1145 io_uring_cqe_seen(ring, cqe);
1146
1147
1148 sqe = io_uring_get_sqe(ring);
1149 if (!sqe) {
1150 fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
1151 goto err;
1152 }
1153 msec_to_ts(&ts, 0);
1154 io_uring_prep_timeout_update(sqe, &ts, 0, -1);
1155
1156 ret = io_uring_submit(ring);
1157 if (ret != 1) {
1158 fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
1159 goto err;
1160 }
1161
1162 ret = io_uring_wait_cqe(ring, &cqe);
1163 if (ret < 0) {
1164 fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
1165 goto err;
1166 }
1167 if (cqe->res != -EINVAL) {
1168 fprintf(stderr, "%s: got %d, wanted %d\n",
1169 __FUNCTION__, cqe->res, -EINVAL);
1170 goto err;
1171 }
1172 io_uring_cqe_seen(ring, cqe);
1173
1174 return 0;
1175 err:
1176 return 1;
1177 }
1178
fill_exec_target(char * dst,char * path)1179 static int fill_exec_target(char *dst, char *path)
1180 {
1181 struct stat sb;
1182
1183 /*
1184 * Should either be ./exec-target.t or test/exec-target.t
1185 */
1186 sprintf(dst, "%s", path);
1187 return stat(dst, &sb);
1188 }
1189
test_timeout_link_cancel(void)1190 static int test_timeout_link_cancel(void)
1191 {
1192 struct io_uring ring;
1193 struct io_uring_cqe *cqe;
1194 char prog_path[PATH_MAX];
1195 pid_t p;
1196 int ret, i, wstatus;
1197
1198 if (fill_exec_target(prog_path, "./exec-target.t") &&
1199 fill_exec_target(prog_path, "test/exec-target.t")) {
1200 fprintf(stdout, "Can't find exec-target, skipping\n");
1201 return 0;
1202 }
1203
1204 ret = io_uring_queue_init(8, &ring, 0);
1205 if (ret) {
1206 fprintf(stderr, "ring create failed: %d\n", ret);
1207 return 1;
1208 }
1209
1210 p = fork();
1211 if (p == -1) {
1212 fprintf(stderr, "fork() failed\n");
1213 return 1;
1214 }
1215
1216 if (p == 0) {
1217 struct io_uring_sqe *sqe;
1218 struct __kernel_timespec ts;
1219
1220 msec_to_ts(&ts, 10000);
1221 sqe = io_uring_get_sqe(&ring);
1222 io_uring_prep_timeout(sqe, &ts, 0, 0);
1223 sqe->flags |= IOSQE_IO_LINK;
1224 sqe->user_data = 0;
1225
1226 sqe = io_uring_get_sqe(&ring);
1227 io_uring_prep_nop(sqe);
1228 sqe->user_data = 1;
1229
1230 ret = io_uring_submit(&ring);
1231 if (ret != 2) {
1232 fprintf(stderr, "%s: got %d, wanted 1\n", __FUNCTION__, ret);
1233 exit(1);
1234 }
1235
1236 /* trigger full cancelation */
1237 ret = execl(prog_path, prog_path, NULL);
1238 if (ret) {
1239 fprintf(stderr, "exec failed %i\n", errno);
1240 exit(1);
1241 }
1242 exit(0);
1243 }
1244
1245 if (waitpid(p, &wstatus, 0) == (pid_t)-1) {
1246 perror("waitpid()");
1247 return 1;
1248 }
1249 if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus)) {
1250 fprintf(stderr, "child failed %i\n", WEXITSTATUS(wstatus));
1251 return 1;
1252 }
1253
1254 for (i = 0; i < 2; ++i) {
1255 ret = io_uring_wait_cqe(&ring, &cqe);
1256 if (ret) {
1257 fprintf(stderr, "wait_cqe=%d\n", ret);
1258 return 1;
1259 }
1260 if (cqe->res != -ECANCELED) {
1261 fprintf(stderr, "invalid result, user_data: %i res: %i\n",
1262 (int)cqe->user_data, cqe->res);
1263 return 1;
1264 }
1265 io_uring_cqe_seen(&ring, cqe);
1266 }
1267
1268 io_uring_queue_exit(&ring);
1269 return 0;
1270 }
1271
1272
test_not_failing_links(void)1273 static int test_not_failing_links(void)
1274 {
1275 struct io_uring ring;
1276 struct io_uring_sqe *sqe;
1277 struct io_uring_cqe *cqe;
1278 struct __kernel_timespec ts;
1279 int ret;
1280
1281 ret = io_uring_queue_init(8, &ring, 0);
1282 if (ret) {
1283 fprintf(stderr, "ring create failed: %d\n", ret);
1284 return 1;
1285 }
1286
1287 msec_to_ts(&ts, 1);
1288 sqe = io_uring_get_sqe(&ring);
1289 io_uring_prep_timeout(sqe, &ts, 0, IORING_TIMEOUT_ETIME_SUCCESS);
1290 sqe->user_data = 1;
1291 sqe->flags |= IOSQE_IO_LINK;
1292
1293 sqe = io_uring_get_sqe(&ring);
1294 io_uring_prep_nop(sqe);
1295 sqe->user_data = 2;
1296
1297 ret = io_uring_submit(&ring);
1298 if (ret != 2) {
1299 fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
1300 return 1;
1301 }
1302
1303 ret = io_uring_wait_cqe(&ring, &cqe);
1304 if (ret < 0) {
1305 fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
1306 return 1;
1307 } else if (cqe->user_data == 1 && cqe->res == -EINVAL) {
1308 goto done;
1309 } else if (cqe->res != -ETIME || cqe->user_data != 1) {
1310 fprintf(stderr, "timeout failed %i %i\n", cqe->res,
1311 (int)cqe->user_data);
1312 return 1;
1313 }
1314 io_uring_cqe_seen(&ring, cqe);
1315
1316 ret = io_uring_wait_cqe(&ring, &cqe);
1317 if (ret < 0) {
1318 fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
1319 return 1;
1320 } else if (cqe->res || cqe->user_data != 2) {
1321 fprintf(stderr, "nop failed %i %i\n", cqe->res,
1322 (int)cqe->user_data);
1323 return 1;
1324 }
1325 done:
1326 io_uring_cqe_seen(&ring, cqe);
1327 io_uring_queue_exit(&ring);
1328 return 0;
1329 }
1330
1331
test_timeout_multishot(struct io_uring * ring)1332 static int test_timeout_multishot(struct io_uring *ring)
1333 {
1334 struct io_uring_cqe *cqe;
1335 struct io_uring_sqe *sqe;
1336 struct __kernel_timespec ts;
1337 int ret;
1338
1339 sqe = io_uring_get_sqe(ring);
1340 if (!sqe) {
1341 fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
1342 goto err;
1343 }
1344
1345 msec_to_ts(&ts, TIMEOUT_MSEC);
1346 io_uring_prep_timeout(sqe, &ts, 0, IORING_TIMEOUT_MULTISHOT);
1347 io_uring_sqe_set_data(sqe, (void *) 1);
1348
1349 ret = io_uring_submit(ring);
1350 if (ret <= 0) {
1351 fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
1352 goto err;
1353 }
1354
1355 for (int i = 0; i < 2; i++) {
1356 ret = io_uring_wait_cqe(ring, &cqe);
1357 if (ret < 0) {
1358 fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
1359 goto err;
1360 }
1361
1362 ret = cqe->res;
1363 if (ret == -EINVAL) {
1364 no_multishot = 1;
1365 return T_EXIT_SKIP;
1366 }
1367
1368 if (!(cqe->flags & IORING_CQE_F_MORE)) {
1369 fprintf(stderr, "%s: flag not set in cqe\n", __FUNCTION__);
1370 goto err;
1371 }
1372
1373 if (ret != -ETIME) {
1374 fprintf(stderr, "%s: Timeout: %s\n", __FUNCTION__, strerror(-ret));
1375 goto err;
1376 }
1377
1378 io_uring_cqe_seen(ring, cqe);
1379 }
1380
1381 sqe = io_uring_get_sqe(ring);
1382 if (!sqe) {
1383 fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
1384 goto err;
1385 }
1386
1387 io_uring_prep_timeout_remove(sqe, 1, 0);
1388 io_uring_sqe_set_data(sqe, (void *) 2);
1389
1390 ret = io_uring_submit(ring);
1391 if (ret <= 0) {
1392 fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
1393 goto err;
1394 }
1395
1396 ret = io_uring_wait_cqe(ring, &cqe);
1397 if (ret < 0) {
1398 fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
1399 goto err;
1400 }
1401
1402 ret = cqe->res;
1403 if (ret < 0) {
1404 fprintf(stderr, "%s: remove failed: %s\n", __FUNCTION__, strerror(-ret));
1405 goto err;
1406 }
1407
1408 io_uring_cqe_seen(ring, cqe);
1409
1410 ret = io_uring_wait_cqe(ring, &cqe);
1411 if (ret < 0) {
1412 fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
1413 goto err;
1414 }
1415
1416 ret = cqe->res;
1417 if (ret != -ECANCELED) {
1418 fprintf(stderr, "%s: timeout canceled: %s %llu\n", __FUNCTION__, strerror(-ret), cqe->user_data);
1419 goto err;
1420 }
1421
1422 io_uring_cqe_seen(ring, cqe);
1423 return 0;
1424 err:
1425 return 1;
1426 }
1427
1428
test_timeout_multishot_nr(struct io_uring * ring)1429 static int test_timeout_multishot_nr(struct io_uring *ring)
1430 {
1431 struct io_uring_cqe *cqe;
1432 struct io_uring_sqe *sqe;
1433 struct __kernel_timespec ts;
1434 int ret;
1435
1436 if (no_multishot)
1437 return T_EXIT_SKIP;
1438
1439 sqe = io_uring_get_sqe(ring);
1440 if (!sqe) {
1441 fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
1442 goto err;
1443 }
1444
1445 msec_to_ts(&ts, TIMEOUT_MSEC);
1446 io_uring_prep_timeout(sqe, &ts, 3, IORING_TIMEOUT_MULTISHOT);
1447 io_uring_sqe_set_data(sqe, (void *) 1);
1448
1449 ret = io_uring_submit(ring);
1450 if (ret <= 0) {
1451 fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
1452 goto err;
1453 }
1454
1455 for (int i = 0; i < 3; i++) {
1456 ret = io_uring_wait_cqe(ring, &cqe);
1457 if (ret < 0) {
1458 fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
1459 goto err;
1460 }
1461
1462 if (i < 2 && !(cqe->flags & IORING_CQE_F_MORE)) {
1463 fprintf(stderr, "%s: flag not set in cqe\n", __FUNCTION__);
1464 goto err;
1465 }
1466 if (i == 3 && (cqe->flags & IORING_CQE_F_MORE)) {
1467 fprintf(stderr, "%s: flag set in cqe\n", __FUNCTION__);
1468 goto err;
1469 }
1470
1471 ret = cqe->res;
1472 if (ret != -ETIME) {
1473 fprintf(stderr, "%s: Timeout: %s\n", __FUNCTION__, strerror(-ret));
1474 goto err;
1475 }
1476
1477 io_uring_cqe_seen(ring, cqe);
1478 }
1479
1480 msec_to_ts(&ts, 2 * TIMEOUT_MSEC);
1481 ret = io_uring_wait_cqe_timeout(ring, &cqe, &ts);
1482 if (ret != -ETIME) {
1483 fprintf(stderr, "%s: wait completion timeout %s\n", __FUNCTION__, strerror(-ret));
1484 goto err;
1485 }
1486
1487 return 0;
1488 err:
1489 return 1;
1490 }
1491
1492
test_timeout_multishot_overflow(struct io_uring * ring)1493 static int test_timeout_multishot_overflow(struct io_uring *ring)
1494 {
1495 struct io_uring_cqe *cqe;
1496 struct io_uring_sqe *sqe;
1497 struct __kernel_timespec ts;
1498 int ret;
1499
1500 if (no_multishot)
1501 return T_EXIT_SKIP;
1502
1503 sqe = io_uring_get_sqe(ring);
1504 if (!sqe) {
1505 fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
1506 goto err;
1507 }
1508
1509 msec_to_ts(&ts, 10);
1510 io_uring_prep_timeout(sqe, &ts, 0, IORING_TIMEOUT_MULTISHOT);
1511 io_uring_sqe_set_data(sqe, (void *) 1);
1512
1513 ret = io_uring_submit(ring);
1514 if (ret <= 0) {
1515 fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
1516 goto err;
1517 }
1518
1519 ret = io_uring_wait_cqe(ring, &cqe);
1520 if (ret < 0) {
1521 fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
1522 goto err;
1523 }
1524
1525 ret = cqe->res;
1526 if (ret != -ETIME) {
1527 fprintf(stderr, "%s: Timeout: %s\n", __FUNCTION__, strerror(-ret));
1528 goto err;
1529 }
1530
1531 io_uring_cqe_seen(ring, cqe);
1532 sleep(1);
1533
1534 if (!((*ring->sq.kflags) & IORING_SQ_CQ_OVERFLOW)) {
1535 goto err;
1536 }
1537
1538 /* multishot timer should be gone */
1539 sqe = io_uring_get_sqe(ring);
1540 if (!sqe) {
1541 fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
1542 goto err;
1543 }
1544
1545 io_uring_prep_timeout_remove(sqe, 1, 0);
1546
1547 ret = io_uring_submit(ring);
1548 if (ret <= 0) {
1549 fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
1550 goto err;
1551 }
1552
1553 ret = io_uring_wait_cqe(ring, &cqe);
1554 if (ret < 0) {
1555 fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
1556 goto err;
1557 }
1558
1559 ret = cqe->res;
1560 io_uring_cqe_seen(ring, cqe);
1561 if (ret != -ETIME) {
1562 fprintf(stderr, "%s: remove failed: %d %s\n", __FUNCTION__, ret, strerror(-ret));
1563 goto err;
1564 }
1565
1566 return 0;
1567 err:
1568 return 1;
1569 }
1570
1571
main(int argc,char * argv[])1572 int main(int argc, char *argv[])
1573 {
1574 struct io_uring ring, sqpoll_ring;
1575 bool has_timeout_update, sqpoll;
1576 struct io_uring_params p = { };
1577 int ret;
1578
1579 if (argc > 1)
1580 return 0;
1581
1582 ret = io_uring_queue_init_params(8, &ring, &p);
1583 if (ret) {
1584 fprintf(stderr, "ring setup failed\n");
1585 return 1;
1586 }
1587
1588 ret = io_uring_queue_init(8, &sqpoll_ring, IORING_SETUP_SQPOLL);
1589 sqpoll = !ret;
1590
1591 ret = test_single_timeout(&ring);
1592 if (ret) {
1593 fprintf(stderr, "test_single_timeout failed\n");
1594 return ret;
1595 }
1596 if (not_supported)
1597 return 0;
1598
1599 ret = test_multi_timeout(&ring);
1600 if (ret) {
1601 fprintf(stderr, "test_multi_timeout failed\n");
1602 return ret;
1603 }
1604
1605 ret = test_single_timeout_abs(&ring);
1606 if (ret) {
1607 fprintf(stderr, "test_single_timeout_abs failed\n");
1608 return ret;
1609 }
1610
1611 ret = test_single_timeout_remove(&ring);
1612 if (ret) {
1613 fprintf(stderr, "test_single_timeout_remove failed\n");
1614 return ret;
1615 }
1616
1617 ret = test_single_timeout_remove_notfound(&ring);
1618 if (ret) {
1619 fprintf(stderr, "test_single_timeout_remove_notfound failed\n");
1620 return ret;
1621 }
1622
1623 ret = test_single_timeout_many(&ring);
1624 if (ret) {
1625 fprintf(stderr, "test_single_timeout_many failed\n");
1626 return ret;
1627 }
1628
1629 ret = test_single_timeout_nr(&ring, 1);
1630 if (ret) {
1631 fprintf(stderr, "test_single_timeout_nr(1) failed\n");
1632 return ret;
1633 }
1634 ret = test_single_timeout_nr(&ring, 2);
1635 if (ret) {
1636 fprintf(stderr, "test_single_timeout_nr(2) failed\n");
1637 return ret;
1638 }
1639
1640 ret = test_multi_timeout_nr(&ring);
1641 if (ret) {
1642 fprintf(stderr, "test_multi_timeout_nr failed\n");
1643 return ret;
1644 }
1645
1646 ret = test_timeout_flags1(&ring);
1647 if (ret) {
1648 fprintf(stderr, "test_timeout_flags1 failed\n");
1649 return ret;
1650 }
1651
1652 ret = test_timeout_flags2(&ring);
1653 if (ret) {
1654 fprintf(stderr, "test_timeout_flags2 failed\n");
1655 return ret;
1656 }
1657
1658 ret = test_timeout_flags3(&ring);
1659 if (ret) {
1660 fprintf(stderr, "test_timeout_flags3 failed\n");
1661 return ret;
1662 }
1663
1664 ret = test_timeout_multishot(&ring);
1665 if (ret && ret != T_EXIT_SKIP) {
1666 fprintf(stderr, "test_timeout_multishot failed\n");
1667 return ret;
1668 }
1669
1670 ret = test_timeout_multishot_nr(&ring);
1671 if (ret && ret != T_EXIT_SKIP) {
1672 fprintf(stderr, "test_timeout_multishot_nr failed\n");
1673 return ret;
1674 }
1675
1676 /* io_uring_wait_cqe_timeout() may have left a timeout, reinit ring */
1677 io_uring_queue_exit(&ring);
1678 ret = io_uring_queue_init(8, &ring, 0);
1679 if (ret) {
1680 fprintf(stderr, "ring setup failed\n");
1681 return 1;
1682 }
1683
1684 ret = test_timeout_multishot_overflow(&ring);
1685 if (ret && ret != T_EXIT_SKIP) {
1686 fprintf(stderr, "test_timeout_multishot_overflow failed\n");
1687 return ret;
1688 }
1689
1690 /* io_uring_wait_cqe_timeout() may have left a timeout, reinit ring */
1691 io_uring_queue_exit(&ring);
1692 ret = io_uring_queue_init(8, &ring, 0);
1693 if (ret) {
1694 fprintf(stderr, "ring setup failed\n");
1695 return 1;
1696 }
1697
1698 ret = test_single_timeout_wait(&ring, &p);
1699 if (ret) {
1700 fprintf(stderr, "test_single_timeout_wait failed\n");
1701 return ret;
1702 }
1703
1704 /* io_uring_wait_cqes() may have left a timeout, reinit ring */
1705 io_uring_queue_exit(&ring);
1706 ret = io_uring_queue_init(8, &ring, 0);
1707 if (ret) {
1708 fprintf(stderr, "ring setup failed\n");
1709 return 1;
1710 }
1711
1712 ret = test_update_nonexistent_timeout(&ring);
1713 has_timeout_update = (ret != -EINVAL);
1714 if (has_timeout_update) {
1715 if (ret) {
1716 fprintf(stderr, "test_update_nonexistent_timeout failed\n");
1717 return ret;
1718 }
1719
1720 ret = test_update_invalid_flags(&ring);
1721 if (ret) {
1722 fprintf(stderr, "test_update_invalid_flags failed\n");
1723 return ret;
1724 }
1725
1726 ret = test_update_timeout(&ring, 0, false, false, false);
1727 if (ret) {
1728 fprintf(stderr, "test_update_timeout failed\n");
1729 return ret;
1730 }
1731
1732 ret = test_update_timeout(&ring, 1, false, false, false);
1733 if (ret) {
1734 fprintf(stderr, "test_update_timeout 1ms failed\n");
1735 return ret;
1736 }
1737
1738 ret = test_update_timeout(&ring, 1000, false, false, false);
1739 if (ret) {
1740 fprintf(stderr, "test_update_timeout 1s failed\n");
1741 return ret;
1742 }
1743
1744 ret = test_update_timeout(&ring, 0, true, true, false);
1745 if (ret) {
1746 fprintf(stderr, "test_update_timeout abs failed\n");
1747 return ret;
1748 }
1749
1750
1751 ret = test_update_timeout(&ring, 0, false, true, false);
1752 if (ret) {
1753 fprintf(stderr, "test_update_timeout async failed\n");
1754 return ret;
1755 }
1756
1757 ret = test_update_timeout(&ring, 0, false, false, true);
1758 if (ret) {
1759 fprintf(stderr, "test_update_timeout linked failed\n");
1760 return ret;
1761 }
1762
1763 if (sqpoll) {
1764 ret = test_update_timeout(&sqpoll_ring, 0, false, false,
1765 false);
1766 if (ret) {
1767 fprintf(stderr, "test_update_timeout sqpoll"
1768 "failed\n");
1769 return ret;
1770 }
1771 }
1772 }
1773
1774 /*
1775 * this test must go last, it kills the ring
1776 */
1777 ret = test_single_timeout_exit(&ring);
1778 if (ret) {
1779 fprintf(stderr, "test_single_timeout_exit failed\n");
1780 return ret;
1781 }
1782
1783 ret = test_timeout_link_cancel();
1784 if (ret) {
1785 fprintf(stderr, "test_timeout_link_cancel failed\n");
1786 return ret;
1787 }
1788
1789 ret = test_not_failing_links();
1790 if (ret) {
1791 fprintf(stderr, "test_not_failing_links failed\n");
1792 return ret;
1793 }
1794
1795 if (sqpoll)
1796 io_uring_queue_exit(&sqpoll_ring);
1797 return 0;
1798 }
1799