• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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