• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: MIT */
2 /*
3  * Description: run various nop 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 
13 #include "liburing.h"
14 #include "test.h"
15 
16 static int seq;
17 
test_nop_inject(struct io_uring * ring,unsigned req_flags)18 static int test_nop_inject(struct io_uring *ring, unsigned req_flags)
19 {
20 	struct io_uring_cqe *cqe;
21 	struct io_uring_sqe *sqe;
22 	int ret;
23 
24 	sqe = io_uring_get_sqe(ring);
25 	if (!sqe) {
26 		fprintf(stderr, "get sqe failed\n");
27 		goto err;
28 	}
29 
30 	io_uring_prep_nop(sqe);
31 	sqe->user_data = ++seq;
32 	sqe->nop_flags = IORING_NOP_INJECT_RESULT;
33 	sqe->flags |= req_flags;
34 	sqe->len = -EFAULT;
35 
36 	ret = io_uring_submit(ring);
37 	if (ret <= 0) {
38 		fprintf(stderr, "sqe submit failed: %d\n", ret);
39 		goto err;
40 	}
41 
42 	ret = io_uring_wait_cqe(ring, &cqe);
43 	if (ret < 0) {
44 		fprintf(stderr, "wait completion %d\n", ret);
45 		goto err;
46 	}
47 	if (cqe->res != -EINVAL && cqe->res != -EFAULT) {
48 		fprintf(stderr, "expected injected result, got %d\n", cqe->res);
49 		goto err;
50 	}
51 	io_uring_cqe_seen(ring, cqe);
52 	return 0;
53 err:
54 	return 1;
55 }
56 
test_single_nop(struct io_uring * ring,unsigned req_flags)57 static int test_single_nop(struct io_uring *ring, unsigned req_flags)
58 {
59 	struct io_uring_cqe *cqe;
60 	struct io_uring_sqe *sqe;
61 	int ret;
62 	bool cqe32 = (ring->flags & IORING_SETUP_CQE32);
63 
64 	sqe = io_uring_get_sqe(ring);
65 	if (!sqe) {
66 		fprintf(stderr, "get sqe failed\n");
67 		goto err;
68 	}
69 
70 	io_uring_prep_nop(sqe);
71 	sqe->user_data = ++seq;
72 	sqe->flags |= req_flags;
73 
74 	ret = io_uring_submit(ring);
75 	if (ret <= 0) {
76 		fprintf(stderr, "sqe submit failed: %d\n", ret);
77 		goto err;
78 	}
79 
80 	ret = io_uring_wait_cqe(ring, &cqe);
81 	if (ret < 0) {
82 		fprintf(stderr, "wait completion %d\n", ret);
83 		goto err;
84 	}
85 	if (!cqe->user_data) {
86 		fprintf(stderr, "Unexpected 0 user_data\n");
87 		goto err;
88 	}
89 	if (cqe32) {
90 		if (cqe->big_cqe[0] != 0) {
91 			fprintf(stderr, "Unexpected extra1\n");
92 			goto err;
93 
94 		}
95 		if (cqe->big_cqe[1] != 0) {
96 			fprintf(stderr, "Unexpected extra2\n");
97 			goto err;
98 		}
99 	}
100 	io_uring_cqe_seen(ring, cqe);
101 	return 0;
102 err:
103 	return 1;
104 }
105 
test_barrier_nop(struct io_uring * ring,unsigned req_flags)106 static int test_barrier_nop(struct io_uring *ring, unsigned req_flags)
107 {
108 	struct io_uring_cqe *cqe;
109 	struct io_uring_sqe *sqe;
110 	int ret, i;
111 	bool cqe32 = (ring->flags & IORING_SETUP_CQE32);
112 
113 	for (i = 0; i < 8; i++) {
114 		sqe = io_uring_get_sqe(ring);
115 		if (!sqe) {
116 			fprintf(stderr, "get sqe failed\n");
117 			goto err;
118 		}
119 
120 		io_uring_prep_nop(sqe);
121 		if (i == 4)
122 			sqe->flags = IOSQE_IO_DRAIN;
123 		sqe->user_data = ++seq;
124 		sqe->flags |= req_flags;
125 	}
126 
127 	ret = io_uring_submit(ring);
128 	if (ret < 0) {
129 		fprintf(stderr, "sqe submit failed: %d\n", ret);
130 		goto err;
131 	} else if (ret < 8) {
132 		fprintf(stderr, "Submitted only %d\n", ret);
133 		goto err;
134 	}
135 
136 	for (i = 0; i < 8; i++) {
137 		ret = io_uring_wait_cqe(ring, &cqe);
138 		if (ret < 0) {
139 			fprintf(stderr, "wait completion %d\n", ret);
140 			goto err;
141 		}
142 		if (!cqe->user_data) {
143 			fprintf(stderr, "Unexpected 0 user_data\n");
144 			goto err;
145 		}
146 		if (cqe32) {
147 			if (cqe->big_cqe[0] != 0) {
148 				fprintf(stderr, "Unexpected extra1\n");
149 				goto err;
150 			}
151 			if (cqe->big_cqe[1] != 0) {
152 				fprintf(stderr, "Unexpected extra2\n");
153 				goto err;
154 			}
155 		}
156 		io_uring_cqe_seen(ring, cqe);
157 	}
158 
159 	return 0;
160 err:
161 	return 1;
162 }
163 
test_ring(unsigned flags)164 static int test_ring(unsigned flags)
165 {
166 	struct io_uring ring;
167 	struct io_uring_params p = { };
168 	int ret, i;
169 
170 	p.flags = flags;
171 	ret = io_uring_queue_init_params(8, &ring, &p);
172 	if (ret) {
173 		if (ret == -EINVAL)
174 			return 0;
175 		fprintf(stderr, "ring setup failed: %d\n", ret);
176 		return 1;
177 	}
178 
179 	for (i = 0; i < 1000; i++) {
180 		unsigned req_flags = (i & 1) ? IOSQE_ASYNC : 0;
181 
182 		ret = test_single_nop(&ring, req_flags);
183 		if (ret) {
184 			fprintf(stderr, "test_single_nop failed\n");
185 			goto err;
186 		}
187 
188 		ret = test_barrier_nop(&ring, req_flags);
189 		if (ret) {
190 			fprintf(stderr, "test_barrier_nop failed\n");
191 			goto err;
192 		}
193 		ret = test_nop_inject(&ring, req_flags);
194 		if (ret) {
195 			fprintf(stderr, "test_nop_inject failed\n");
196 			goto err;
197 		}
198 	}
199 err:
200 	io_uring_queue_exit(&ring);
201 	return ret;
202 }
203 
main(int argc,char * argv[])204 int main(int argc, char *argv[])
205 {
206 	int ret;
207 
208 	if (argc > 1)
209 		return 0;
210 
211 	FOR_ALL_TEST_CONFIGS {
212 		ret = test_ring(IORING_GET_TEST_CONFIG_FLAGS());
213 		if (ret) {
214 			fprintf(stderr, "Normal ring test failed: %s\n",
215 					IORING_GET_TEST_CONFIG_DESCRIPTION());
216 			return ret;
217 		}
218 	}
219 
220 	return 0;
221 }
222