• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: MIT */
2 /*
3  * Description: test io_uring fallocate
4  *
5  */
6 #include <errno.h>
7 #include <stdio.h>
8 #include <unistd.h>
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include <sys/resource.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <fcntl.h>
15 
16 #include "liburing.h"
17 
18 static int no_fallocate;
19 
test_fallocate_rlimit(struct io_uring * ring)20 static int test_fallocate_rlimit(struct io_uring *ring)
21 {
22 	struct io_uring_cqe *cqe;
23 	struct io_uring_sqe *sqe;
24 	struct rlimit rlim;
25 	char buf[32];
26 	int fd, ret;
27 
28 	if (getrlimit(RLIMIT_FSIZE, &rlim) < 0) {
29 		perror("getrlimit");
30 		return 1;
31 	}
32 	rlim.rlim_cur = 64 * 1024;
33 	rlim.rlim_max = 64 * 1024;
34 	if (setrlimit(RLIMIT_FSIZE, &rlim) < 0) {
35 		perror("setrlimit");
36 		return 1;
37 	}
38 
39 	sprintf(buf, "./XXXXXX");
40 	fd = mkstemp(buf);
41 	if (fd < 0) {
42 		perror("open");
43 		return 1;
44 	}
45 
46 	sqe = io_uring_get_sqe(ring);
47 	if (!sqe) {
48 		fprintf(stderr, "get sqe failed\n");
49 		goto err;
50 	}
51 	io_uring_prep_fallocate(sqe, fd, 0, 0, 128*1024);
52 
53 	ret = io_uring_submit(ring);
54 	if (ret <= 0) {
55 		fprintf(stderr, "sqe submit failed: %d\n", ret);
56 		goto err;
57 	}
58 
59 	ret = io_uring_wait_cqe(ring, &cqe);
60 	if (ret < 0) {
61 		fprintf(stderr, "wait completion %d\n", ret);
62 		goto err;
63 	}
64 
65 	if (cqe->res == -EINVAL) {
66 		fprintf(stdout, "Fallocate not supported, skipping\n");
67 		no_fallocate = 1;
68 		goto out;
69 	} else if (cqe->res != -EFBIG) {
70 		fprintf(stderr, "Expected -EFBIG: %d\n", cqe->res);
71 		goto err;
72 	}
73 	io_uring_cqe_seen(ring, cqe);
74 out:
75 	unlink(buf);
76 	return 0;
77 err:
78 	unlink(buf);
79 	return 1;
80 }
81 
test_fallocate(struct io_uring * ring)82 static int test_fallocate(struct io_uring *ring)
83 {
84 	struct io_uring_cqe *cqe;
85 	struct io_uring_sqe *sqe;
86 	struct stat st;
87 	char buf[32];
88 	int fd, ret;
89 
90 	sprintf(buf, "./XXXXXX");
91 	fd = mkstemp(buf);
92 	if (fd < 0) {
93 		perror("open");
94 		return 1;
95 	}
96 
97 	sqe = io_uring_get_sqe(ring);
98 	if (!sqe) {
99 		fprintf(stderr, "get sqe failed\n");
100 		goto err;
101 	}
102 	io_uring_prep_fallocate(sqe, fd, 0, 0, 128*1024);
103 
104 	ret = io_uring_submit(ring);
105 	if (ret <= 0) {
106 		fprintf(stderr, "sqe submit failed: %d\n", ret);
107 		goto err;
108 	}
109 
110 	ret = io_uring_wait_cqe(ring, &cqe);
111 	if (ret < 0) {
112 		fprintf(stderr, "wait completion %d\n", ret);
113 		goto err;
114 	}
115 
116 	if (cqe->res == -EINVAL) {
117 		fprintf(stdout, "Fallocate not supported, skipping\n");
118 		no_fallocate = 1;
119 		goto out;
120 	}
121 	if (cqe->res) {
122 		fprintf(stderr, "cqe->res=%d\n", cqe->res);
123 		goto err;
124 	}
125 	io_uring_cqe_seen(ring, cqe);
126 
127 	if (fstat(fd, &st) < 0) {
128 		perror("stat");
129 		goto err;
130 	}
131 
132 	if (st.st_size != 128*1024) {
133 		fprintf(stderr, "Size mismatch: %llu\n",
134 					(unsigned long long) st.st_size);
135 		goto err;
136 	}
137 
138 out:
139 	unlink(buf);
140 	return 0;
141 err:
142 	unlink(buf);
143 	return 1;
144 }
145 
test_fallocate_fsync(struct io_uring * ring)146 static int test_fallocate_fsync(struct io_uring *ring)
147 {
148 	struct io_uring_cqe *cqe;
149 	struct io_uring_sqe *sqe;
150 	struct stat st;
151 	char buf[32];
152 	int fd, ret, i;
153 
154 	if (no_fallocate)
155 		return 0;
156 
157 	sprintf(buf, "./XXXXXX");
158 	fd = mkstemp(buf);
159 	if (fd < 0) {
160 		perror("open");
161 		return 1;
162 	}
163 
164 	sqe = io_uring_get_sqe(ring);
165 	if (!sqe) {
166 		fprintf(stderr, "get sqe failed\n");
167 		goto err;
168 	}
169 	io_uring_prep_fallocate(sqe, fd, 0, 0, 128*1024);
170 	sqe->flags |= IOSQE_IO_LINK;
171 	sqe->user_data = 1;
172 
173 	sqe = io_uring_get_sqe(ring);
174 	if (!sqe) {
175 		fprintf(stderr, "get sqe failed\n");
176 		goto err;
177 	}
178 	io_uring_prep_fsync(sqe, fd, 0);
179 	sqe->user_data = 2;
180 
181 	ret = io_uring_submit(ring);
182 	if (ret <= 0) {
183 		fprintf(stderr, "sqe submit failed: %d\n", ret);
184 		goto err;
185 	}
186 
187 	for (i = 0; i < 2; i++) {
188 		ret = io_uring_wait_cqe(ring, &cqe);
189 		if (ret < 0) {
190 			fprintf(stderr, "wait completion %d\n", ret);
191 			goto err;
192 		}
193 		if (cqe->res) {
194 			fprintf(stderr, "cqe->res=%d,data=%" PRIu64 "\n", cqe->res,
195 							(uint64_t) cqe->user_data);
196 			goto err;
197 		}
198 		io_uring_cqe_seen(ring, cqe);
199 	}
200 
201 	if (fstat(fd, &st) < 0) {
202 		perror("stat");
203 		goto err;
204 	}
205 
206 	if (st.st_size != 128*1024) {
207 		fprintf(stderr, "Size mismatch: %llu\n",
208 					(unsigned long long) st.st_size);
209 		goto err;
210 	}
211 
212 	unlink(buf);
213 	return 0;
214 err:
215 	unlink(buf);
216 	return 1;
217 }
218 
main(int argc,char * argv[])219 int main(int argc, char *argv[])
220 {
221 	struct io_uring ring;
222 	int ret;
223 
224 	if (argc > 1)
225 		return 0;
226 
227 	ret = io_uring_queue_init(8, &ring, 0);
228 	if (ret) {
229 		fprintf(stderr, "ring setup failed\n");
230 		return 1;
231 	}
232 
233 	ret = test_fallocate(&ring);
234 	if (ret) {
235 		fprintf(stderr, "test_fallocate failed\n");
236 		return ret;
237 	}
238 
239 	ret = test_fallocate_fsync(&ring);
240 	if (ret) {
241 		fprintf(stderr, "test_fallocate_fsync failed\n");
242 		return ret;
243 	}
244 
245 	ret = test_fallocate_rlimit(&ring);
246 	if (ret) {
247 		fprintf(stderr, "test_fallocate_rlimit failed\n");
248 		return ret;
249 	}
250 
251 	return 0;
252 }
253