• 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)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