xref: /aosp_15_r20/external/liburing/test/io_uring_register.c (revision 25da2bea747f3a93b4c30fd9708b0618ef55a0e6)
1*25da2beaSAndroid Build Coastguard Worker /* SPDX-License-Identifier: MIT */
2*25da2beaSAndroid Build Coastguard Worker /*
3*25da2beaSAndroid Build Coastguard Worker  * io_uring_register.c
4*25da2beaSAndroid Build Coastguard Worker  *
5*25da2beaSAndroid Build Coastguard Worker  * Description: Unit tests for the io_uring_register system call.
6*25da2beaSAndroid Build Coastguard Worker  *
7*25da2beaSAndroid Build Coastguard Worker  * Copyright 2019, Red Hat, Inc.
8*25da2beaSAndroid Build Coastguard Worker  * Author: Jeff Moyer <[email protected]>
9*25da2beaSAndroid Build Coastguard Worker  */
10*25da2beaSAndroid Build Coastguard Worker #include <stdio.h>
11*25da2beaSAndroid Build Coastguard Worker #include <fcntl.h>
12*25da2beaSAndroid Build Coastguard Worker #include <string.h>
13*25da2beaSAndroid Build Coastguard Worker #include <stdlib.h>
14*25da2beaSAndroid Build Coastguard Worker #include <unistd.h>
15*25da2beaSAndroid Build Coastguard Worker #include <errno.h>
16*25da2beaSAndroid Build Coastguard Worker #include <sys/sysinfo.h>
17*25da2beaSAndroid Build Coastguard Worker #include <poll.h>
18*25da2beaSAndroid Build Coastguard Worker #include <assert.h>
19*25da2beaSAndroid Build Coastguard Worker #include <sys/uio.h>
20*25da2beaSAndroid Build Coastguard Worker #include <sys/mman.h>
21*25da2beaSAndroid Build Coastguard Worker #include <linux/mman.h>
22*25da2beaSAndroid Build Coastguard Worker #include <sys/time.h>
23*25da2beaSAndroid Build Coastguard Worker #include <sys/resource.h>
24*25da2beaSAndroid Build Coastguard Worker #include <limits.h>
25*25da2beaSAndroid Build Coastguard Worker 
26*25da2beaSAndroid Build Coastguard Worker #include "helpers.h"
27*25da2beaSAndroid Build Coastguard Worker #include "liburing.h"
28*25da2beaSAndroid Build Coastguard Worker #include "../src/syscall.h"
29*25da2beaSAndroid Build Coastguard Worker 
30*25da2beaSAndroid Build Coastguard Worker static int pagesize;
31*25da2beaSAndroid Build Coastguard Worker static rlim_t mlock_limit;
32*25da2beaSAndroid Build Coastguard Worker static int devnull;
33*25da2beaSAndroid Build Coastguard Worker 
34*25da2beaSAndroid Build Coastguard Worker #if !defined(CONFIG_HAVE_MEMFD_CREATE)
35*25da2beaSAndroid Build Coastguard Worker #include <sys/syscall.h>
36*25da2beaSAndroid Build Coastguard Worker #include <linux/memfd.h>
37*25da2beaSAndroid Build Coastguard Worker 
memfd_create(const char * name,unsigned int flags)38*25da2beaSAndroid Build Coastguard Worker static int memfd_create(const char *name, unsigned int flags)
39*25da2beaSAndroid Build Coastguard Worker {
40*25da2beaSAndroid Build Coastguard Worker 	return (int)syscall(SYS_memfd_create, name, flags);
41*25da2beaSAndroid Build Coastguard Worker }
42*25da2beaSAndroid Build Coastguard Worker #endif
43*25da2beaSAndroid Build Coastguard Worker 
44*25da2beaSAndroid Build Coastguard Worker 
expect_fail(int fd,unsigned int opcode,void * arg,unsigned int nr_args,int error)45*25da2beaSAndroid Build Coastguard Worker static int expect_fail(int fd, unsigned int opcode, void *arg,
46*25da2beaSAndroid Build Coastguard Worker 	    unsigned int nr_args, int error)
47*25da2beaSAndroid Build Coastguard Worker {
48*25da2beaSAndroid Build Coastguard Worker 	int ret;
49*25da2beaSAndroid Build Coastguard Worker 
50*25da2beaSAndroid Build Coastguard Worker 	ret = __sys_io_uring_register(fd, opcode, arg, nr_args);
51*25da2beaSAndroid Build Coastguard Worker 	if (ret != -1) {
52*25da2beaSAndroid Build Coastguard Worker 		int ret2 = 0;
53*25da2beaSAndroid Build Coastguard Worker 
54*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "expected %s, but call succeeded\n", strerror(error));
55*25da2beaSAndroid Build Coastguard Worker 		if (opcode == IORING_REGISTER_BUFFERS) {
56*25da2beaSAndroid Build Coastguard Worker 			ret2 = __sys_io_uring_register(fd,
57*25da2beaSAndroid Build Coastguard Worker 					IORING_UNREGISTER_BUFFERS, 0, 0);
58*25da2beaSAndroid Build Coastguard Worker 		} else if (opcode == IORING_REGISTER_FILES) {
59*25da2beaSAndroid Build Coastguard Worker 			ret2 = __sys_io_uring_register(fd,
60*25da2beaSAndroid Build Coastguard Worker 					IORING_UNREGISTER_FILES, 0, 0);
61*25da2beaSAndroid Build Coastguard Worker 		}
62*25da2beaSAndroid Build Coastguard Worker 		if (ret2) {
63*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "internal error: failed to unregister\n");
64*25da2beaSAndroid Build Coastguard Worker 			exit(1);
65*25da2beaSAndroid Build Coastguard Worker 		}
66*25da2beaSAndroid Build Coastguard Worker 		return 1;
67*25da2beaSAndroid Build Coastguard Worker 	}
68*25da2beaSAndroid Build Coastguard Worker 
69*25da2beaSAndroid Build Coastguard Worker 	if (errno != error) {
70*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "expected %d, got %d\n", error, errno);
71*25da2beaSAndroid Build Coastguard Worker 		return 1;
72*25da2beaSAndroid Build Coastguard Worker 	}
73*25da2beaSAndroid Build Coastguard Worker 	return 0;
74*25da2beaSAndroid Build Coastguard Worker }
75*25da2beaSAndroid Build Coastguard Worker 
new_io_uring(int entries,struct io_uring_params * p)76*25da2beaSAndroid Build Coastguard Worker static int new_io_uring(int entries, struct io_uring_params *p)
77*25da2beaSAndroid Build Coastguard Worker {
78*25da2beaSAndroid Build Coastguard Worker 	int fd;
79*25da2beaSAndroid Build Coastguard Worker 
80*25da2beaSAndroid Build Coastguard Worker 	fd = __sys_io_uring_setup(entries, p);
81*25da2beaSAndroid Build Coastguard Worker 	if (fd < 0) {
82*25da2beaSAndroid Build Coastguard Worker 		perror("io_uring_setup");
83*25da2beaSAndroid Build Coastguard Worker 		exit(1);
84*25da2beaSAndroid Build Coastguard Worker 	}
85*25da2beaSAndroid Build Coastguard Worker 	return fd;
86*25da2beaSAndroid Build Coastguard Worker }
87*25da2beaSAndroid Build Coastguard Worker 
88*25da2beaSAndroid Build Coastguard Worker #define MAXFDS (UINT_MAX * sizeof(int))
89*25da2beaSAndroid Build Coastguard Worker 
map_filebacked(size_t size)90*25da2beaSAndroid Build Coastguard Worker static void *map_filebacked(size_t size)
91*25da2beaSAndroid Build Coastguard Worker {
92*25da2beaSAndroid Build Coastguard Worker 	int fd, ret;
93*25da2beaSAndroid Build Coastguard Worker 	void *addr;
94*25da2beaSAndroid Build Coastguard Worker 	char template[32] = "io_uring_register-test-XXXXXXXX";
95*25da2beaSAndroid Build Coastguard Worker 
96*25da2beaSAndroid Build Coastguard Worker 	fd = mkstemp(template);
97*25da2beaSAndroid Build Coastguard Worker 	if (fd < 0) {
98*25da2beaSAndroid Build Coastguard Worker 		perror("mkstemp");
99*25da2beaSAndroid Build Coastguard Worker 		return NULL;
100*25da2beaSAndroid Build Coastguard Worker 	}
101*25da2beaSAndroid Build Coastguard Worker 	unlink(template);
102*25da2beaSAndroid Build Coastguard Worker 
103*25da2beaSAndroid Build Coastguard Worker 	ret = ftruncate(fd, size);
104*25da2beaSAndroid Build Coastguard Worker 	if (ret < 0) {
105*25da2beaSAndroid Build Coastguard Worker 		perror("ftruncate");
106*25da2beaSAndroid Build Coastguard Worker 		close(fd);
107*25da2beaSAndroid Build Coastguard Worker 		return NULL;
108*25da2beaSAndroid Build Coastguard Worker 	}
109*25da2beaSAndroid Build Coastguard Worker 
110*25da2beaSAndroid Build Coastguard Worker 	addr = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
111*25da2beaSAndroid Build Coastguard Worker 	if (addr == MAP_FAILED) {
112*25da2beaSAndroid Build Coastguard Worker 		perror("mmap");
113*25da2beaSAndroid Build Coastguard Worker 		close(fd);
114*25da2beaSAndroid Build Coastguard Worker 		return NULL;
115*25da2beaSAndroid Build Coastguard Worker 	}
116*25da2beaSAndroid Build Coastguard Worker 
117*25da2beaSAndroid Build Coastguard Worker 	close(fd);
118*25da2beaSAndroid Build Coastguard Worker 	return addr;
119*25da2beaSAndroid Build Coastguard Worker }
120*25da2beaSAndroid Build Coastguard Worker 
121*25da2beaSAndroid Build Coastguard Worker /*
122*25da2beaSAndroid Build Coastguard Worker  * NOTE: this is now limited by SCM_MAX_FD (253).  Keep the code for now,
123*25da2beaSAndroid Build Coastguard Worker  * but probably should augment it to test 253 and 254, specifically.
124*25da2beaSAndroid Build Coastguard Worker  */
test_max_fds(int uring_fd)125*25da2beaSAndroid Build Coastguard Worker static int test_max_fds(int uring_fd)
126*25da2beaSAndroid Build Coastguard Worker {
127*25da2beaSAndroid Build Coastguard Worker 	int status = 1;
128*25da2beaSAndroid Build Coastguard Worker 	int ret;
129*25da2beaSAndroid Build Coastguard Worker 	void *fd_as; /* file descriptor address space */
130*25da2beaSAndroid Build Coastguard Worker 	int fdtable_fd; /* fd for the file that will be mapped over and over */
131*25da2beaSAndroid Build Coastguard Worker 	int io_fd; /* the valid fd for I/O -- /dev/null */
132*25da2beaSAndroid Build Coastguard Worker 	int *fds; /* used to map the file into the address space */
133*25da2beaSAndroid Build Coastguard Worker 	char template[32] = "io_uring_register-test-XXXXXXXX";
134*25da2beaSAndroid Build Coastguard Worker 	unsigned long long i, nr_maps, nr_fds;
135*25da2beaSAndroid Build Coastguard Worker 
136*25da2beaSAndroid Build Coastguard Worker 	/*
137*25da2beaSAndroid Build Coastguard Worker 	 * First, mmap anonymous the full size.  That will guarantee the
138*25da2beaSAndroid Build Coastguard Worker 	 * mapping will fit in the memory area selected by mmap.  Then,
139*25da2beaSAndroid Build Coastguard Worker 	 * over-write that mapping using a file-backed mapping, 128MiB at
140*25da2beaSAndroid Build Coastguard Worker 	 * a time using MAP_FIXED.
141*25da2beaSAndroid Build Coastguard Worker 	 */
142*25da2beaSAndroid Build Coastguard Worker 	fd_as = mmap(NULL, UINT_MAX * sizeof(int), PROT_READ|PROT_WRITE,
143*25da2beaSAndroid Build Coastguard Worker 		     MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
144*25da2beaSAndroid Build Coastguard Worker 	if (fd_as == MAP_FAILED) {
145*25da2beaSAndroid Build Coastguard Worker 		if (errno == ENOMEM)
146*25da2beaSAndroid Build Coastguard Worker 			return 0;
147*25da2beaSAndroid Build Coastguard Worker 		perror("mmap fd_as");
148*25da2beaSAndroid Build Coastguard Worker 		exit(1);
149*25da2beaSAndroid Build Coastguard Worker 	}
150*25da2beaSAndroid Build Coastguard Worker 
151*25da2beaSAndroid Build Coastguard Worker 	fdtable_fd = mkstemp(template);
152*25da2beaSAndroid Build Coastguard Worker 	if (fdtable_fd < 0) {
153*25da2beaSAndroid Build Coastguard Worker 		perror("mkstemp");
154*25da2beaSAndroid Build Coastguard Worker 		exit(1);
155*25da2beaSAndroid Build Coastguard Worker 	}
156*25da2beaSAndroid Build Coastguard Worker 	unlink(template);
157*25da2beaSAndroid Build Coastguard Worker 	ret = ftruncate(fdtable_fd, 128*1024*1024);
158*25da2beaSAndroid Build Coastguard Worker 	if (ret < 0) {
159*25da2beaSAndroid Build Coastguard Worker 		perror("ftruncate");
160*25da2beaSAndroid Build Coastguard Worker 		exit(1);
161*25da2beaSAndroid Build Coastguard Worker 	}
162*25da2beaSAndroid Build Coastguard Worker 
163*25da2beaSAndroid Build Coastguard Worker 	io_fd = open("/dev/null", O_RDWR);
164*25da2beaSAndroid Build Coastguard Worker 	if (io_fd < 0) {
165*25da2beaSAndroid Build Coastguard Worker 		perror("open /dev/null");
166*25da2beaSAndroid Build Coastguard Worker 		exit(1);
167*25da2beaSAndroid Build Coastguard Worker 	}
168*25da2beaSAndroid Build Coastguard Worker 	fds = mmap(fd_as, 128*1024*1024, PROT_READ|PROT_WRITE,
169*25da2beaSAndroid Build Coastguard Worker 		   MAP_SHARED|MAP_FIXED, fdtable_fd, 0);
170*25da2beaSAndroid Build Coastguard Worker 	if (fds == MAP_FAILED) {
171*25da2beaSAndroid Build Coastguard Worker 		perror("mmap fdtable");
172*25da2beaSAndroid Build Coastguard Worker 		exit(1);
173*25da2beaSAndroid Build Coastguard Worker 	}
174*25da2beaSAndroid Build Coastguard Worker 
175*25da2beaSAndroid Build Coastguard Worker 	/* fill the fd table */
176*25da2beaSAndroid Build Coastguard Worker 	nr_fds = 128*1024*1024 / sizeof(int);
177*25da2beaSAndroid Build Coastguard Worker 	for (i = 0; i < nr_fds; i++)
178*25da2beaSAndroid Build Coastguard Worker 		fds[i] = io_fd;
179*25da2beaSAndroid Build Coastguard Worker 
180*25da2beaSAndroid Build Coastguard Worker 	/* map the file through the rest of the address space */
181*25da2beaSAndroid Build Coastguard Worker 	nr_maps = (UINT_MAX * sizeof(int)) / (128*1024*1024);
182*25da2beaSAndroid Build Coastguard Worker 	for (i = 0; i < nr_maps; i++) {
183*25da2beaSAndroid Build Coastguard Worker 		fds = &fds[nr_fds]; /* advance fds by 128MiB */
184*25da2beaSAndroid Build Coastguard Worker 		fds = mmap(fds, 128*1024*1024, PROT_READ|PROT_WRITE,
185*25da2beaSAndroid Build Coastguard Worker 			   MAP_SHARED|MAP_FIXED, fdtable_fd, 0);
186*25da2beaSAndroid Build Coastguard Worker 		if (fds == MAP_FAILED) {
187*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "mmap failed at offset %lu\n",
188*25da2beaSAndroid Build Coastguard Worker 			       (unsigned long)((char *)fd_as - (char *)fds));
189*25da2beaSAndroid Build Coastguard Worker 			exit(1);
190*25da2beaSAndroid Build Coastguard Worker 		}
191*25da2beaSAndroid Build Coastguard Worker 	}
192*25da2beaSAndroid Build Coastguard Worker 
193*25da2beaSAndroid Build Coastguard Worker 	/* Now fd_as points to the file descriptor array. */
194*25da2beaSAndroid Build Coastguard Worker 	/*
195*25da2beaSAndroid Build Coastguard Worker 	 * We may not be able to map all of these files.  Let's back off
196*25da2beaSAndroid Build Coastguard Worker 	 * until success.
197*25da2beaSAndroid Build Coastguard Worker 	 */
198*25da2beaSAndroid Build Coastguard Worker 	nr_fds = UINT_MAX;
199*25da2beaSAndroid Build Coastguard Worker 	while (nr_fds) {
200*25da2beaSAndroid Build Coastguard Worker 		ret = __sys_io_uring_register(uring_fd, IORING_REGISTER_FILES,
201*25da2beaSAndroid Build Coastguard Worker 						fd_as, nr_fds);
202*25da2beaSAndroid Build Coastguard Worker 		if (ret != 0) {
203*25da2beaSAndroid Build Coastguard Worker 			nr_fds /= 2;
204*25da2beaSAndroid Build Coastguard Worker 			continue;
205*25da2beaSAndroid Build Coastguard Worker 		}
206*25da2beaSAndroid Build Coastguard Worker 		status = 0;
207*25da2beaSAndroid Build Coastguard Worker 		ret = __sys_io_uring_register(uring_fd, IORING_UNREGISTER_FILES,
208*25da2beaSAndroid Build Coastguard Worker 						0, 0);
209*25da2beaSAndroid Build Coastguard Worker 		if (ret < 0) {
210*25da2beaSAndroid Build Coastguard Worker 			ret = errno;
211*25da2beaSAndroid Build Coastguard Worker 			errno = ret;
212*25da2beaSAndroid Build Coastguard Worker 			perror("io_uring_register UNREGISTER_FILES");
213*25da2beaSAndroid Build Coastguard Worker 			exit(1);
214*25da2beaSAndroid Build Coastguard Worker 		}
215*25da2beaSAndroid Build Coastguard Worker 		break;
216*25da2beaSAndroid Build Coastguard Worker 	}
217*25da2beaSAndroid Build Coastguard Worker 
218*25da2beaSAndroid Build Coastguard Worker 	close(io_fd);
219*25da2beaSAndroid Build Coastguard Worker 	close(fdtable_fd);
220*25da2beaSAndroid Build Coastguard Worker 	ret = munmap(fd_as, UINT_MAX * sizeof(int));
221*25da2beaSAndroid Build Coastguard Worker 	if (ret != 0) {
222*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "munmap(%zu) failed\n", UINT_MAX * sizeof(int));
223*25da2beaSAndroid Build Coastguard Worker 		exit(1);
224*25da2beaSAndroid Build Coastguard Worker 	}
225*25da2beaSAndroid Build Coastguard Worker 
226*25da2beaSAndroid Build Coastguard Worker 	return status;
227*25da2beaSAndroid Build Coastguard Worker }
228*25da2beaSAndroid Build Coastguard Worker 
test_memlock_exceeded(int fd)229*25da2beaSAndroid Build Coastguard Worker static int test_memlock_exceeded(int fd)
230*25da2beaSAndroid Build Coastguard Worker {
231*25da2beaSAndroid Build Coastguard Worker 	int ret;
232*25da2beaSAndroid Build Coastguard Worker 	void *buf;
233*25da2beaSAndroid Build Coastguard Worker 	struct iovec iov;
234*25da2beaSAndroid Build Coastguard Worker 
235*25da2beaSAndroid Build Coastguard Worker 	/* if limit is larger than 2gb, just skip this test */
236*25da2beaSAndroid Build Coastguard Worker 	if (mlock_limit >= 2 * 1024 * 1024 * 1024ULL)
237*25da2beaSAndroid Build Coastguard Worker 		return 0;
238*25da2beaSAndroid Build Coastguard Worker 
239*25da2beaSAndroid Build Coastguard Worker 	iov.iov_len = mlock_limit * 2;
240*25da2beaSAndroid Build Coastguard Worker 	buf = t_malloc(iov.iov_len);
241*25da2beaSAndroid Build Coastguard Worker 	iov.iov_base = buf;
242*25da2beaSAndroid Build Coastguard Worker 
243*25da2beaSAndroid Build Coastguard Worker 	while (iov.iov_len) {
244*25da2beaSAndroid Build Coastguard Worker 		ret = __sys_io_uring_register(fd, IORING_REGISTER_BUFFERS, &iov, 1);
245*25da2beaSAndroid Build Coastguard Worker 		if (ret < 0) {
246*25da2beaSAndroid Build Coastguard Worker 			if (errno == ENOMEM) {
247*25da2beaSAndroid Build Coastguard Worker 				iov.iov_len /= 2;
248*25da2beaSAndroid Build Coastguard Worker 				continue;
249*25da2beaSAndroid Build Coastguard Worker 			}
250*25da2beaSAndroid Build Coastguard Worker 			if (errno == EFAULT) {
251*25da2beaSAndroid Build Coastguard Worker 				free(buf);
252*25da2beaSAndroid Build Coastguard Worker 				return 0;
253*25da2beaSAndroid Build Coastguard Worker 			}
254*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "expected success or EFAULT, got %d\n", errno);
255*25da2beaSAndroid Build Coastguard Worker 			free(buf);
256*25da2beaSAndroid Build Coastguard Worker 			return 1;
257*25da2beaSAndroid Build Coastguard Worker 		}
258*25da2beaSAndroid Build Coastguard Worker 		ret = __sys_io_uring_register(fd, IORING_UNREGISTER_BUFFERS,
259*25da2beaSAndroid Build Coastguard Worker 						NULL, 0);
260*25da2beaSAndroid Build Coastguard Worker 		if (ret != 0) {
261*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "error: unregister failed with %d\n", errno);
262*25da2beaSAndroid Build Coastguard Worker 			free(buf);
263*25da2beaSAndroid Build Coastguard Worker 			return 1;
264*25da2beaSAndroid Build Coastguard Worker 		}
265*25da2beaSAndroid Build Coastguard Worker 		break;
266*25da2beaSAndroid Build Coastguard Worker 	}
267*25da2beaSAndroid Build Coastguard Worker 	if (!iov.iov_len)
268*25da2beaSAndroid Build Coastguard Worker 		printf("Unable to register buffers.  Check memlock rlimit.\n");
269*25da2beaSAndroid Build Coastguard Worker 
270*25da2beaSAndroid Build Coastguard Worker 	free(buf);
271*25da2beaSAndroid Build Coastguard Worker 	return 0;
272*25da2beaSAndroid Build Coastguard Worker }
273*25da2beaSAndroid Build Coastguard Worker 
test_iovec_nr(int fd)274*25da2beaSAndroid Build Coastguard Worker static int test_iovec_nr(int fd)
275*25da2beaSAndroid Build Coastguard Worker {
276*25da2beaSAndroid Build Coastguard Worker 	int i, ret, status = 0;
277*25da2beaSAndroid Build Coastguard Worker 	unsigned int nr = 1000000;
278*25da2beaSAndroid Build Coastguard Worker 	struct iovec *iovs;
279*25da2beaSAndroid Build Coastguard Worker 	void *buf;
280*25da2beaSAndroid Build Coastguard Worker 
281*25da2beaSAndroid Build Coastguard Worker 	iovs = malloc(nr * sizeof(struct iovec));
282*25da2beaSAndroid Build Coastguard Worker 	if (!iovs) {
283*25da2beaSAndroid Build Coastguard Worker 		fprintf(stdout, "can't allocate iovecs, skip\n");
284*25da2beaSAndroid Build Coastguard Worker 		return 0;
285*25da2beaSAndroid Build Coastguard Worker 	}
286*25da2beaSAndroid Build Coastguard Worker 	buf = t_malloc(pagesize);
287*25da2beaSAndroid Build Coastguard Worker 
288*25da2beaSAndroid Build Coastguard Worker 	for (i = 0; i < nr; i++) {
289*25da2beaSAndroid Build Coastguard Worker 		iovs[i].iov_base = buf;
290*25da2beaSAndroid Build Coastguard Worker 		iovs[i].iov_len = pagesize;
291*25da2beaSAndroid Build Coastguard Worker 	}
292*25da2beaSAndroid Build Coastguard Worker 
293*25da2beaSAndroid Build Coastguard Worker 	status |= expect_fail(fd, IORING_REGISTER_BUFFERS, iovs, nr, EINVAL);
294*25da2beaSAndroid Build Coastguard Worker 
295*25da2beaSAndroid Build Coastguard Worker 	/* reduce to UIO_MAXIOV */
296*25da2beaSAndroid Build Coastguard Worker 	nr = UIO_MAXIOV;
297*25da2beaSAndroid Build Coastguard Worker 	ret = __sys_io_uring_register(fd, IORING_REGISTER_BUFFERS, iovs, nr);
298*25da2beaSAndroid Build Coastguard Worker 	if (ret && (errno == ENOMEM || errno == EPERM) && geteuid()) {
299*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "can't register large iovec for regular users, skip\n");
300*25da2beaSAndroid Build Coastguard Worker 	} else if (ret != 0) {
301*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "expected success, got %d\n", errno);
302*25da2beaSAndroid Build Coastguard Worker 		status = 1;
303*25da2beaSAndroid Build Coastguard Worker 	} else {
304*25da2beaSAndroid Build Coastguard Worker 		__sys_io_uring_register(fd, IORING_UNREGISTER_BUFFERS, 0, 0);
305*25da2beaSAndroid Build Coastguard Worker 	}
306*25da2beaSAndroid Build Coastguard Worker 	free(buf);
307*25da2beaSAndroid Build Coastguard Worker 	free(iovs);
308*25da2beaSAndroid Build Coastguard Worker 	return status;
309*25da2beaSAndroid Build Coastguard Worker }
310*25da2beaSAndroid Build Coastguard Worker 
311*25da2beaSAndroid Build Coastguard Worker /*
312*25da2beaSAndroid Build Coastguard Worker  * io_uring limit is 1G.  iov_len limit is ~OUL, I think
313*25da2beaSAndroid Build Coastguard Worker  */
test_iovec_size(int fd)314*25da2beaSAndroid Build Coastguard Worker static int test_iovec_size(int fd)
315*25da2beaSAndroid Build Coastguard Worker {
316*25da2beaSAndroid Build Coastguard Worker 	unsigned int status = 0;
317*25da2beaSAndroid Build Coastguard Worker 	int ret;
318*25da2beaSAndroid Build Coastguard Worker 	struct iovec iov;
319*25da2beaSAndroid Build Coastguard Worker 	void *buf;
320*25da2beaSAndroid Build Coastguard Worker 
321*25da2beaSAndroid Build Coastguard Worker 	/* NULL pointer for base */
322*25da2beaSAndroid Build Coastguard Worker 	iov.iov_base = 0;
323*25da2beaSAndroid Build Coastguard Worker 	iov.iov_len = 4096;
324*25da2beaSAndroid Build Coastguard Worker 	status |= expect_fail(fd, IORING_REGISTER_BUFFERS, &iov, 1, EFAULT);
325*25da2beaSAndroid Build Coastguard Worker 
326*25da2beaSAndroid Build Coastguard Worker 	/* valid base, 0 length */
327*25da2beaSAndroid Build Coastguard Worker 	iov.iov_base = &buf;
328*25da2beaSAndroid Build Coastguard Worker 	iov.iov_len = 0;
329*25da2beaSAndroid Build Coastguard Worker 	status |= expect_fail(fd, IORING_REGISTER_BUFFERS, &iov, 1, EFAULT);
330*25da2beaSAndroid Build Coastguard Worker 
331*25da2beaSAndroid Build Coastguard Worker 	/* valid base, length exceeds size */
332*25da2beaSAndroid Build Coastguard Worker 	/* this requires an unampped page directly after buf */
333*25da2beaSAndroid Build Coastguard Worker 	buf = mmap(NULL, 2 * pagesize, PROT_READ|PROT_WRITE,
334*25da2beaSAndroid Build Coastguard Worker 		   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
335*25da2beaSAndroid Build Coastguard Worker 	assert(buf != MAP_FAILED);
336*25da2beaSAndroid Build Coastguard Worker 	ret = munmap(buf + pagesize, pagesize);
337*25da2beaSAndroid Build Coastguard Worker 	assert(ret == 0);
338*25da2beaSAndroid Build Coastguard Worker 	iov.iov_base = buf;
339*25da2beaSAndroid Build Coastguard Worker 	iov.iov_len = 2 * pagesize;
340*25da2beaSAndroid Build Coastguard Worker 	status |= expect_fail(fd, IORING_REGISTER_BUFFERS, &iov, 1, EFAULT);
341*25da2beaSAndroid Build Coastguard Worker 	munmap(buf, pagesize);
342*25da2beaSAndroid Build Coastguard Worker 
343*25da2beaSAndroid Build Coastguard Worker 	/* huge page */
344*25da2beaSAndroid Build Coastguard Worker 	buf = mmap(NULL, 2*1024*1024, PROT_READ|PROT_WRITE,
345*25da2beaSAndroid Build Coastguard Worker 		   MAP_PRIVATE | MAP_HUGETLB | MAP_HUGE_2MB | MAP_ANONYMOUS,
346*25da2beaSAndroid Build Coastguard Worker 		   -1, 0);
347*25da2beaSAndroid Build Coastguard Worker 	if (buf == MAP_FAILED) {
348*25da2beaSAndroid Build Coastguard Worker 		printf("Unable to map a huge page.  Try increasing "
349*25da2beaSAndroid Build Coastguard Worker 		       "/proc/sys/vm/nr_hugepages by at least 1.\n");
350*25da2beaSAndroid Build Coastguard Worker 		printf("Skipping the hugepage test\n");
351*25da2beaSAndroid Build Coastguard Worker 	} else {
352*25da2beaSAndroid Build Coastguard Worker 		/*
353*25da2beaSAndroid Build Coastguard Worker 		 * This should succeed, so long as RLIMIT_MEMLOCK is
354*25da2beaSAndroid Build Coastguard Worker 		 * not exceeded
355*25da2beaSAndroid Build Coastguard Worker 		 */
356*25da2beaSAndroid Build Coastguard Worker 		iov.iov_base = buf;
357*25da2beaSAndroid Build Coastguard Worker 		iov.iov_len = 2*1024*1024;
358*25da2beaSAndroid Build Coastguard Worker 		ret = __sys_io_uring_register(fd, IORING_REGISTER_BUFFERS, &iov, 1);
359*25da2beaSAndroid Build Coastguard Worker 		if (ret < 0) {
360*25da2beaSAndroid Build Coastguard Worker 			if (errno == ENOMEM)
361*25da2beaSAndroid Build Coastguard Worker 				printf("Unable to test registering of a huge "
362*25da2beaSAndroid Build Coastguard Worker 				       "page.  Try increasing the "
363*25da2beaSAndroid Build Coastguard Worker 				       "RLIMIT_MEMLOCK resource limit by at "
364*25da2beaSAndroid Build Coastguard Worker 				       "least 2MB.");
365*25da2beaSAndroid Build Coastguard Worker 			else {
366*25da2beaSAndroid Build Coastguard Worker 				fprintf(stderr, "expected success, got %d\n", errno);
367*25da2beaSAndroid Build Coastguard Worker 				status = 1;
368*25da2beaSAndroid Build Coastguard Worker 			}
369*25da2beaSAndroid Build Coastguard Worker 		} else {
370*25da2beaSAndroid Build Coastguard Worker 			ret = __sys_io_uring_register(fd,
371*25da2beaSAndroid Build Coastguard Worker 					IORING_UNREGISTER_BUFFERS, 0, 0);
372*25da2beaSAndroid Build Coastguard Worker 			if (ret < 0) {
373*25da2beaSAndroid Build Coastguard Worker 				perror("io_uring_unregister");
374*25da2beaSAndroid Build Coastguard Worker 				status = 1;
375*25da2beaSAndroid Build Coastguard Worker 			}
376*25da2beaSAndroid Build Coastguard Worker 		}
377*25da2beaSAndroid Build Coastguard Worker 	}
378*25da2beaSAndroid Build Coastguard Worker 	ret = munmap(iov.iov_base, iov.iov_len);
379*25da2beaSAndroid Build Coastguard Worker 	assert(ret == 0);
380*25da2beaSAndroid Build Coastguard Worker 
381*25da2beaSAndroid Build Coastguard Worker 	/* file-backed buffers -- not supported */
382*25da2beaSAndroid Build Coastguard Worker 	buf = map_filebacked(2*1024*1024);
383*25da2beaSAndroid Build Coastguard Worker 	if (!buf)
384*25da2beaSAndroid Build Coastguard Worker 		status = 1;
385*25da2beaSAndroid Build Coastguard Worker 	iov.iov_base = buf;
386*25da2beaSAndroid Build Coastguard Worker 	iov.iov_len = 2*1024*1024;
387*25da2beaSAndroid Build Coastguard Worker 	status |= expect_fail(fd, IORING_REGISTER_BUFFERS, &iov, 1, EOPNOTSUPP);
388*25da2beaSAndroid Build Coastguard Worker 	munmap(buf, 2*1024*1024);
389*25da2beaSAndroid Build Coastguard Worker 
390*25da2beaSAndroid Build Coastguard Worker 	/* bump up against the soft limit and make sure we get EFAULT
391*25da2beaSAndroid Build Coastguard Worker 	 * or whatever we're supposed to get.  NOTE: this requires
392*25da2beaSAndroid Build Coastguard Worker 	 * running the test as non-root. */
393*25da2beaSAndroid Build Coastguard Worker 	if (getuid() != 0)
394*25da2beaSAndroid Build Coastguard Worker 		status |= test_memlock_exceeded(fd);
395*25da2beaSAndroid Build Coastguard Worker 
396*25da2beaSAndroid Build Coastguard Worker 	return status;
397*25da2beaSAndroid Build Coastguard Worker }
398*25da2beaSAndroid Build Coastguard Worker 
ioring_poll(struct io_uring * ring,int fd,int fixed)399*25da2beaSAndroid Build Coastguard Worker static int ioring_poll(struct io_uring *ring, int fd, int fixed)
400*25da2beaSAndroid Build Coastguard Worker {
401*25da2beaSAndroid Build Coastguard Worker 	int ret;
402*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_sqe *sqe;
403*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_cqe *cqe;
404*25da2beaSAndroid Build Coastguard Worker 
405*25da2beaSAndroid Build Coastguard Worker 	sqe = io_uring_get_sqe(ring);
406*25da2beaSAndroid Build Coastguard Worker 	memset(sqe, 0, sizeof(*sqe));
407*25da2beaSAndroid Build Coastguard Worker 	sqe->opcode = IORING_OP_POLL_ADD;
408*25da2beaSAndroid Build Coastguard Worker 	if (fixed)
409*25da2beaSAndroid Build Coastguard Worker 		sqe->flags = IOSQE_FIXED_FILE;
410*25da2beaSAndroid Build Coastguard Worker 	sqe->fd = fd;
411*25da2beaSAndroid Build Coastguard Worker 	sqe->poll_events = POLLIN|POLLOUT;
412*25da2beaSAndroid Build Coastguard Worker 
413*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_submit(ring);
414*25da2beaSAndroid Build Coastguard Worker 	if (ret != 1) {
415*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "failed to submit poll sqe: %d.\n", errno);
416*25da2beaSAndroid Build Coastguard Worker 		return 1;
417*25da2beaSAndroid Build Coastguard Worker 	}
418*25da2beaSAndroid Build Coastguard Worker 
419*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_wait_cqe(ring, &cqe);
420*25da2beaSAndroid Build Coastguard Worker 	if (ret < 0) {
421*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "io_uring_wait_cqe failed with %d\n", ret);
422*25da2beaSAndroid Build Coastguard Worker 		return 1;
423*25da2beaSAndroid Build Coastguard Worker 	}
424*25da2beaSAndroid Build Coastguard Worker 	ret = 0;
425*25da2beaSAndroid Build Coastguard Worker 	if (cqe->res != POLLOUT) {
426*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "io_uring_wait_cqe: expected 0x%.8x, got 0x%.8x\n",
427*25da2beaSAndroid Build Coastguard Worker 		       POLLOUT, cqe->res);
428*25da2beaSAndroid Build Coastguard Worker 		ret = 1;
429*25da2beaSAndroid Build Coastguard Worker 	}
430*25da2beaSAndroid Build Coastguard Worker 
431*25da2beaSAndroid Build Coastguard Worker 	io_uring_cqe_seen(ring, cqe);
432*25da2beaSAndroid Build Coastguard Worker 	return ret;
433*25da2beaSAndroid Build Coastguard Worker }
434*25da2beaSAndroid Build Coastguard Worker 
test_poll_ringfd(void)435*25da2beaSAndroid Build Coastguard Worker static int test_poll_ringfd(void)
436*25da2beaSAndroid Build Coastguard Worker {
437*25da2beaSAndroid Build Coastguard Worker 	int status = 0;
438*25da2beaSAndroid Build Coastguard Worker 	int ret;
439*25da2beaSAndroid Build Coastguard Worker 	int fd;
440*25da2beaSAndroid Build Coastguard Worker 	struct io_uring ring;
441*25da2beaSAndroid Build Coastguard Worker 
442*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_queue_init(1, &ring, 0);
443*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
444*25da2beaSAndroid Build Coastguard Worker 		perror("io_uring_queue_init");
445*25da2beaSAndroid Build Coastguard Worker 		return 1;
446*25da2beaSAndroid Build Coastguard Worker 	}
447*25da2beaSAndroid Build Coastguard Worker 	fd = ring.ring_fd;
448*25da2beaSAndroid Build Coastguard Worker 
449*25da2beaSAndroid Build Coastguard Worker 	/* try polling the ring fd */
450*25da2beaSAndroid Build Coastguard Worker 	status = ioring_poll(&ring, fd, 0);
451*25da2beaSAndroid Build Coastguard Worker 
452*25da2beaSAndroid Build Coastguard Worker 	/*
453*25da2beaSAndroid Build Coastguard Worker 	 * now register the ring fd, and try the poll again.  This should
454*25da2beaSAndroid Build Coastguard Worker 	 * fail, because the kernel does not allow registering of the
455*25da2beaSAndroid Build Coastguard Worker 	 * ring_fd.
456*25da2beaSAndroid Build Coastguard Worker 	 */
457*25da2beaSAndroid Build Coastguard Worker 	status |= expect_fail(fd, IORING_REGISTER_FILES, &fd, 1, EBADF);
458*25da2beaSAndroid Build Coastguard Worker 
459*25da2beaSAndroid Build Coastguard Worker 	/* tear down queue */
460*25da2beaSAndroid Build Coastguard Worker 	io_uring_queue_exit(&ring);
461*25da2beaSAndroid Build Coastguard Worker 
462*25da2beaSAndroid Build Coastguard Worker 	return status;
463*25da2beaSAndroid Build Coastguard Worker }
464*25da2beaSAndroid Build Coastguard Worker 
test_shmem(void)465*25da2beaSAndroid Build Coastguard Worker static int test_shmem(void)
466*25da2beaSAndroid Build Coastguard Worker {
467*25da2beaSAndroid Build Coastguard Worker 	const char pattern = 0xEA;
468*25da2beaSAndroid Build Coastguard Worker 	const int len = 4096;
469*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_sqe *sqe;
470*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_cqe *cqe;
471*25da2beaSAndroid Build Coastguard Worker 	struct io_uring ring;
472*25da2beaSAndroid Build Coastguard Worker 	struct iovec iov;
473*25da2beaSAndroid Build Coastguard Worker 	int memfd, ret, i;
474*25da2beaSAndroid Build Coastguard Worker 	char *mem;
475*25da2beaSAndroid Build Coastguard Worker 	int pipefd[2] = {-1, -1};
476*25da2beaSAndroid Build Coastguard Worker 
477*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_queue_init(8, &ring, 0);
478*25da2beaSAndroid Build Coastguard Worker 	if (ret)
479*25da2beaSAndroid Build Coastguard Worker 		return 1;
480*25da2beaSAndroid Build Coastguard Worker 
481*25da2beaSAndroid Build Coastguard Worker 	if (pipe(pipefd)) {
482*25da2beaSAndroid Build Coastguard Worker 		perror("pipe");
483*25da2beaSAndroid Build Coastguard Worker 		return 1;
484*25da2beaSAndroid Build Coastguard Worker 	}
485*25da2beaSAndroid Build Coastguard Worker 	memfd = memfd_create("uring-shmem-test", 0);
486*25da2beaSAndroid Build Coastguard Worker 	if (memfd < 0) {
487*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "memfd_create() failed %i\n", -errno);
488*25da2beaSAndroid Build Coastguard Worker 		return 1;
489*25da2beaSAndroid Build Coastguard Worker 	}
490*25da2beaSAndroid Build Coastguard Worker 	if (ftruncate(memfd, len)) {
491*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "can't truncate memfd\n");
492*25da2beaSAndroid Build Coastguard Worker 		return 1;
493*25da2beaSAndroid Build Coastguard Worker 	}
494*25da2beaSAndroid Build Coastguard Worker 	mem = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, memfd, 0);
495*25da2beaSAndroid Build Coastguard Worker 	if (!mem) {
496*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "mmap failed\n");
497*25da2beaSAndroid Build Coastguard Worker 		return 1;
498*25da2beaSAndroid Build Coastguard Worker 	}
499*25da2beaSAndroid Build Coastguard Worker 	for (i = 0; i < len; i++)
500*25da2beaSAndroid Build Coastguard Worker 		mem[i] = pattern;
501*25da2beaSAndroid Build Coastguard Worker 
502*25da2beaSAndroid Build Coastguard Worker 	iov.iov_base = mem;
503*25da2beaSAndroid Build Coastguard Worker 	iov.iov_len = len;
504*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_register_buffers(&ring, &iov, 1);
505*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
506*25da2beaSAndroid Build Coastguard Worker 		if (ret == -EOPNOTSUPP) {
507*25da2beaSAndroid Build Coastguard Worker 			fprintf(stdout, "memfd registration isn't supported, "
508*25da2beaSAndroid Build Coastguard Worker 					"skip\n");
509*25da2beaSAndroid Build Coastguard Worker 			goto out;
510*25da2beaSAndroid Build Coastguard Worker 		}
511*25da2beaSAndroid Build Coastguard Worker 
512*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "buffer reg failed: %d\n", ret);
513*25da2beaSAndroid Build Coastguard Worker 		return 1;
514*25da2beaSAndroid Build Coastguard Worker 	}
515*25da2beaSAndroid Build Coastguard Worker 
516*25da2beaSAndroid Build Coastguard Worker 	/* check that we can read and write from/to shmem reg buffer */
517*25da2beaSAndroid Build Coastguard Worker 	sqe = io_uring_get_sqe(&ring);
518*25da2beaSAndroid Build Coastguard Worker 	io_uring_prep_write_fixed(sqe, pipefd[1], mem, 512, 0, 0);
519*25da2beaSAndroid Build Coastguard Worker 	sqe->user_data = 1;
520*25da2beaSAndroid Build Coastguard Worker 
521*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_submit(&ring);
522*25da2beaSAndroid Build Coastguard Worker 	if (ret != 1) {
523*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "submit write failed\n");
524*25da2beaSAndroid Build Coastguard Worker 		return 1;
525*25da2beaSAndroid Build Coastguard Worker 	}
526*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_wait_cqe(&ring, &cqe);
527*25da2beaSAndroid Build Coastguard Worker 	if (ret < 0 || cqe->user_data != 1 || cqe->res != 512) {
528*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "reading from shmem failed\n");
529*25da2beaSAndroid Build Coastguard Worker 		return 1;
530*25da2beaSAndroid Build Coastguard Worker 	}
531*25da2beaSAndroid Build Coastguard Worker 	io_uring_cqe_seen(&ring, cqe);
532*25da2beaSAndroid Build Coastguard Worker 
533*25da2beaSAndroid Build Coastguard Worker 	/* clean it, should be populated with the pattern back from the pipe */
534*25da2beaSAndroid Build Coastguard Worker 	memset(mem, 0, 512);
535*25da2beaSAndroid Build Coastguard Worker 	sqe = io_uring_get_sqe(&ring);
536*25da2beaSAndroid Build Coastguard Worker 	io_uring_prep_read_fixed(sqe, pipefd[0], mem, 512, 0, 0);
537*25da2beaSAndroid Build Coastguard Worker 	sqe->user_data = 2;
538*25da2beaSAndroid Build Coastguard Worker 
539*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_submit(&ring);
540*25da2beaSAndroid Build Coastguard Worker 	if (ret != 1) {
541*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "submit write failed\n");
542*25da2beaSAndroid Build Coastguard Worker 		return 1;
543*25da2beaSAndroid Build Coastguard Worker 	}
544*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_wait_cqe(&ring, &cqe);
545*25da2beaSAndroid Build Coastguard Worker 	if (ret < 0 || cqe->user_data != 2 || cqe->res != 512) {
546*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "reading from shmem failed\n");
547*25da2beaSAndroid Build Coastguard Worker 		return 1;
548*25da2beaSAndroid Build Coastguard Worker 	}
549*25da2beaSAndroid Build Coastguard Worker 	io_uring_cqe_seen(&ring, cqe);
550*25da2beaSAndroid Build Coastguard Worker 
551*25da2beaSAndroid Build Coastguard Worker 	for (i = 0; i < 512; i++) {
552*25da2beaSAndroid Build Coastguard Worker 		if (mem[i] != pattern) {
553*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "data integrity fail\n");
554*25da2beaSAndroid Build Coastguard Worker 			return 1;
555*25da2beaSAndroid Build Coastguard Worker 		}
556*25da2beaSAndroid Build Coastguard Worker 	}
557*25da2beaSAndroid Build Coastguard Worker 
558*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_unregister_buffers(&ring);
559*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
560*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "buffer unreg failed: %d\n", ret);
561*25da2beaSAndroid Build Coastguard Worker 		return 1;
562*25da2beaSAndroid Build Coastguard Worker 	}
563*25da2beaSAndroid Build Coastguard Worker out:
564*25da2beaSAndroid Build Coastguard Worker 	io_uring_queue_exit(&ring);
565*25da2beaSAndroid Build Coastguard Worker 	close(pipefd[0]);
566*25da2beaSAndroid Build Coastguard Worker 	close(pipefd[1]);
567*25da2beaSAndroid Build Coastguard Worker 	munmap(mem, len);
568*25da2beaSAndroid Build Coastguard Worker 	close(memfd);
569*25da2beaSAndroid Build Coastguard Worker 	return 0;
570*25da2beaSAndroid Build Coastguard Worker }
571*25da2beaSAndroid Build Coastguard Worker 
main(int argc,char ** argv)572*25da2beaSAndroid Build Coastguard Worker int main(int argc, char **argv)
573*25da2beaSAndroid Build Coastguard Worker {
574*25da2beaSAndroid Build Coastguard Worker 	int fd, ret;
575*25da2beaSAndroid Build Coastguard Worker 	unsigned int status = 0;
576*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_params p;
577*25da2beaSAndroid Build Coastguard Worker 	struct rlimit rlim;
578*25da2beaSAndroid Build Coastguard Worker 
579*25da2beaSAndroid Build Coastguard Worker 	if (argc > 1)
580*25da2beaSAndroid Build Coastguard Worker 		return 0;
581*25da2beaSAndroid Build Coastguard Worker 
582*25da2beaSAndroid Build Coastguard Worker 	/* setup globals */
583*25da2beaSAndroid Build Coastguard Worker 	pagesize = getpagesize();
584*25da2beaSAndroid Build Coastguard Worker 	ret = getrlimit(RLIMIT_MEMLOCK, &rlim);
585*25da2beaSAndroid Build Coastguard Worker 	if (ret < 0) {
586*25da2beaSAndroid Build Coastguard Worker 		perror("getrlimit");
587*25da2beaSAndroid Build Coastguard Worker 		return 1;
588*25da2beaSAndroid Build Coastguard Worker 	}
589*25da2beaSAndroid Build Coastguard Worker 	mlock_limit = rlim.rlim_cur;
590*25da2beaSAndroid Build Coastguard Worker 	devnull = open("/dev/null", O_RDWR);
591*25da2beaSAndroid Build Coastguard Worker 	if (devnull < 0) {
592*25da2beaSAndroid Build Coastguard Worker 		perror("open /dev/null");
593*25da2beaSAndroid Build Coastguard Worker 		exit(1);
594*25da2beaSAndroid Build Coastguard Worker 	}
595*25da2beaSAndroid Build Coastguard Worker 
596*25da2beaSAndroid Build Coastguard Worker 	/* invalid fd */
597*25da2beaSAndroid Build Coastguard Worker 	status |= expect_fail(-1, 0, NULL, 0, EBADF);
598*25da2beaSAndroid Build Coastguard Worker 	/* valid fd that is not an io_uring fd */
599*25da2beaSAndroid Build Coastguard Worker 	status |= expect_fail(devnull, 0, NULL, 0, EOPNOTSUPP);
600*25da2beaSAndroid Build Coastguard Worker 
601*25da2beaSAndroid Build Coastguard Worker 	/* invalid opcode */
602*25da2beaSAndroid Build Coastguard Worker 	memset(&p, 0, sizeof(p));
603*25da2beaSAndroid Build Coastguard Worker 	fd = new_io_uring(1, &p);
604*25da2beaSAndroid Build Coastguard Worker 	ret = expect_fail(fd, ~0U, NULL, 0, EINVAL);
605*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
606*25da2beaSAndroid Build Coastguard Worker 		/* if this succeeds, tear down the io_uring instance
607*25da2beaSAndroid Build Coastguard Worker 		 * and start clean for the next test. */
608*25da2beaSAndroid Build Coastguard Worker 		close(fd);
609*25da2beaSAndroid Build Coastguard Worker 		fd = new_io_uring(1, &p);
610*25da2beaSAndroid Build Coastguard Worker 	}
611*25da2beaSAndroid Build Coastguard Worker 
612*25da2beaSAndroid Build Coastguard Worker 	/* IORING_REGISTER_BUFFERS */
613*25da2beaSAndroid Build Coastguard Worker 	status |= test_iovec_size(fd);
614*25da2beaSAndroid Build Coastguard Worker 	status |= test_iovec_nr(fd);
615*25da2beaSAndroid Build Coastguard Worker 	/* IORING_REGISTER_FILES */
616*25da2beaSAndroid Build Coastguard Worker 	status |= test_max_fds(fd);
617*25da2beaSAndroid Build Coastguard Worker 	close(fd);
618*25da2beaSAndroid Build Coastguard Worker 	/* uring poll on the uring fd */
619*25da2beaSAndroid Build Coastguard Worker 	status |= test_poll_ringfd();
620*25da2beaSAndroid Build Coastguard Worker 
621*25da2beaSAndroid Build Coastguard Worker 	if (status)
622*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "FAIL\n");
623*25da2beaSAndroid Build Coastguard Worker 
624*25da2beaSAndroid Build Coastguard Worker 	ret = test_shmem();
625*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
626*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "test_shmem() failed\n");
627*25da2beaSAndroid Build Coastguard Worker 		status |= 1;
628*25da2beaSAndroid Build Coastguard Worker 	}
629*25da2beaSAndroid Build Coastguard Worker 
630*25da2beaSAndroid Build Coastguard Worker 	return status;
631*25da2beaSAndroid Build Coastguard Worker }
632