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