• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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