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)52 static int test(int nentries)
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 if (ret == -EINVAL) {
61 no_mmap = 1;
62 return T_EXIT_SKIP;
63 } else if (ret == -ENOMEM) {
64 fprintf(stdout, "Enable huge pages to test big rings\n");
65 return T_EXIT_SKIP;
66 } else if (ret) {
67 fprintf(stderr, "ring setup failed\n");
68 return T_EXIT_FAIL;
69 }
70
71 ret = io_uring_register_ring_fd(&ring);
72 if (ret != -EEXIST) {
73 fprintf(stderr, "registering already-registered ring fd should fail\n");
74 goto err;
75 }
76
77 ret = io_uring_close_ring_fd(&ring);
78 if (ret != -EBADF) {
79 fprintf(stderr, "closing already-closed ring fd should fail\n");
80 goto err;
81 }
82
83 /* Test a simple io_uring_register operation expected to work.
84 * io_uring_register_iowq_max_workers is arbitrary.
85 */
86 values[0] = values[1] = 0;
87 ret = io_uring_register_iowq_max_workers(&ring, values);
88 if (ret || (values[0] == 0 && values[1] == 0)) {
89 fprintf(stderr, "io_uring_register operation failed after closing ring fd\n");
90 goto err;
91 }
92
93 ret = test_nops(&ring, nentries, nentries * 4);
94 if (ret)
95 goto err;
96
97 io_uring_queue_exit(&ring);
98 return T_EXIT_PASS;
99
100 err:
101 io_uring_queue_exit(&ring);
102 return T_EXIT_FAIL;
103 }
104
main(int argc,char * argv[])105 int main(int argc, char *argv[])
106 {
107 int ret;
108
109 if (argc > 1)
110 return T_EXIT_SKIP;
111
112 /* test single normal page */
113 ret = test(NORMAL_PAGE_ENTRIES);
114 if (ret == T_EXIT_SKIP || no_mmap) {
115 return T_EXIT_SKIP;
116 } else if (ret != T_EXIT_PASS) {
117 fprintf(stderr, "test 8 failed\n");
118 return T_EXIT_FAIL;
119 }
120
121 /* test with entries requiring a huge page */
122 ret = test(HUGE_PAGE_ENTRIES);
123 if (ret == T_EXIT_SKIP) {
124 return T_EXIT_SKIP;
125 } else if (ret != T_EXIT_PASS) {
126 fprintf(stderr, "test 512 failed\n");
127 return T_EXIT_FAIL;
128 }
129
130 return T_EXIT_PASS;
131 }
132