xref: /aosp_15_r20/external/liburing/test/io_uring_setup.c (revision 25da2bea747f3a93b4c30fd9708b0618ef55a0e6)
1*25da2beaSAndroid Build Coastguard Worker /* SPDX-License-Identifier: MIT */
2*25da2beaSAndroid Build Coastguard Worker /*
3*25da2beaSAndroid Build Coastguard Worker  * io_uring_setup.c
4*25da2beaSAndroid Build Coastguard Worker  *
5*25da2beaSAndroid Build Coastguard Worker  * Description: Unit tests for the io_uring_setup 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 "liburing.h"
18*25da2beaSAndroid Build Coastguard Worker 
19*25da2beaSAndroid Build Coastguard Worker #include "../syscall.h"
20*25da2beaSAndroid Build Coastguard Worker 
features_string(struct io_uring_params * p)21*25da2beaSAndroid Build Coastguard Worker char *features_string(struct io_uring_params *p)
22*25da2beaSAndroid Build Coastguard Worker {
23*25da2beaSAndroid Build Coastguard Worker 	static char flagstr[64];
24*25da2beaSAndroid Build Coastguard Worker 
25*25da2beaSAndroid Build Coastguard Worker 	if (!p || !p->features)
26*25da2beaSAndroid Build Coastguard Worker 		return "none";
27*25da2beaSAndroid Build Coastguard Worker 
28*25da2beaSAndroid Build Coastguard Worker 	if (p->features & ~IORING_FEAT_SINGLE_MMAP) {
29*25da2beaSAndroid Build Coastguard Worker 		snprintf(flagstr, 64, "0x%.8x", p->features);
30*25da2beaSAndroid Build Coastguard Worker 		return flagstr;
31*25da2beaSAndroid Build Coastguard Worker 	}
32*25da2beaSAndroid Build Coastguard Worker 
33*25da2beaSAndroid Build Coastguard Worker 	if (p->features & IORING_FEAT_SINGLE_MMAP)
34*25da2beaSAndroid Build Coastguard Worker 		strncat(flagstr, "IORING_FEAT_SINGLE_MMAP", 64 - strlen(flagstr));
35*25da2beaSAndroid Build Coastguard Worker 
36*25da2beaSAndroid Build Coastguard Worker 	return flagstr;
37*25da2beaSAndroid Build Coastguard Worker }
38*25da2beaSAndroid Build Coastguard Worker 
39*25da2beaSAndroid Build Coastguard Worker /*
40*25da2beaSAndroid Build Coastguard Worker  * Attempt the call with the given args.  Return 0 when expect matches
41*25da2beaSAndroid Build Coastguard Worker  * the return value of the system call, 1 otherwise.
42*25da2beaSAndroid Build Coastguard Worker  */
43*25da2beaSAndroid Build Coastguard Worker char *
flags_string(struct io_uring_params * p)44*25da2beaSAndroid Build Coastguard Worker flags_string(struct io_uring_params *p)
45*25da2beaSAndroid Build Coastguard Worker {
46*25da2beaSAndroid Build Coastguard Worker 	static char flagstr[64];
47*25da2beaSAndroid Build Coastguard Worker 	int add_pipe = 0;
48*25da2beaSAndroid Build Coastguard Worker 
49*25da2beaSAndroid Build Coastguard Worker 	memset(flagstr, 0, sizeof(flagstr));
50*25da2beaSAndroid Build Coastguard Worker 
51*25da2beaSAndroid Build Coastguard Worker 	if (!p || p->flags == 0)
52*25da2beaSAndroid Build Coastguard Worker 		return "none";
53*25da2beaSAndroid Build Coastguard Worker 
54*25da2beaSAndroid Build Coastguard Worker 	/*
55*25da2beaSAndroid Build Coastguard Worker 	 * If unsupported flags are present, just print the bitmask.
56*25da2beaSAndroid Build Coastguard Worker 	 */
57*25da2beaSAndroid Build Coastguard Worker 	if (p->flags & ~(IORING_SETUP_IOPOLL | IORING_SETUP_SQPOLL |
58*25da2beaSAndroid Build Coastguard Worker 			 IORING_SETUP_SQ_AFF)) {
59*25da2beaSAndroid Build Coastguard Worker 		snprintf(flagstr, 64, "0x%.8x", p->flags);
60*25da2beaSAndroid Build Coastguard Worker 		return flagstr;
61*25da2beaSAndroid Build Coastguard Worker 	}
62*25da2beaSAndroid Build Coastguard Worker 
63*25da2beaSAndroid Build Coastguard Worker 	if (p->flags & IORING_SETUP_IOPOLL) {
64*25da2beaSAndroid Build Coastguard Worker 		strncat(flagstr, "IORING_SETUP_IOPOLL", 64 - strlen(flagstr));
65*25da2beaSAndroid Build Coastguard Worker 		add_pipe = 1;
66*25da2beaSAndroid Build Coastguard Worker 	}
67*25da2beaSAndroid Build Coastguard Worker 	if (p->flags & IORING_SETUP_SQPOLL) {
68*25da2beaSAndroid Build Coastguard Worker 		if (add_pipe)
69*25da2beaSAndroid Build Coastguard Worker 			strncat(flagstr, "|", 64 - strlen(flagstr));
70*25da2beaSAndroid Build Coastguard Worker 		else
71*25da2beaSAndroid Build Coastguard Worker 			add_pipe = 1;
72*25da2beaSAndroid Build Coastguard Worker 		strncat(flagstr, "IORING_SETUP_SQPOLL", 64 - strlen(flagstr));
73*25da2beaSAndroid Build Coastguard Worker 	}
74*25da2beaSAndroid Build Coastguard Worker 	if (p->flags & IORING_SETUP_SQ_AFF) {
75*25da2beaSAndroid Build Coastguard Worker 		if (add_pipe)
76*25da2beaSAndroid Build Coastguard Worker 			strncat(flagstr, "|", 64 - strlen(flagstr));
77*25da2beaSAndroid Build Coastguard Worker 		strncat(flagstr, "IORING_SETUP_SQ_AFF", 64 - strlen(flagstr));
78*25da2beaSAndroid Build Coastguard Worker 	}
79*25da2beaSAndroid Build Coastguard Worker 
80*25da2beaSAndroid Build Coastguard Worker 	return flagstr;
81*25da2beaSAndroid Build Coastguard Worker }
82*25da2beaSAndroid Build Coastguard Worker 
83*25da2beaSAndroid Build Coastguard Worker char *
dump_resv(struct io_uring_params * p)84*25da2beaSAndroid Build Coastguard Worker dump_resv(struct io_uring_params *p)
85*25da2beaSAndroid Build Coastguard Worker {
86*25da2beaSAndroid Build Coastguard Worker 	static char resvstr[4096];
87*25da2beaSAndroid Build Coastguard Worker 
88*25da2beaSAndroid Build Coastguard Worker 	if (!p)
89*25da2beaSAndroid Build Coastguard Worker 		return "";
90*25da2beaSAndroid Build Coastguard Worker 
91*25da2beaSAndroid Build Coastguard Worker 	sprintf(resvstr, "0x%.8x 0x%.8x 0x%.8x", p->resv[0],
92*25da2beaSAndroid Build Coastguard Worker 		p->resv[1], p->resv[2]);
93*25da2beaSAndroid Build Coastguard Worker 
94*25da2beaSAndroid Build Coastguard Worker 	return resvstr;
95*25da2beaSAndroid Build Coastguard Worker }
96*25da2beaSAndroid Build Coastguard Worker 
97*25da2beaSAndroid Build Coastguard Worker /* bogus: setup returns a valid fd on success... expect can't predict the
98*25da2beaSAndroid Build Coastguard Worker    fd we'll get, so this really only takes 1 parameter: error */
99*25da2beaSAndroid Build Coastguard Worker int
try_io_uring_setup(unsigned entries,struct io_uring_params * p,int expect,int error)100*25da2beaSAndroid Build Coastguard Worker try_io_uring_setup(unsigned entries, struct io_uring_params *p, int expect, int error)
101*25da2beaSAndroid Build Coastguard Worker {
102*25da2beaSAndroid Build Coastguard Worker 	int ret, err;
103*25da2beaSAndroid Build Coastguard Worker 
104*25da2beaSAndroid Build Coastguard Worker 	ret = __sys_io_uring_setup(entries, p);
105*25da2beaSAndroid Build Coastguard Worker 	if (ret != expect) {
106*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "expected %d, got %d\n", expect, ret);
107*25da2beaSAndroid Build Coastguard Worker 		/* if we got a valid uring, close it */
108*25da2beaSAndroid Build Coastguard Worker 		if (ret > 0)
109*25da2beaSAndroid Build Coastguard Worker 			close(ret);
110*25da2beaSAndroid Build Coastguard Worker 		return 1;
111*25da2beaSAndroid Build Coastguard Worker 	}
112*25da2beaSAndroid Build Coastguard Worker 	err = errno;
113*25da2beaSAndroid Build Coastguard Worker 	if (expect == -1 && error != err) {
114*25da2beaSAndroid Build Coastguard Worker 		if (err == EPERM && geteuid() != 0) {
115*25da2beaSAndroid Build Coastguard Worker 			printf("Needs root, not flagging as an error\n");
116*25da2beaSAndroid Build Coastguard Worker 			return 0;
117*25da2beaSAndroid Build Coastguard Worker 		}
118*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "expected errno %d, got %d\n", error, err);
119*25da2beaSAndroid Build Coastguard Worker 		return 1;
120*25da2beaSAndroid Build Coastguard Worker 	}
121*25da2beaSAndroid Build Coastguard Worker 
122*25da2beaSAndroid Build Coastguard Worker 	return 0;
123*25da2beaSAndroid Build Coastguard Worker }
124*25da2beaSAndroid Build Coastguard Worker 
125*25da2beaSAndroid Build Coastguard Worker int
main(int argc,char ** argv)126*25da2beaSAndroid Build Coastguard Worker main(int argc, char **argv)
127*25da2beaSAndroid Build Coastguard Worker {
128*25da2beaSAndroid Build Coastguard Worker 	int fd;
129*25da2beaSAndroid Build Coastguard Worker 	unsigned int status = 0;
130*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_params p;
131*25da2beaSAndroid Build Coastguard Worker 
132*25da2beaSAndroid Build Coastguard Worker 	if (argc > 1)
133*25da2beaSAndroid Build Coastguard Worker 		return 0;
134*25da2beaSAndroid Build Coastguard Worker 
135*25da2beaSAndroid Build Coastguard Worker 	memset(&p, 0, sizeof(p));
136*25da2beaSAndroid Build Coastguard Worker 	status |= try_io_uring_setup(0, &p, -1, EINVAL);
137*25da2beaSAndroid Build Coastguard Worker 	status |= try_io_uring_setup(1, NULL, -1, EFAULT);
138*25da2beaSAndroid Build Coastguard Worker 
139*25da2beaSAndroid Build Coastguard Worker 	/* resv array is non-zero */
140*25da2beaSAndroid Build Coastguard Worker 	memset(&p, 0, sizeof(p));
141*25da2beaSAndroid Build Coastguard Worker 	p.resv[0] = p.resv[1] = p.resv[2] = 1;
142*25da2beaSAndroid Build Coastguard Worker 	status |= try_io_uring_setup(1, &p, -1, EINVAL);
143*25da2beaSAndroid Build Coastguard Worker 
144*25da2beaSAndroid Build Coastguard Worker 	/* invalid flags */
145*25da2beaSAndroid Build Coastguard Worker 	memset(&p, 0, sizeof(p));
146*25da2beaSAndroid Build Coastguard Worker 	p.flags = ~0U;
147*25da2beaSAndroid Build Coastguard Worker 	status |= try_io_uring_setup(1, &p, -1, EINVAL);
148*25da2beaSAndroid Build Coastguard Worker 
149*25da2beaSAndroid Build Coastguard Worker 	/* IORING_SETUP_SQ_AFF set but not IORING_SETUP_SQPOLL */
150*25da2beaSAndroid Build Coastguard Worker 	memset(&p, 0, sizeof(p));
151*25da2beaSAndroid Build Coastguard Worker 	p.flags = IORING_SETUP_SQ_AFF;
152*25da2beaSAndroid Build Coastguard Worker 	status |= try_io_uring_setup(1, &p, -1, EINVAL);
153*25da2beaSAndroid Build Coastguard Worker 
154*25da2beaSAndroid Build Coastguard Worker 	/* attempt to bind to invalid cpu */
155*25da2beaSAndroid Build Coastguard Worker 	memset(&p, 0, sizeof(p));
156*25da2beaSAndroid Build Coastguard Worker 	p.flags = IORING_SETUP_SQPOLL | IORING_SETUP_SQ_AFF;
157*25da2beaSAndroid Build Coastguard Worker 	p.sq_thread_cpu = get_nprocs_conf();
158*25da2beaSAndroid Build Coastguard Worker 	status |= try_io_uring_setup(1, &p, -1, EINVAL);
159*25da2beaSAndroid Build Coastguard Worker 
160*25da2beaSAndroid Build Coastguard Worker 	/* I think we can limit a process to a set of cpus.  I assume
161*25da2beaSAndroid Build Coastguard Worker 	 * we shouldn't be able to setup a kernel thread outside of that.
162*25da2beaSAndroid Build Coastguard Worker 	 * try to do that. (task->cpus_allowed) */
163*25da2beaSAndroid Build Coastguard Worker 
164*25da2beaSAndroid Build Coastguard Worker 	/* read/write on io_uring_fd */
165*25da2beaSAndroid Build Coastguard Worker 	memset(&p, 0, sizeof(p));
166*25da2beaSAndroid Build Coastguard Worker 	fd = __sys_io_uring_setup(1, &p);
167*25da2beaSAndroid Build Coastguard Worker 	if (fd < 0) {
168*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "io_uring_setup failed with %d, expected success\n",
169*25da2beaSAndroid Build Coastguard Worker 		       errno);
170*25da2beaSAndroid Build Coastguard Worker 		status = 1;
171*25da2beaSAndroid Build Coastguard Worker 	} else {
172*25da2beaSAndroid Build Coastguard Worker 		char buf[4096];
173*25da2beaSAndroid Build Coastguard Worker 		int ret;
174*25da2beaSAndroid Build Coastguard Worker 		ret = read(fd, buf, 4096);
175*25da2beaSAndroid Build Coastguard Worker 		if (ret >= 0) {
176*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "read from io_uring fd succeeded.  expected fail\n");
177*25da2beaSAndroid Build Coastguard Worker 			status = 1;
178*25da2beaSAndroid Build Coastguard Worker 		}
179*25da2beaSAndroid Build Coastguard Worker 	}
180*25da2beaSAndroid Build Coastguard Worker 
181*25da2beaSAndroid Build Coastguard Worker 	if (!status)
182*25da2beaSAndroid Build Coastguard Worker 		return 0;
183*25da2beaSAndroid Build Coastguard Worker 
184*25da2beaSAndroid Build Coastguard Worker 	fprintf(stderr, "FAIL\n");
185*25da2beaSAndroid Build Coastguard Worker 	return -1;
186*25da2beaSAndroid Build Coastguard Worker }
187