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_single_nop(struct io_uring * ring,unsigned req_flags)18 static int test_single_nop(struct io_uring *ring, unsigned req_flags)
19 {
20 struct io_uring_cqe *cqe;
21 struct io_uring_sqe *sqe;
22 int ret;
23 bool cqe32 = (ring->flags & IORING_SETUP_CQE32);
24
25 sqe = io_uring_get_sqe(ring);
26 if (!sqe) {
27 fprintf(stderr, "get sqe failed\n");
28 goto err;
29 }
30
31 io_uring_prep_nop(sqe);
32 sqe->user_data = ++seq;
33 sqe->flags |= req_flags;
34
35 ret = io_uring_submit(ring);
36 if (ret <= 0) {
37 fprintf(stderr, "sqe submit failed: %d\n", ret);
38 goto err;
39 }
40
41 ret = io_uring_wait_cqe(ring, &cqe);
42 if (ret < 0) {
43 fprintf(stderr, "wait completion %d\n", ret);
44 goto err;
45 }
46 if (!cqe->user_data) {
47 fprintf(stderr, "Unexpected 0 user_data\n");
48 goto err;
49 }
50 if (cqe32) {
51 if (cqe->big_cqe[0] != 0) {
52 fprintf(stderr, "Unexpected extra1\n");
53 goto err;
54
55 }
56 if (cqe->big_cqe[1] != 0) {
57 fprintf(stderr, "Unexpected extra2\n");
58 goto err;
59 }
60 }
61 io_uring_cqe_seen(ring, cqe);
62 return 0;
63 err:
64 return 1;
65 }
66
test_barrier_nop(struct io_uring * ring,unsigned req_flags)67 static int test_barrier_nop(struct io_uring *ring, unsigned req_flags)
68 {
69 struct io_uring_cqe *cqe;
70 struct io_uring_sqe *sqe;
71 int ret, i;
72 bool cqe32 = (ring->flags & IORING_SETUP_CQE32);
73
74 for (i = 0; i < 8; i++) {
75 sqe = io_uring_get_sqe(ring);
76 if (!sqe) {
77 fprintf(stderr, "get sqe failed\n");
78 goto err;
79 }
80
81 io_uring_prep_nop(sqe);
82 if (i == 4)
83 sqe->flags = IOSQE_IO_DRAIN;
84 sqe->user_data = ++seq;
85 sqe->flags |= req_flags;
86 }
87
88 ret = io_uring_submit(ring);
89 if (ret < 0) {
90 fprintf(stderr, "sqe submit failed: %d\n", ret);
91 goto err;
92 } else if (ret < 8) {
93 fprintf(stderr, "Submitted only %d\n", ret);
94 goto err;
95 }
96
97 for (i = 0; i < 8; i++) {
98 ret = io_uring_wait_cqe(ring, &cqe);
99 if (ret < 0) {
100 fprintf(stderr, "wait completion %d\n", ret);
101 goto err;
102 }
103 if (!cqe->user_data) {
104 fprintf(stderr, "Unexpected 0 user_data\n");
105 goto err;
106 }
107 if (cqe32) {
108 if (cqe->big_cqe[0] != 0) {
109 fprintf(stderr, "Unexpected extra1\n");
110 goto err;
111 }
112 if (cqe->big_cqe[1] != 0) {
113 fprintf(stderr, "Unexpected extra2\n");
114 goto err;
115 }
116 }
117 io_uring_cqe_seen(ring, cqe);
118 }
119
120 return 0;
121 err:
122 return 1;
123 }
124
test_ring(unsigned flags)125 static int test_ring(unsigned flags)
126 {
127 struct io_uring ring;
128 struct io_uring_params p = { };
129 int ret, i;
130
131 p.flags = flags;
132 ret = io_uring_queue_init_params(8, &ring, &p);
133 if (ret) {
134 if (ret == -EINVAL)
135 return 0;
136 fprintf(stderr, "ring setup failed: %d\n", ret);
137 return 1;
138 }
139
140 for (i = 0; i < 1000; i++) {
141 unsigned req_flags = (i & 1) ? IOSQE_ASYNC : 0;
142
143 ret = test_single_nop(&ring, req_flags);
144 if (ret) {
145 fprintf(stderr, "test_single_nop failed\n");
146 goto err;
147 }
148
149 ret = test_barrier_nop(&ring, req_flags);
150 if (ret) {
151 fprintf(stderr, "test_barrier_nop failed\n");
152 goto err;
153 }
154 }
155 err:
156 io_uring_queue_exit(&ring);
157 return ret;
158 }
159
main(int argc,char * argv[])160 int main(int argc, char *argv[])
161 {
162 int ret;
163
164 if (argc > 1)
165 return 0;
166
167 FOR_ALL_TEST_CONFIGS {
168 ret = test_ring(IORING_GET_TEST_CONFIG_FLAGS());
169 if (ret) {
170 fprintf(stderr, "Normal ring test failed: %s\n",
171 IORING_GET_TEST_CONFIG_DESCRIPTION());
172 return ret;
173 }
174 }
175
176 return 0;
177 }
178