1 /* SPDX-License-Identifier: MIT */
2 /*
3 * Description: run various linked timeout cases
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 <poll.h>
13 #include <sys/time.h>
14
15 #include "liburing.h"
16 #include "helpers.h"
17
test_fail_lone_link_timeouts(struct io_uring * ring)18 static int test_fail_lone_link_timeouts(struct io_uring *ring)
19 {
20 struct __kernel_timespec ts;
21 struct io_uring_cqe *cqe;
22 struct io_uring_sqe *sqe;
23 int ret;
24
25 sqe = io_uring_get_sqe(ring);
26 if (!sqe) {
27 printf("get sqe failed\n");
28 goto err;
29 }
30 io_uring_prep_link_timeout(sqe, &ts, 0);
31 ts.tv_sec = 1;
32 ts.tv_nsec = 0;
33 sqe->user_data = 1;
34 sqe->flags |= IOSQE_IO_LINK;
35
36 ret = io_uring_submit(ring);
37 if (ret != 1) {
38 printf("sqe submit failed: %d\n", ret);
39 goto err;
40 }
41
42 ret = io_uring_wait_cqe(ring, &cqe);
43 if (ret < 0) {
44 printf("wait completion %d\n", ret);
45 goto err;
46 }
47
48 if (cqe->user_data != 1) {
49 fprintf(stderr, "invalid user data %d\n", cqe->res);
50 goto err;
51 }
52 if (cqe->res != -EINVAL) {
53 fprintf(stderr, "got %d, wanted -EINVAL\n", cqe->res);
54 goto err;
55 }
56 io_uring_cqe_seen(ring, cqe);
57
58 return 0;
59 err:
60 return 1;
61 }
62
test_fail_two_link_timeouts(struct io_uring * ring)63 static int test_fail_two_link_timeouts(struct io_uring *ring)
64 {
65 struct __kernel_timespec ts;
66 struct io_uring_cqe *cqe;
67 struct io_uring_sqe *sqe;
68 int ret, i, nr_wait;
69
70 ts.tv_sec = 1;
71 ts.tv_nsec = 0;
72
73 /*
74 * sqe_1: write destined to fail
75 * use buf=NULL, to do that during the issuing stage
76 */
77 sqe = io_uring_get_sqe(ring);
78 if (!sqe) {
79 printf("get sqe failed\n");
80 goto err;
81 }
82 io_uring_prep_writev(sqe, 0, NULL, 1, 0);
83 sqe->flags |= IOSQE_IO_LINK;
84 sqe->user_data = 1;
85
86
87 /* sqe_2: valid linked timeout */
88 sqe = io_uring_get_sqe(ring);
89 if (!sqe) {
90 printf("get sqe failed\n");
91 goto err;
92 }
93 io_uring_prep_link_timeout(sqe, &ts, 0);
94 sqe->user_data = 2;
95 sqe->flags |= IOSQE_IO_LINK;
96
97
98 /* sqe_3: invalid linked timeout */
99 sqe = io_uring_get_sqe(ring);
100 if (!sqe) {
101 printf("get sqe failed\n");
102 goto err;
103 }
104 io_uring_prep_link_timeout(sqe, &ts, 0);
105 sqe->flags |= IOSQE_IO_LINK;
106 sqe->user_data = 3;
107
108 /* sqe_4: invalid linked timeout */
109 sqe = io_uring_get_sqe(ring);
110 if (!sqe) {
111 printf("get sqe failed\n");
112 goto err;
113 }
114 io_uring_prep_link_timeout(sqe, &ts, 0);
115 sqe->flags |= IOSQE_IO_LINK;
116 sqe->user_data = 4;
117
118 ret = io_uring_submit(ring);
119 if (ret < 3) {
120 printf("sqe submit failed: %d\n", ret);
121 goto err;
122 }
123 nr_wait = ret;
124
125 for (i = 0; i < nr_wait; i++) {
126 ret = io_uring_wait_cqe(ring, &cqe);
127 if (ret < 0) {
128 printf("wait completion %d\n", ret);
129 goto err;
130 }
131
132 switch (cqe->user_data) {
133 case 1:
134 if (cqe->res != -EFAULT && cqe->res != -ECANCELED) {
135 fprintf(stderr, "write got %d, wanted -EFAULT "
136 "or -ECANCELED\n", cqe->res);
137 goto err;
138 }
139 break;
140 case 2:
141 if (cqe->res != -ECANCELED) {
142 fprintf(stderr, "Link timeout got %d, wanted -ECACNCELED\n", cqe->res);
143 goto err;
144 }
145 break;
146 case 3:
147 /* fall through */
148 case 4:
149 if (cqe->res != -ECANCELED && cqe->res != -EINVAL) {
150 fprintf(stderr, "Invalid link timeout got %d"
151 ", wanted -ECACNCELED || -EINVAL\n", cqe->res);
152 goto err;
153 }
154 break;
155 }
156 io_uring_cqe_seen(ring, cqe);
157 }
158
159 return 0;
160 err:
161 return 1;
162 }
163
164 /*
165 * Test linked timeout with timeout (timeoutception)
166 */
test_single_link_timeout_ception(struct io_uring * ring)167 static int test_single_link_timeout_ception(struct io_uring *ring)
168 {
169 struct __kernel_timespec ts1, ts2;
170 struct io_uring_cqe *cqe;
171 struct io_uring_sqe *sqe;
172 int ret, i;
173
174 sqe = io_uring_get_sqe(ring);
175 if (!sqe) {
176 printf("get sqe failed\n");
177 goto err;
178 }
179
180 ts1.tv_sec = 1;
181 ts1.tv_nsec = 0;
182 io_uring_prep_timeout(sqe, &ts1, -1U, 0);
183 sqe->flags |= IOSQE_IO_LINK;
184 sqe->user_data = 1;
185
186 sqe = io_uring_get_sqe(ring);
187 if (!sqe) {
188 printf("get sqe failed\n");
189 goto err;
190 }
191
192 ts2.tv_sec = 2;
193 ts2.tv_nsec = 0;
194 io_uring_prep_link_timeout(sqe, &ts2, 0);
195 sqe->user_data = 2;
196
197 ret = io_uring_submit(ring);
198 if (ret != 2) {
199 printf("sqe submit failed: %d\n", ret);
200 goto err;
201 }
202
203 for (i = 0; i < 2; i++) {
204 ret = io_uring_wait_cqe(ring, &cqe);
205 if (ret < 0) {
206 printf("wait completion %d\n", ret);
207 goto err;
208 }
209 switch (cqe->user_data) {
210 case 1:
211 /* newer kernels allow timeout links */
212 if (cqe->res != -EINVAL && cqe->res != -ETIME) {
213 fprintf(stderr, "Timeout got %d, wanted "
214 "-EINVAL or -ETIME\n", cqe->res);
215 goto err;
216 }
217 break;
218 case 2:
219 if (cqe->res != -ECANCELED) {
220 fprintf(stderr, "Link timeout got %d, wanted -ECANCELED\n", cqe->res);
221 goto err;
222 }
223 break;
224 }
225 io_uring_cqe_seen(ring, cqe);
226 }
227
228 return 0;
229 err:
230 return 1;
231 }
232
233 /*
234 * Test linked timeout with NOP
235 */
test_single_link_timeout_nop(struct io_uring * ring)236 static int test_single_link_timeout_nop(struct io_uring *ring)
237 {
238 struct __kernel_timespec ts;
239 struct io_uring_cqe *cqe;
240 struct io_uring_sqe *sqe;
241 int ret, i;
242
243 sqe = io_uring_get_sqe(ring);
244 if (!sqe) {
245 printf("get sqe failed\n");
246 goto err;
247 }
248
249 io_uring_prep_nop(sqe);
250 sqe->flags |= IOSQE_IO_LINK;
251 sqe->user_data = 1;
252
253 sqe = io_uring_get_sqe(ring);
254 if (!sqe) {
255 printf("get sqe failed\n");
256 goto err;
257 }
258
259 ts.tv_sec = 1;
260 ts.tv_nsec = 0;
261 io_uring_prep_link_timeout(sqe, &ts, 0);
262 sqe->user_data = 2;
263
264 ret = io_uring_submit(ring);
265 if (ret != 2) {
266 printf("sqe submit failed: %d\n", ret);
267 goto err;
268 }
269
270 for (i = 0; i < 2; i++) {
271 ret = io_uring_wait_cqe(ring, &cqe);
272 if (ret < 0) {
273 printf("wait completion %d\n", ret);
274 goto err;
275 }
276 switch (cqe->user_data) {
277 case 1:
278 if (cqe->res) {
279 fprintf(stderr, "NOP got %d, wanted 0\n", cqe->res);
280 goto err;
281 }
282 break;
283 case 2:
284 if (cqe->res != -ECANCELED) {
285 fprintf(stderr, "Link timeout got %d, wanted -ECACNCELED\n", cqe->res);
286 goto err;
287 }
288 break;
289 }
290 io_uring_cqe_seen(ring, cqe);
291 }
292
293 return 0;
294 err:
295 return 1;
296 }
297
298 /*
299 * Test read that will not complete, with a linked timeout behind it that
300 * has errors in the SQE
301 */
test_single_link_timeout_error(struct io_uring * ring)302 static int test_single_link_timeout_error(struct io_uring *ring)
303 {
304 struct __kernel_timespec ts;
305 struct io_uring_cqe *cqe;
306 struct io_uring_sqe *sqe;
307 int fds[2], ret, i;
308 struct iovec iov;
309 char buffer[128];
310
311 if (pipe(fds)) {
312 perror("pipe");
313 return 1;
314 }
315
316 sqe = io_uring_get_sqe(ring);
317 if (!sqe) {
318 printf("get sqe failed\n");
319 goto err;
320 }
321
322 iov.iov_base = buffer;
323 iov.iov_len = sizeof(buffer);
324 io_uring_prep_readv(sqe, fds[0], &iov, 1, 0);
325 sqe->flags |= IOSQE_IO_LINK;
326 sqe->user_data = 1;
327
328 sqe = io_uring_get_sqe(ring);
329 if (!sqe) {
330 printf("get sqe failed\n");
331 goto err;
332 }
333
334 ts.tv_sec = 1;
335 ts.tv_nsec = 0;
336 io_uring_prep_link_timeout(sqe, &ts, 0);
337 /* set invalid field, it'll get failed */
338 sqe->ioprio = 89;
339 sqe->user_data = 2;
340
341 ret = io_uring_submit(ring);
342 if (ret != 2) {
343 printf("sqe submit failed: %d\n", ret);
344 goto err;
345 }
346
347 for (i = 0; i < 2; i++) {
348 ret = io_uring_wait_cqe(ring, &cqe);
349 if (ret < 0) {
350 printf("wait completion %d\n", ret);
351 goto err;
352 }
353 switch (cqe->user_data) {
354 case 1:
355 if (cqe->res != -ECANCELED) {
356 fprintf(stderr, "Read got %d, wanted -ECANCELED\n",
357 cqe->res);
358 goto err;
359 }
360 break;
361 case 2:
362 if (cqe->res != -EINVAL) {
363 fprintf(stderr, "Link timeout got %d, wanted -EINVAL\n", cqe->res);
364 goto err;
365 }
366 break;
367 }
368 io_uring_cqe_seen(ring, cqe);
369 }
370
371 return 0;
372 err:
373 return 1;
374 }
375
376 /*
377 * Test read that will complete, with a linked timeout behind it
378 */
test_single_link_no_timeout(struct io_uring * ring)379 static int test_single_link_no_timeout(struct io_uring *ring)
380 {
381 struct __kernel_timespec ts;
382 struct io_uring_cqe *cqe;
383 struct io_uring_sqe *sqe;
384 int fds[2], ret, i;
385 struct iovec iov;
386 char buffer[128];
387
388 if (pipe(fds)) {
389 perror("pipe");
390 return 1;
391 }
392
393 sqe = io_uring_get_sqe(ring);
394 if (!sqe) {
395 printf("get sqe failed\n");
396 goto err;
397 }
398
399 iov.iov_base = buffer;
400 iov.iov_len = sizeof(buffer);
401 io_uring_prep_readv(sqe, fds[0], &iov, 1, 0);
402 sqe->flags |= IOSQE_IO_LINK;
403 sqe->user_data = 1;
404
405 sqe = io_uring_get_sqe(ring);
406 if (!sqe) {
407 printf("get sqe failed\n");
408 goto err;
409 }
410
411 ts.tv_sec = 1;
412 ts.tv_nsec = 0;
413 io_uring_prep_link_timeout(sqe, &ts, 0);
414 sqe->user_data = 2;
415
416 sqe = io_uring_get_sqe(ring);
417 if (!sqe) {
418 printf("get sqe failed\n");
419 goto err;
420 }
421
422 iov.iov_base = buffer;
423 iov.iov_len = sizeof(buffer);
424 io_uring_prep_writev(sqe, fds[1], &iov, 1, 0);
425 sqe->user_data = 3;
426
427 ret = io_uring_submit(ring);
428 if (ret != 3) {
429 printf("sqe submit failed: %d\n", ret);
430 goto err;
431 }
432
433 for (i = 0; i < 3; i++) {
434 ret = io_uring_wait_cqe(ring, &cqe);
435 if (ret < 0) {
436 printf("wait completion %d\n", ret);
437 goto err;
438 }
439 switch (cqe->user_data) {
440 case 1:
441 case 3:
442 if (cqe->res != sizeof(buffer)) {
443 fprintf(stderr, "R/W got %d, wanted %d\n", cqe->res,
444 (int) sizeof(buffer));
445 goto err;
446 }
447 break;
448 case 2:
449 if (cqe->res != -ECANCELED) {
450 fprintf(stderr, "Link timeout %d, wanted -ECANCELED\n",
451 cqe->res);
452 goto err;
453 }
454 break;
455 }
456 io_uring_cqe_seen(ring, cqe);
457 }
458
459 return 0;
460 err:
461 return 1;
462 }
463
464 /*
465 * Test read that will not complete, with a linked timeout behind it
466 */
test_single_link_timeout(struct io_uring * ring,unsigned nsec)467 static int test_single_link_timeout(struct io_uring *ring, unsigned nsec)
468 {
469 struct __kernel_timespec ts;
470 struct io_uring_cqe *cqe;
471 struct io_uring_sqe *sqe;
472 int fds[2], ret, i;
473 struct iovec iov;
474 char buffer[128];
475
476 if (pipe(fds)) {
477 perror("pipe");
478 return 1;
479 }
480
481 sqe = io_uring_get_sqe(ring);
482 if (!sqe) {
483 printf("get sqe failed\n");
484 goto err;
485 }
486
487 iov.iov_base = buffer;
488 iov.iov_len = sizeof(buffer);
489 io_uring_prep_readv(sqe, fds[0], &iov, 1, 0);
490 sqe->flags |= IOSQE_IO_LINK;
491 sqe->user_data = 1;
492
493 sqe = io_uring_get_sqe(ring);
494 if (!sqe) {
495 printf("get sqe failed\n");
496 goto err;
497 }
498
499 ts.tv_sec = 0;
500 ts.tv_nsec = nsec;
501 io_uring_prep_link_timeout(sqe, &ts, 0);
502 sqe->user_data = 2;
503
504 ret = io_uring_submit(ring);
505 if (ret != 2) {
506 printf("sqe submit failed: %d\n", ret);
507 goto err;
508 }
509
510 for (i = 0; i < 2; i++) {
511 ret = io_uring_wait_cqe(ring, &cqe);
512 if (ret < 0) {
513 printf("wait completion %d\n", ret);
514 goto err;
515 }
516 switch (cqe->user_data) {
517 case 1:
518 if (cqe->res != -EINTR && cqe->res != -ECANCELED) {
519 fprintf(stderr, "Read got %d\n", cqe->res);
520 goto err;
521 }
522 break;
523 case 2:
524 if (cqe->res != -EALREADY && cqe->res != -ETIME &&
525 cqe->res != 0) {
526 fprintf(stderr, "Link timeout got %d\n", cqe->res);
527 goto err;
528 }
529 break;
530 }
531 io_uring_cqe_seen(ring, cqe);
532 }
533
534 close(fds[0]);
535 close(fds[1]);
536 return 0;
537 err:
538 return 1;
539 }
540
test_link_timeout_update(struct io_uring * ring,int async)541 static int test_link_timeout_update(struct io_uring *ring, int async)
542 {
543 struct __kernel_timespec ts;
544 struct io_uring_cqe *cqe;
545 struct io_uring_sqe *sqe;
546 struct timeval start;
547 unsigned long msec;
548 int fds[2], ret, i;
549 struct iovec iov;
550 char buffer[128];
551
552 if (pipe(fds)) {
553 perror("pipe");
554 return 1;
555 }
556
557 sqe = io_uring_get_sqe(ring);
558 if (!sqe) {
559 printf("get sqe failed\n");
560 goto err;
561 }
562 iov.iov_base = buffer;
563 iov.iov_len = sizeof(buffer);
564 io_uring_prep_readv(sqe, fds[0], &iov, 1, 0);
565 sqe->flags |= IOSQE_IO_LINK;
566 sqe->user_data = 1;
567
568 sqe = io_uring_get_sqe(ring);
569 if (!sqe) {
570 printf("get sqe failed\n");
571 goto err;
572 }
573 ts.tv_sec = 5;
574 ts.tv_nsec = 0;
575 io_uring_prep_link_timeout(sqe, &ts, 0);
576 sqe->user_data = 2;
577
578 ret = io_uring_submit(ring);
579 if (ret != 2) {
580 printf("sqe submit failed: %d\n", ret);
581 goto err;
582 }
583
584 ts.tv_sec = 0;
585 ts.tv_nsec = 100000000LL;
586 sqe = io_uring_get_sqe(ring);
587 io_uring_prep_timeout_update(sqe, &ts, 2, IORING_LINK_TIMEOUT_UPDATE);
588 if (async)
589 sqe->flags |= IOSQE_ASYNC;
590 sqe->user_data = 3;
591
592 io_uring_submit(ring);
593
594 gettimeofday(&start, NULL);
595 for (i = 0; i < 3; i++) {
596 ret = io_uring_wait_cqe(ring, &cqe);
597 if (ret < 0) {
598 printf("wait completion %d\n", ret);
599 goto err;
600 }
601 switch (cqe->user_data) {
602 case 1:
603 if (cqe->res != -EINTR && cqe->res != -ECANCELED) {
604 fprintf(stderr, "Req %" PRIu64 " got %d\n", (uint64_t) cqe->user_data,
605 cqe->res);
606 goto err;
607 }
608 break;
609 case 2:
610 /* FASTPOLL kernels can cancel successfully */
611 if (cqe->res != -EALREADY && cqe->res != -ETIME) {
612 fprintf(stderr, "Req %" PRIu64 " got %d\n", (uint64_t) cqe->user_data,
613 cqe->res);
614 goto err;
615 }
616 break;
617 case 3:
618 if (cqe->res) {
619 fprintf(stderr, "Req %" PRIu64 " got %d\n", (uint64_t) cqe->user_data,
620 cqe->res);
621 goto err;
622 }
623 break;
624 }
625
626 io_uring_cqe_seen(ring, cqe);
627 }
628
629 msec = mtime_since_now(&start);
630 if (msec < 10 || msec > 200) {
631 fprintf(stderr, "Timeout appears incorrect: %lu\n", msec);
632 goto err;
633 }
634
635 close(fds[0]);
636 close(fds[1]);
637 return 0;
638 err:
639 return 1;
640 }
641
test_link_timeout_update_invalid(struct io_uring * ring,int async)642 static int test_link_timeout_update_invalid(struct io_uring *ring, int async)
643 {
644 struct __kernel_timespec ts;
645 struct io_uring_cqe *cqe;
646 struct io_uring_sqe *sqe;
647 int ret;
648
649 ts.tv_sec = 0;
650 ts.tv_nsec = 100000000LL;
651 sqe = io_uring_get_sqe(ring);
652 io_uring_prep_timeout_update(sqe, &ts, 2, IORING_LINK_TIMEOUT_UPDATE);
653 sqe->user_data = 0xcafe0000;
654 if (async)
655 sqe->flags |= IOSQE_ASYNC;
656
657 io_uring_submit(ring);
658
659 ret = io_uring_wait_cqe(ring, &cqe);
660 if (ret < 0) {
661 printf("wait completion %d\n", ret);
662 goto err;
663 }
664 if (cqe->res != -ENOENT) {
665 fprintf(stderr, "bad timeout update: %d\n", cqe->res);
666 goto err;
667 }
668 io_uring_cqe_seen(ring, cqe);
669 return 0;
670 err:
671 return 1;
672 }
673
test_timeout_link_chain1(struct io_uring * ring)674 static int test_timeout_link_chain1(struct io_uring *ring)
675 {
676 struct __kernel_timespec ts;
677 struct io_uring_cqe *cqe;
678 struct io_uring_sqe *sqe;
679 int fds[2], ret, i;
680 struct iovec iov;
681 char buffer[128];
682
683 if (pipe(fds)) {
684 perror("pipe");
685 return 1;
686 }
687
688 sqe = io_uring_get_sqe(ring);
689 if (!sqe) {
690 printf("get sqe failed\n");
691 goto err;
692 }
693 iov.iov_base = buffer;
694 iov.iov_len = sizeof(buffer);
695 io_uring_prep_readv(sqe, fds[0], &iov, 1, 0);
696 sqe->flags |= IOSQE_IO_LINK;
697 sqe->user_data = 1;
698
699 sqe = io_uring_get_sqe(ring);
700 if (!sqe) {
701 printf("get sqe failed\n");
702 goto err;
703 }
704 ts.tv_sec = 0;
705 ts.tv_nsec = 1000000;
706 io_uring_prep_link_timeout(sqe, &ts, 0);
707 sqe->flags |= IOSQE_IO_LINK;
708 sqe->user_data = 2;
709
710 sqe = io_uring_get_sqe(ring);
711 if (!sqe) {
712 printf("get sqe failed\n");
713 goto err;
714 }
715 io_uring_prep_nop(sqe);
716 sqe->user_data = 3;
717
718 ret = io_uring_submit(ring);
719 if (ret != 3) {
720 printf("sqe submit failed: %d\n", ret);
721 goto err;
722 }
723
724 for (i = 0; i < 3; i++) {
725 ret = io_uring_wait_cqe(ring, &cqe);
726 if (ret < 0) {
727 printf("wait completion %d\n", ret);
728 goto err;
729 }
730 switch (cqe->user_data) {
731 case 1:
732 if (cqe->res != -EINTR && cqe->res != -ECANCELED) {
733 fprintf(stderr, "Req %" PRIu64 " got %d\n", (uint64_t) cqe->user_data,
734 cqe->res);
735 goto err;
736 }
737 break;
738 case 2:
739 /* FASTPOLL kernels can cancel successfully */
740 if (cqe->res != -EALREADY && cqe->res != -ETIME) {
741 fprintf(stderr, "Req %" PRIu64 " got %d\n", (uint64_t) cqe->user_data,
742 cqe->res);
743 goto err;
744 }
745 break;
746 case 3:
747 if (cqe->res != -ECANCELED) {
748 fprintf(stderr, "Req %" PRIu64 " got %d\n", (uint64_t) cqe->user_data,
749 cqe->res);
750 goto err;
751 }
752 break;
753 }
754
755 io_uring_cqe_seen(ring, cqe);
756 }
757
758 close(fds[0]);
759 close(fds[1]);
760 return 0;
761 err:
762 return 1;
763 }
764
test_timeout_link_chain2(struct io_uring * ring)765 static int test_timeout_link_chain2(struct io_uring *ring)
766 {
767 struct __kernel_timespec ts;
768 struct io_uring_cqe *cqe;
769 struct io_uring_sqe *sqe;
770 int fds[2], ret, i;
771
772 if (pipe(fds)) {
773 perror("pipe");
774 return 1;
775 }
776
777 sqe = io_uring_get_sqe(ring);
778 if (!sqe) {
779 printf("get sqe failed\n");
780 goto err;
781 }
782 io_uring_prep_poll_add(sqe, fds[0], POLLIN);
783 sqe->flags |= IOSQE_IO_LINK;
784 sqe->user_data = 1;
785
786 sqe = io_uring_get_sqe(ring);
787 if (!sqe) {
788 printf("get sqe failed\n");
789 goto err;
790 }
791 ts.tv_sec = 0;
792 ts.tv_nsec = 1000000;
793 io_uring_prep_link_timeout(sqe, &ts, 0);
794 sqe->flags |= IOSQE_IO_LINK;
795 sqe->user_data = 2;
796
797 sqe = io_uring_get_sqe(ring);
798 if (!sqe) {
799 printf("get sqe failed\n");
800 goto err;
801 }
802 io_uring_prep_nop(sqe);
803 sqe->flags |= IOSQE_IO_LINK;
804 sqe->user_data = 3;
805
806 sqe = io_uring_get_sqe(ring);
807 if (!sqe) {
808 printf("get sqe failed\n");
809 goto err;
810 }
811 io_uring_prep_nop(sqe);
812 sqe->user_data = 4;
813
814 ret = io_uring_submit(ring);
815 if (ret != 4) {
816 printf("sqe submit failed: %d\n", ret);
817 goto err;
818 }
819
820 for (i = 0; i < 4; i++) {
821 ret = io_uring_wait_cqe(ring, &cqe);
822 if (ret < 0) {
823 printf("wait completion %d\n", ret);
824 goto err;
825 }
826 switch (cqe->user_data) {
827 /* poll cancel really should return -ECANCEL... */
828 case 1:
829 if (cqe->res != -ECANCELED) {
830 fprintf(stderr, "Req %" PRIu64 " got %d\n", (uint64_t) cqe->user_data,
831 cqe->res);
832 goto err;
833 }
834 break;
835 case 2:
836 if (cqe->res != -ETIME) {
837 fprintf(stderr, "Req %" PRIu64 " got %d\n", (uint64_t) cqe->user_data,
838 cqe->res);
839 goto err;
840 }
841 break;
842 case 3:
843 case 4:
844 if (cqe->res != -ECANCELED) {
845 fprintf(stderr, "Req %" PRIu64 " got %d\n", (uint64_t) cqe->user_data,
846 cqe->res);
847 goto err;
848 }
849 break;
850 }
851 io_uring_cqe_seen(ring, cqe);
852 }
853
854 close(fds[0]);
855 close(fds[1]);
856 return 0;
857 err:
858 return 1;
859 }
860
test_timeout_link_chain3(struct io_uring * ring)861 static int test_timeout_link_chain3(struct io_uring *ring)
862 {
863 struct __kernel_timespec ts;
864 struct io_uring_cqe *cqe;
865 struct io_uring_sqe *sqe;
866 int fds[2], ret, i;
867
868 if (pipe(fds)) {
869 perror("pipe");
870 return 1;
871 }
872
873 sqe = io_uring_get_sqe(ring);
874 if (!sqe) {
875 printf("get sqe failed\n");
876 goto err;
877 }
878 io_uring_prep_poll_add(sqe, fds[0], POLLIN);
879 sqe->flags |= IOSQE_IO_LINK;
880 sqe->user_data = 1;
881
882 sqe = io_uring_get_sqe(ring);
883 if (!sqe) {
884 printf("get sqe failed\n");
885 goto err;
886 }
887 ts.tv_sec = 0;
888 ts.tv_nsec = 1000000;
889 io_uring_prep_link_timeout(sqe, &ts, 0);
890 sqe->flags |= IOSQE_IO_LINK;
891 sqe->user_data = 2;
892
893 sqe = io_uring_get_sqe(ring);
894 if (!sqe) {
895 printf("get sqe failed\n");
896 goto err;
897 }
898 io_uring_prep_nop(sqe);
899 sqe->flags |= IOSQE_IO_LINK;
900 sqe->user_data = 3;
901
902 /* POLL -> TIMEOUT -> NOP */
903
904 sqe = io_uring_get_sqe(ring);
905 if (!sqe) {
906 printf("get sqe failed\n");
907 goto err;
908 }
909 io_uring_prep_poll_add(sqe, fds[0], POLLIN);
910 sqe->flags |= IOSQE_IO_LINK;
911 sqe->user_data = 4;
912
913 sqe = io_uring_get_sqe(ring);
914 if (!sqe) {
915 printf("get sqe failed\n");
916 goto err;
917 }
918 ts.tv_sec = 0;
919 ts.tv_nsec = 1000000;
920 io_uring_prep_link_timeout(sqe, &ts, 0);
921 sqe->user_data = 5;
922
923 /* poll on pipe + timeout */
924
925 sqe = io_uring_get_sqe(ring);
926 if (!sqe) {
927 printf("get sqe failed\n");
928 goto err;
929 }
930 io_uring_prep_nop(sqe);
931 sqe->user_data = 6;
932
933 /* nop */
934
935 ret = io_uring_submit(ring);
936 if (ret != 6) {
937 printf("sqe submit failed: %d\n", ret);
938 goto err;
939 }
940
941 for (i = 0; i < 6; i++) {
942 ret = io_uring_wait_cqe(ring, &cqe);
943 if (ret < 0) {
944 printf("wait completion %d\n", ret);
945 goto err;
946 }
947 switch (cqe->user_data) {
948 case 2:
949 if (cqe->res != -ETIME) {
950 fprintf(stderr, "Req %" PRIu64 " got %d\n", (uint64_t) cqe->user_data,
951 cqe->res);
952 goto err;
953 }
954 break;
955 case 1:
956 case 3:
957 case 4:
958 case 5:
959 if (cqe->res != -ECANCELED) {
960 fprintf(stderr, "Req %" PRIu64 " got %d\n", (uint64_t) cqe->user_data,
961 cqe->res);
962 goto err;
963 }
964 break;
965 case 6:
966 if (cqe->res) {
967 fprintf(stderr, "Req %" PRIu64 " got %d\n", (uint64_t) cqe->user_data,
968 cqe->res);
969 goto err;
970 }
971 break;
972 }
973 io_uring_cqe_seen(ring, cqe);
974 }
975
976 close(fds[0]);
977 close(fds[1]);
978 return 0;
979 err:
980 return 1;
981 }
982
test_timeout_link_chain4(struct io_uring * ring)983 static int test_timeout_link_chain4(struct io_uring *ring)
984 {
985 struct __kernel_timespec ts;
986 struct io_uring_cqe *cqe;
987 struct io_uring_sqe *sqe;
988 int fds[2], ret, i;
989
990 if (pipe(fds)) {
991 perror("pipe");
992 return 1;
993 }
994
995 sqe = io_uring_get_sqe(ring);
996 if (!sqe) {
997 printf("get sqe failed\n");
998 goto err;
999 }
1000 io_uring_prep_nop(sqe);
1001 sqe->flags |= IOSQE_IO_LINK;
1002 sqe->user_data = 1;
1003
1004 sqe = io_uring_get_sqe(ring);
1005 if (!sqe) {
1006 printf("get sqe failed\n");
1007 goto err;
1008 }
1009 io_uring_prep_poll_add(sqe, fds[0], POLLIN);
1010 sqe->flags |= IOSQE_IO_LINK;
1011 sqe->user_data = 2;
1012
1013 sqe = io_uring_get_sqe(ring);
1014 if (!sqe) {
1015 printf("get sqe failed\n");
1016 goto err;
1017 }
1018 ts.tv_sec = 0;
1019 ts.tv_nsec = 1000000;
1020 io_uring_prep_link_timeout(sqe, &ts, 0);
1021 sqe->user_data = 3;
1022
1023 ret = io_uring_submit(ring);
1024 if (ret != 3) {
1025 printf("sqe submit failed: %d\n", ret);
1026 goto err;
1027 }
1028
1029 for (i = 0; i < 3; i++) {
1030 ret = io_uring_wait_cqe(ring, &cqe);
1031 if (ret < 0) {
1032 printf("wait completion %d\n", ret);
1033 goto err;
1034 }
1035 switch (cqe->user_data) {
1036 /* poll cancel really should return -ECANCEL... */
1037 case 1:
1038 if (cqe->res) {
1039 fprintf(stderr, "Req %" PRIu64 " got %d\n", (uint64_t) cqe->user_data,
1040 cqe->res);
1041 goto err;
1042 }
1043 break;
1044 case 2:
1045 if (cqe->res != -ECANCELED) {
1046 fprintf(stderr, "Req %" PRIu64 " got %d\n", (uint64_t) cqe->user_data,
1047 cqe->res);
1048 goto err;
1049 }
1050 break;
1051 case 3:
1052 if (cqe->res != -ETIME) {
1053 fprintf(stderr, "Req %" PRIu64 " got %d\n", (uint64_t) cqe->user_data,
1054 cqe->res);
1055 goto err;
1056 }
1057 break;
1058 }
1059 io_uring_cqe_seen(ring, cqe);
1060 }
1061
1062 close(fds[0]);
1063 close(fds[1]);
1064 return 0;
1065 err:
1066 return 1;
1067 }
1068
test_timeout_link_chain5(struct io_uring * ring)1069 static int test_timeout_link_chain5(struct io_uring *ring)
1070 {
1071 struct __kernel_timespec ts1, ts2;
1072 struct io_uring_cqe *cqe;
1073 struct io_uring_sqe *sqe;
1074 int ret, i;
1075
1076 sqe = io_uring_get_sqe(ring);
1077 if (!sqe) {
1078 printf("get sqe failed\n");
1079 goto err;
1080 }
1081 io_uring_prep_nop(sqe);
1082 sqe->flags |= IOSQE_IO_LINK;
1083 sqe->user_data = 1;
1084
1085 sqe = io_uring_get_sqe(ring);
1086 if (!sqe) {
1087 printf("get sqe failed\n");
1088 goto err;
1089 }
1090 ts1.tv_sec = 1;
1091 ts1.tv_nsec = 0;
1092 io_uring_prep_link_timeout(sqe, &ts1, 0);
1093 sqe->flags |= IOSQE_IO_LINK;
1094 sqe->user_data = 2;
1095
1096 sqe = io_uring_get_sqe(ring);
1097 if (!sqe) {
1098 printf("get sqe failed\n");
1099 goto err;
1100 }
1101 ts2.tv_sec = 2;
1102 ts2.tv_nsec = 0;
1103 io_uring_prep_link_timeout(sqe, &ts2, 0);
1104 sqe->user_data = 3;
1105
1106 ret = io_uring_submit(ring);
1107 if (ret != 3) {
1108 printf("sqe submit failed: %d\n", ret);
1109 goto err;
1110 }
1111
1112 for (i = 0; i < 3; i++) {
1113 ret = io_uring_wait_cqe(ring, &cqe);
1114 if (ret < 0) {
1115 printf("wait completion %d\n", ret);
1116 goto err;
1117 }
1118 switch (cqe->user_data) {
1119 case 1:
1120 case 2:
1121 if (cqe->res && cqe->res != -ECANCELED) {
1122 fprintf(stderr, "Request got %d, wanted -EINVAL "
1123 "or -ECANCELED\n",
1124 cqe->res);
1125 goto err;
1126 }
1127 break;
1128 case 3:
1129 if (cqe->res != -ECANCELED && cqe->res != -EINVAL) {
1130 fprintf(stderr, "Link timeout got %d, wanted -ECANCELED\n", cqe->res);
1131 goto err;
1132 }
1133 break;
1134 }
1135 io_uring_cqe_seen(ring, cqe);
1136 }
1137
1138 return 0;
1139 err:
1140 return 1;
1141 }
1142
main(int argc,char * argv[])1143 int main(int argc, char *argv[])
1144 {
1145 struct io_uring ring;
1146 int ret;
1147
1148 if (argc > 1)
1149 return T_EXIT_SKIP;
1150
1151 ret = io_uring_queue_init(8, &ring, 0);
1152 if (ret) {
1153 printf("ring setup failed\n");
1154 return T_EXIT_FAIL;
1155 }
1156
1157 ret = test_timeout_link_chain1(&ring);
1158 if (ret) {
1159 printf("test_single_link_chain1 failed\n");
1160 return ret;
1161 }
1162
1163 ret = test_timeout_link_chain2(&ring);
1164 if (ret) {
1165 printf("test_single_link_chain2 failed\n");
1166 return ret;
1167 }
1168
1169 ret = test_timeout_link_chain3(&ring);
1170 if (ret) {
1171 printf("test_single_link_chain3 failed\n");
1172 return ret;
1173 }
1174
1175 ret = test_timeout_link_chain4(&ring);
1176 if (ret) {
1177 printf("test_single_link_chain4 failed\n");
1178 return ret;
1179 }
1180
1181 ret = test_timeout_link_chain5(&ring);
1182 if (ret) {
1183 printf("test_single_link_chain5 failed\n");
1184 return ret;
1185 }
1186
1187 ret = test_single_link_timeout(&ring, 10);
1188 if (ret) {
1189 printf("test_single_link_timeout 10 failed\n");
1190 return ret;
1191 }
1192
1193 ret = test_single_link_timeout(&ring, 100000ULL);
1194 if (ret) {
1195 printf("test_single_link_timeout 100000 failed\n");
1196 return ret;
1197 }
1198
1199 ret = test_single_link_timeout(&ring, 500000000ULL);
1200 if (ret) {
1201 printf("test_single_link_timeout 500000000 failed\n");
1202 return ret;
1203 }
1204
1205 ret = test_single_link_no_timeout(&ring);
1206 if (ret) {
1207 printf("test_single_link_no_timeout failed\n");
1208 return ret;
1209 }
1210
1211 ret = test_single_link_timeout_error(&ring);
1212 if (ret) {
1213 printf("test_single_link_timeout_error failed\n");
1214 return ret;
1215 }
1216
1217 ret = test_single_link_timeout_nop(&ring);
1218 if (ret) {
1219 printf("test_single_link_timeout_nop failed\n");
1220 return ret;
1221 }
1222
1223 ret = test_single_link_timeout_ception(&ring);
1224 if (ret) {
1225 printf("test_single_link_timeout_ception failed\n");
1226 return ret;
1227 }
1228
1229 ret = test_fail_lone_link_timeouts(&ring);
1230 if (ret) {
1231 printf("test_fail_lone_link_timeouts failed\n");
1232 return ret;
1233 }
1234
1235 ret = test_fail_two_link_timeouts(&ring);
1236 if (ret) {
1237 printf("test_fail_two_link_timeouts failed\n");
1238 return ret;
1239 }
1240
1241 ret = test_link_timeout_update(&ring, 0);
1242 if (ret) {
1243 printf("test_link_timeout_update 0 failed\n");
1244 return ret;
1245 }
1246
1247 ret = test_link_timeout_update(&ring, 1);
1248 if (ret) {
1249 printf("test_link_timeout_update 1 failed\n");
1250 return ret;
1251 }
1252
1253 ret = test_link_timeout_update_invalid(&ring, 0);
1254 if (ret) {
1255 printf("test_link_timeout_update_invalid 0 failed\n");
1256 return ret;
1257 }
1258
1259 ret = test_link_timeout_update_invalid(&ring, 1);
1260 if (ret) {
1261 printf("test_link_timeout_update_invalid 1 failed\n");
1262 return ret;
1263 }
1264
1265
1266 return T_EXIT_PASS;
1267 }
1268