1 /* SPDX-License-Identifier: MIT */
2 /*
3 * Description: test that the app can always get a new sqe after having
4 * called io_uring_sqring_wait().
5 *
6 */
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10
11 #include "liburing.h"
12 #include "helpers.h"
13
14 #define NR_IOS 10000
15 #define INFLIGHT 256
16 #define FILE_SIZE (256 * 1024 * 1024)
17
18 static int inflight;
19
reap(struct io_uring * ring)20 static int reap(struct io_uring *ring)
21 {
22 struct io_uring_cqe *cqe;
23 int ret;
24
25 while (inflight >= INFLIGHT / 2) {
26 ret = io_uring_wait_cqe(ring, &cqe);
27 if (ret < 0) {
28 fprintf(stderr, "wait=%d\n", ret);
29 return 1;
30 }
31 if (cqe->res < 0) {
32 printf("cqe res %d\n", cqe->res);
33 return 1;
34 }
35 io_uring_cqe_seen(ring, cqe);
36 inflight--;
37 }
38
39 return 0;
40 }
41
main(int argc,char * argv[])42 int main(int argc, char *argv[])
43 {
44 struct io_uring_sqe *sqe;
45 struct io_uring ring;
46 int fd = -1, i, iov_off, ret, fret;
47 struct iovec iovs[INFLIGHT];
48 const char *fname;
49 char buf[256];
50 loff_t off;
51
52 if (argc > 1) {
53 fname = argv[1];
54 } else {
55 srand((unsigned)time(NULL));
56 snprintf(buf, sizeof(buf), ".sqwait-%u-%u", (unsigned)rand(),
57 (unsigned)getpid());
58 fname = buf;
59 t_create_file(fname, FILE_SIZE);
60 }
61
62 fret = T_EXIT_SKIP;
63 ret = io_uring_queue_init(8, &ring, IORING_SETUP_SQPOLL);
64 if (ret < 0) {
65 if (errno == EINVAL || errno == EPERM)
66 goto err;
67 fprintf(stderr, "queue init %d\n", ret);
68 fret = T_EXIT_FAIL;
69 goto err;
70 }
71
72 fd = open(fname, O_RDONLY | O_DIRECT);
73 if (fd < 0) {
74 if (errno == EACCES || errno == EPERM || errno == EINVAL)
75 return T_EXIT_SKIP;
76 perror("open");
77 fret = T_EXIT_FAIL;
78 goto err;
79 }
80
81 for (i = 0; i < INFLIGHT; i++) {
82 if (posix_memalign(&iovs[i].iov_base, 4096, 4096))
83 goto err;
84 iovs[i].iov_len = 4096;
85 }
86
87 iov_off = off = 0;
88 for (i = 0; i < NR_IOS; i++) {
89 struct iovec *iov = &iovs[iov_off];
90
91 sqe = io_uring_get_sqe(&ring);
92 if (!sqe) {
93 ret = io_uring_sqring_wait(&ring);
94 if (ret < 0) {
95 if (ret == -EINVAL)
96 return T_EXIT_SKIP;
97 fprintf(stderr, "sqwait=%d\n", ret);
98 fret = T_EXIT_FAIL;
99 goto err;
100 }
101 sqe = io_uring_get_sqe(&ring);
102 if (!sqe) {
103 fprintf(stderr, "No sqe post wait\n");
104 fret = T_EXIT_FAIL;
105 goto err;
106 }
107 }
108 io_uring_prep_read(sqe, fd, iov->iov_base, iov->iov_len, 0);
109 io_uring_submit(&ring);
110 inflight++;
111
112 iov_off++;
113 if (iov_off == INFLIGHT)
114 iov_off = 0;
115 off += 8192;
116 if (off > FILE_SIZE - 8192)
117 off = 0;
118 if (reap(&ring)) {
119 fret = T_EXIT_FAIL;
120 goto err;
121 }
122 }
123
124 if (fd != -1)
125 close(fd);
126 if (fname != argv[1])
127 unlink(fname);
128 io_uring_queue_exit(&ring);
129 return T_EXIT_PASS;
130 err:
131 if (fd != -1)
132 close(fd);
133 if (fname != argv[1])
134 unlink(fname);
135 return fret;
136 }
137