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