1 /* SPDX-License-Identifier: MIT */
2 /*
3 * Test io_uring_setup with IORING_SETUP_REGISTERED_FD_ONLY
4 *
5 */
6 #include <stdio.h>
7
8 #include "helpers.h"
9
10 #define NORMAL_PAGE_ENTRIES 8
11 #define HUGE_PAGE_ENTRIES 512
12
13 static int no_mmap;
14
test_nops(struct io_uring * ring,int sq_size,int nr_nops)15 static int test_nops(struct io_uring *ring, int sq_size, int nr_nops)
16 {
17 struct io_uring_sqe *sqe;
18 struct io_uring_cqe *cqe;
19 int i, ret;
20
21 do {
22 int todo = nr_nops;
23
24 if (todo > sq_size)
25 todo = sq_size;
26
27 for (i = 0; i < todo; i++) {
28 sqe = io_uring_get_sqe(ring);
29 io_uring_prep_nop(sqe);
30 }
31
32 ret = io_uring_submit(ring);
33 if (ret != todo) {
34 fprintf(stderr, "short submit %d\n", ret);
35 return T_EXIT_FAIL;
36 }
37
38 for (i = 0; i < todo; i++) {
39 ret = io_uring_wait_cqe(ring, &cqe);
40 if (ret) {
41 fprintf(stderr, "wait err %d\n", ret);
42 return T_EXIT_FAIL;
43 }
44 io_uring_cqe_seen(ring, cqe);
45 }
46 nr_nops -= todo;
47 } while (nr_nops);
48
49 return T_EXIT_PASS;
50 }
51
test(int nentries,int ring_flags)52 static int test(int nentries, int ring_flags)
53 {
54 struct io_uring ring;
55 unsigned values[2];
56 int ret;
57
58 ret = io_uring_queue_init(nentries, &ring,
59 IORING_SETUP_REGISTERED_FD_ONLY | IORING_SETUP_NO_MMAP |
60 ring_flags);
61 if (ret == -EINVAL) {
62 no_mmap = 1;
63 return T_EXIT_SKIP;
64 } else if (ret == -ENOMEM) {
65 fprintf(stdout, "Enable huge pages to test big rings\n");
66 return T_EXIT_SKIP;
67 } else if (ret) {
68 fprintf(stderr, "ring setup failed: %d\n", ret);
69 return T_EXIT_FAIL;
70 }
71
72 ret = io_uring_register_ring_fd(&ring);
73 if (ret != -EEXIST) {
74 fprintf(stderr, "registering already-registered ring fd should fail\n");
75 goto err;
76 }
77
78 ret = io_uring_close_ring_fd(&ring);
79 if (ret != -EBADF) {
80 fprintf(stderr, "closing already-closed ring fd should fail\n");
81 goto err;
82 }
83
84 /* Test a simple io_uring_register operation expected to work.
85 * io_uring_register_iowq_max_workers is arbitrary.
86 */
87 values[0] = values[1] = 0;
88 ret = io_uring_register_iowq_max_workers(&ring, values);
89 if (ret || (values[0] == 0 && values[1] == 0)) {
90 fprintf(stderr, "io_uring_register operation failed after closing ring fd\n");
91 goto err;
92 }
93
94 ret = test_nops(&ring, nentries, nentries * 4);
95 if (ret)
96 goto err;
97
98 io_uring_queue_exit(&ring);
99 return T_EXIT_PASS;
100
101 err:
102 io_uring_queue_exit(&ring);
103 return T_EXIT_FAIL;
104 }
105
main(int argc,char * argv[])106 int main(int argc, char *argv[])
107 {
108 int ret;
109
110 if (argc > 1)
111 return T_EXIT_SKIP;
112
113 /* test single normal page */
114 ret = test(NORMAL_PAGE_ENTRIES, 0);
115 if (ret == T_EXIT_SKIP || no_mmap) {
116 return T_EXIT_SKIP;
117 } else if (ret != T_EXIT_PASS) {
118 fprintf(stderr, "test 8 failed\n");
119 return T_EXIT_FAIL;
120 }
121
122 /* test single normal page */
123 ret = test(NORMAL_PAGE_ENTRIES, IORING_SETUP_SQPOLL);
124 if (ret == T_EXIT_SKIP || no_mmap) {
125 return T_EXIT_SKIP;
126 } else if (ret != T_EXIT_PASS) {
127 fprintf(stderr, "test 8 failed\n");
128 return T_EXIT_FAIL;
129 }
130
131 /* test with entries requiring a huge page */
132 ret = test(HUGE_PAGE_ENTRIES, 0);
133 if (ret == T_EXIT_SKIP) {
134 return T_EXIT_SKIP;
135 } else if (ret != T_EXIT_PASS) {
136 fprintf(stderr, "test 512 failed\n");
137 return T_EXIT_FAIL;
138 }
139
140 return T_EXIT_PASS;
141 }
142