xref: /aosp_15_r20/external/liburing/test/file-verify.c (revision 25da2bea747f3a93b4c30fd9708b0618ef55a0e6)
1*25da2beaSAndroid Build Coastguard Worker /* SPDX-License-Identifier: MIT */
2*25da2beaSAndroid Build Coastguard Worker /*
3*25da2beaSAndroid Build Coastguard Worker  * Description: run various reads tests, verifying data
4*25da2beaSAndroid Build Coastguard Worker  *
5*25da2beaSAndroid Build Coastguard Worker  */
6*25da2beaSAndroid Build Coastguard Worker #include <errno.h>
7*25da2beaSAndroid Build Coastguard Worker #include <stdio.h>
8*25da2beaSAndroid Build Coastguard Worker #include <unistd.h>
9*25da2beaSAndroid Build Coastguard Worker #include <stdlib.h>
10*25da2beaSAndroid Build Coastguard Worker #include <string.h>
11*25da2beaSAndroid Build Coastguard Worker #include <fcntl.h>
12*25da2beaSAndroid Build Coastguard Worker #include <assert.h>
13*25da2beaSAndroid Build Coastguard Worker #include <string.h>
14*25da2beaSAndroid Build Coastguard Worker #include <sys/ioctl.h>
15*25da2beaSAndroid Build Coastguard Worker #include <sys/stat.h>
16*25da2beaSAndroid Build Coastguard Worker #include <linux/fs.h>
17*25da2beaSAndroid Build Coastguard Worker 
18*25da2beaSAndroid Build Coastguard Worker #include "helpers.h"
19*25da2beaSAndroid Build Coastguard Worker #include "liburing.h"
20*25da2beaSAndroid Build Coastguard Worker 
21*25da2beaSAndroid Build Coastguard Worker #define FSIZE		128*1024*1024
22*25da2beaSAndroid Build Coastguard Worker #define CHUNK_SIZE	131072
23*25da2beaSAndroid Build Coastguard Worker #define PUNCH_SIZE	32768
24*25da2beaSAndroid Build Coastguard Worker 
25*25da2beaSAndroid Build Coastguard Worker /*
26*25da2beaSAndroid Build Coastguard Worker  * 8 because it fits within the on-stack iov, 16 because it's larger than 8
27*25da2beaSAndroid Build Coastguard Worker  */
28*25da2beaSAndroid Build Coastguard Worker #define MIN_VECS	8
29*25da2beaSAndroid Build Coastguard Worker #define MAX_VECS	16
30*25da2beaSAndroid Build Coastguard Worker 
31*25da2beaSAndroid Build Coastguard Worker /*
32*25da2beaSAndroid Build Coastguard Worker  * Can be anything, let's just do something for a bit of parallellism
33*25da2beaSAndroid Build Coastguard Worker  */
34*25da2beaSAndroid Build Coastguard Worker #define READ_BATCH	16
35*25da2beaSAndroid Build Coastguard Worker 
36*25da2beaSAndroid Build Coastguard Worker /*
37*25da2beaSAndroid Build Coastguard Worker  * Each offset in the file has the offset / sizeof(int) stored for every
38*25da2beaSAndroid Build Coastguard Worker  * sizeof(int) address.
39*25da2beaSAndroid Build Coastguard Worker  */
verify_buf(void * buf,size_t size,off_t off)40*25da2beaSAndroid Build Coastguard Worker static int verify_buf(void *buf, size_t size, off_t off)
41*25da2beaSAndroid Build Coastguard Worker {
42*25da2beaSAndroid Build Coastguard Worker 	int i, u_in_buf = size / sizeof(unsigned int);
43*25da2beaSAndroid Build Coastguard Worker 	unsigned int *ptr;
44*25da2beaSAndroid Build Coastguard Worker 
45*25da2beaSAndroid Build Coastguard Worker 	off /= sizeof(unsigned int);
46*25da2beaSAndroid Build Coastguard Worker 	ptr = buf;
47*25da2beaSAndroid Build Coastguard Worker 	for (i = 0; i < u_in_buf; i++) {
48*25da2beaSAndroid Build Coastguard Worker 		if (off != *ptr) {
49*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "Found %u, wanted %lu\n", *ptr, off);
50*25da2beaSAndroid Build Coastguard Worker 			return 1;
51*25da2beaSAndroid Build Coastguard Worker 		}
52*25da2beaSAndroid Build Coastguard Worker 		ptr++;
53*25da2beaSAndroid Build Coastguard Worker 		off++;
54*25da2beaSAndroid Build Coastguard Worker 	}
55*25da2beaSAndroid Build Coastguard Worker 
56*25da2beaSAndroid Build Coastguard Worker 	return 0;
57*25da2beaSAndroid Build Coastguard Worker }
58*25da2beaSAndroid Build Coastguard Worker 
test_truncate(struct io_uring * ring,const char * fname,int buffered,int vectored,int provide_buf)59*25da2beaSAndroid Build Coastguard Worker static int test_truncate(struct io_uring *ring, const char *fname, int buffered,
60*25da2beaSAndroid Build Coastguard Worker 			 int vectored, int provide_buf)
61*25da2beaSAndroid Build Coastguard Worker {
62*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_cqe *cqe;
63*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_sqe *sqe;
64*25da2beaSAndroid Build Coastguard Worker 	struct iovec vec;
65*25da2beaSAndroid Build Coastguard Worker 	struct stat sb;
66*25da2beaSAndroid Build Coastguard Worker 	off_t punch_off, off, file_size;
67*25da2beaSAndroid Build Coastguard Worker 	void *buf = NULL;
68*25da2beaSAndroid Build Coastguard Worker 	int u_in_buf, i, ret, fd, first_pass = 1;
69*25da2beaSAndroid Build Coastguard Worker 	unsigned int *ptr;
70*25da2beaSAndroid Build Coastguard Worker 
71*25da2beaSAndroid Build Coastguard Worker 	if (buffered)
72*25da2beaSAndroid Build Coastguard Worker 		fd = open(fname, O_RDWR);
73*25da2beaSAndroid Build Coastguard Worker 	else
74*25da2beaSAndroid Build Coastguard Worker 		fd = open(fname, O_DIRECT | O_RDWR);
75*25da2beaSAndroid Build Coastguard Worker 	if (fd < 0) {
76*25da2beaSAndroid Build Coastguard Worker 		perror("open");
77*25da2beaSAndroid Build Coastguard Worker 		return 1;
78*25da2beaSAndroid Build Coastguard Worker 	}
79*25da2beaSAndroid Build Coastguard Worker 
80*25da2beaSAndroid Build Coastguard Worker 	if (fstat(fd, &sb) < 0) {
81*25da2beaSAndroid Build Coastguard Worker 		perror("stat");
82*25da2beaSAndroid Build Coastguard Worker 		close(fd);
83*25da2beaSAndroid Build Coastguard Worker 		return 1;
84*25da2beaSAndroid Build Coastguard Worker 	}
85*25da2beaSAndroid Build Coastguard Worker 
86*25da2beaSAndroid Build Coastguard Worker 	if (S_ISREG(sb.st_mode)) {
87*25da2beaSAndroid Build Coastguard Worker 		file_size = sb.st_size;
88*25da2beaSAndroid Build Coastguard Worker 	} else if (S_ISBLK(sb.st_mode)) {
89*25da2beaSAndroid Build Coastguard Worker 		unsigned long long bytes;
90*25da2beaSAndroid Build Coastguard Worker 
91*25da2beaSAndroid Build Coastguard Worker 		if (ioctl(fd, BLKGETSIZE64, &bytes) < 0) {
92*25da2beaSAndroid Build Coastguard Worker 			perror("ioctl");
93*25da2beaSAndroid Build Coastguard Worker 			close(fd);
94*25da2beaSAndroid Build Coastguard Worker 			return 1;
95*25da2beaSAndroid Build Coastguard Worker 		}
96*25da2beaSAndroid Build Coastguard Worker 		file_size = bytes;
97*25da2beaSAndroid Build Coastguard Worker 	} else {
98*25da2beaSAndroid Build Coastguard Worker 		goto out;
99*25da2beaSAndroid Build Coastguard Worker 	}
100*25da2beaSAndroid Build Coastguard Worker 
101*25da2beaSAndroid Build Coastguard Worker 	if (file_size < CHUNK_SIZE)
102*25da2beaSAndroid Build Coastguard Worker 		goto out;
103*25da2beaSAndroid Build Coastguard Worker 
104*25da2beaSAndroid Build Coastguard Worker 	t_posix_memalign(&buf, 4096, CHUNK_SIZE);
105*25da2beaSAndroid Build Coastguard Worker 
106*25da2beaSAndroid Build Coastguard Worker 	off = file_size - (CHUNK_SIZE / 2);
107*25da2beaSAndroid Build Coastguard Worker 	punch_off = off + CHUNK_SIZE / 4;
108*25da2beaSAndroid Build Coastguard Worker 
109*25da2beaSAndroid Build Coastguard Worker 	u_in_buf = CHUNK_SIZE / sizeof(unsigned int);
110*25da2beaSAndroid Build Coastguard Worker 	ptr = buf;
111*25da2beaSAndroid Build Coastguard Worker 	for (i = 0; i < u_in_buf; i++) {
112*25da2beaSAndroid Build Coastguard Worker 		*ptr = i;
113*25da2beaSAndroid Build Coastguard Worker 		ptr++;
114*25da2beaSAndroid Build Coastguard Worker 	}
115*25da2beaSAndroid Build Coastguard Worker 	ret = pwrite(fd, buf, CHUNK_SIZE / 2, off);
116*25da2beaSAndroid Build Coastguard Worker 	if (ret < 0) {
117*25da2beaSAndroid Build Coastguard Worker 		perror("pwrite");
118*25da2beaSAndroid Build Coastguard Worker 		goto err;
119*25da2beaSAndroid Build Coastguard Worker 	} else if (ret != CHUNK_SIZE / 2)
120*25da2beaSAndroid Build Coastguard Worker 		goto out;
121*25da2beaSAndroid Build Coastguard Worker 
122*25da2beaSAndroid Build Coastguard Worker again:
123*25da2beaSAndroid Build Coastguard Worker 	/*
124*25da2beaSAndroid Build Coastguard Worker 	 * Read in last bit of file so it's known cached, then remove half of that
125*25da2beaSAndroid Build Coastguard Worker 	 * last bit so we get a short read that needs retry
126*25da2beaSAndroid Build Coastguard Worker 	 */
127*25da2beaSAndroid Build Coastguard Worker 	ret = pread(fd, buf, CHUNK_SIZE / 2, off);
128*25da2beaSAndroid Build Coastguard Worker 	if (ret < 0) {
129*25da2beaSAndroid Build Coastguard Worker 		perror("pread");
130*25da2beaSAndroid Build Coastguard Worker 		goto err;
131*25da2beaSAndroid Build Coastguard Worker 	} else if (ret != CHUNK_SIZE / 2)
132*25da2beaSAndroid Build Coastguard Worker 		goto out;
133*25da2beaSAndroid Build Coastguard Worker 
134*25da2beaSAndroid Build Coastguard Worker 	if (posix_fadvise(fd, punch_off, CHUNK_SIZE / 4, POSIX_FADV_DONTNEED) < 0) {
135*25da2beaSAndroid Build Coastguard Worker 		perror("posix_fadivse");
136*25da2beaSAndroid Build Coastguard Worker 		goto err;
137*25da2beaSAndroid Build Coastguard Worker 	}
138*25da2beaSAndroid Build Coastguard Worker 
139*25da2beaSAndroid Build Coastguard Worker 	if (provide_buf) {
140*25da2beaSAndroid Build Coastguard Worker 		sqe = io_uring_get_sqe(ring);
141*25da2beaSAndroid Build Coastguard Worker 		io_uring_prep_provide_buffers(sqe, buf, CHUNK_SIZE, 1, 0, 0);
142*25da2beaSAndroid Build Coastguard Worker 		ret = io_uring_submit(ring);
143*25da2beaSAndroid Build Coastguard Worker 		if (ret != 1) {
144*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "submit failed %d\n", ret);
145*25da2beaSAndroid Build Coastguard Worker 			goto err;
146*25da2beaSAndroid Build Coastguard Worker 		}
147*25da2beaSAndroid Build Coastguard Worker 		ret = io_uring_wait_cqe(ring, &cqe);
148*25da2beaSAndroid Build Coastguard Worker 		if (ret < 0) {
149*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "wait completion %d\n", ret);
150*25da2beaSAndroid Build Coastguard Worker 			goto err;
151*25da2beaSAndroid Build Coastguard Worker 		}
152*25da2beaSAndroid Build Coastguard Worker 		ret = cqe->res;
153*25da2beaSAndroid Build Coastguard Worker 		io_uring_cqe_seen(ring, cqe);
154*25da2beaSAndroid Build Coastguard Worker 		if (ret) {
155*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "Provide buffer failed %d\n", ret);
156*25da2beaSAndroid Build Coastguard Worker 			goto err;
157*25da2beaSAndroid Build Coastguard Worker 		}
158*25da2beaSAndroid Build Coastguard Worker 	}
159*25da2beaSAndroid Build Coastguard Worker 
160*25da2beaSAndroid Build Coastguard Worker 	sqe = io_uring_get_sqe(ring);
161*25da2beaSAndroid Build Coastguard Worker 	if (!sqe) {
162*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "get sqe failed\n");
163*25da2beaSAndroid Build Coastguard Worker 		goto err;
164*25da2beaSAndroid Build Coastguard Worker 	}
165*25da2beaSAndroid Build Coastguard Worker 
166*25da2beaSAndroid Build Coastguard Worker 	if (vectored) {
167*25da2beaSAndroid Build Coastguard Worker 		assert(!provide_buf);
168*25da2beaSAndroid Build Coastguard Worker 		vec.iov_base = buf;
169*25da2beaSAndroid Build Coastguard Worker 		vec.iov_len = CHUNK_SIZE;
170*25da2beaSAndroid Build Coastguard Worker 		io_uring_prep_readv(sqe, fd, &vec, 1, off);
171*25da2beaSAndroid Build Coastguard Worker 	} else {
172*25da2beaSAndroid Build Coastguard Worker 		if (provide_buf) {
173*25da2beaSAndroid Build Coastguard Worker 			io_uring_prep_read(sqe, fd, NULL, CHUNK_SIZE, off);
174*25da2beaSAndroid Build Coastguard Worker 			sqe->flags |= IOSQE_BUFFER_SELECT;
175*25da2beaSAndroid Build Coastguard Worker 		} else {
176*25da2beaSAndroid Build Coastguard Worker 			io_uring_prep_read(sqe, fd, buf, CHUNK_SIZE, off);
177*25da2beaSAndroid Build Coastguard Worker 		}
178*25da2beaSAndroid Build Coastguard Worker 	}
179*25da2beaSAndroid Build Coastguard Worker 	memset(buf, 0, CHUNK_SIZE);
180*25da2beaSAndroid Build Coastguard Worker 
181*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_submit(ring);
182*25da2beaSAndroid Build Coastguard Worker 	if (ret != 1) {
183*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "Submit failed %d\n", ret);
184*25da2beaSAndroid Build Coastguard Worker 		goto err;
185*25da2beaSAndroid Build Coastguard Worker 	}
186*25da2beaSAndroid Build Coastguard Worker 
187*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_wait_cqe(ring, &cqe);
188*25da2beaSAndroid Build Coastguard Worker 	if (ret < 0) {
189*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "wait completion %d\n", ret);
190*25da2beaSAndroid Build Coastguard Worker 		goto err;
191*25da2beaSAndroid Build Coastguard Worker 	}
192*25da2beaSAndroid Build Coastguard Worker 
193*25da2beaSAndroid Build Coastguard Worker 	ret = cqe->res;
194*25da2beaSAndroid Build Coastguard Worker 	io_uring_cqe_seen(ring, cqe);
195*25da2beaSAndroid Build Coastguard Worker 	if (ret != CHUNK_SIZE / 2) {
196*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "Unexpected truncated read %d\n", ret);
197*25da2beaSAndroid Build Coastguard Worker 		goto err;
198*25da2beaSAndroid Build Coastguard Worker 	}
199*25da2beaSAndroid Build Coastguard Worker 
200*25da2beaSAndroid Build Coastguard Worker 	if (verify_buf(buf, CHUNK_SIZE / 2, 0))
201*25da2beaSAndroid Build Coastguard Worker 		goto err;
202*25da2beaSAndroid Build Coastguard Worker 
203*25da2beaSAndroid Build Coastguard Worker 	/*
204*25da2beaSAndroid Build Coastguard Worker 	 * Repeat, but punch first part instead of last
205*25da2beaSAndroid Build Coastguard Worker 	 */
206*25da2beaSAndroid Build Coastguard Worker 	if (first_pass) {
207*25da2beaSAndroid Build Coastguard Worker 		punch_off = file_size - CHUNK_SIZE / 4;
208*25da2beaSAndroid Build Coastguard Worker 		first_pass = 0;
209*25da2beaSAndroid Build Coastguard Worker 		goto again;
210*25da2beaSAndroid Build Coastguard Worker 	}
211*25da2beaSAndroid Build Coastguard Worker 
212*25da2beaSAndroid Build Coastguard Worker out:
213*25da2beaSAndroid Build Coastguard Worker 	free(buf);
214*25da2beaSAndroid Build Coastguard Worker 	close(fd);
215*25da2beaSAndroid Build Coastguard Worker 	return 0;
216*25da2beaSAndroid Build Coastguard Worker err:
217*25da2beaSAndroid Build Coastguard Worker 	free(buf);
218*25da2beaSAndroid Build Coastguard Worker 	close(fd);
219*25da2beaSAndroid Build Coastguard Worker 	return 1;
220*25da2beaSAndroid Build Coastguard Worker }
221*25da2beaSAndroid Build Coastguard Worker 
222*25da2beaSAndroid Build Coastguard Worker enum {
223*25da2beaSAndroid Build Coastguard Worker 	PUNCH_NONE,
224*25da2beaSAndroid Build Coastguard Worker 	PUNCH_FRONT,
225*25da2beaSAndroid Build Coastguard Worker 	PUNCH_MIDDLE,
226*25da2beaSAndroid Build Coastguard Worker 	PUNCH_END,
227*25da2beaSAndroid Build Coastguard Worker };
228*25da2beaSAndroid Build Coastguard Worker 
229*25da2beaSAndroid Build Coastguard Worker /*
230*25da2beaSAndroid Build Coastguard Worker  * For each chunk in file, DONTNEED a start, end, or middle segment of it.
231*25da2beaSAndroid Build Coastguard Worker  * We enter here with the file fully cached every time, either freshly
232*25da2beaSAndroid Build Coastguard Worker  * written or after other reads. This forces (at least) the buffered reads
233*25da2beaSAndroid Build Coastguard Worker  * to be handled incrementally, exercising that path.
234*25da2beaSAndroid Build Coastguard Worker  */
do_punch(int fd)235*25da2beaSAndroid Build Coastguard Worker static int do_punch(int fd)
236*25da2beaSAndroid Build Coastguard Worker {
237*25da2beaSAndroid Build Coastguard Worker 	off_t offset = 0;
238*25da2beaSAndroid Build Coastguard Worker 	int punch_type;
239*25da2beaSAndroid Build Coastguard Worker 
240*25da2beaSAndroid Build Coastguard Worker 	while (offset + CHUNK_SIZE <= FSIZE) {
241*25da2beaSAndroid Build Coastguard Worker 		off_t punch_off;
242*25da2beaSAndroid Build Coastguard Worker 
243*25da2beaSAndroid Build Coastguard Worker 		punch_type = rand() % (PUNCH_END + 1);
244*25da2beaSAndroid Build Coastguard Worker 		switch (punch_type) {
245*25da2beaSAndroid Build Coastguard Worker 		default:
246*25da2beaSAndroid Build Coastguard Worker 		case PUNCH_NONE:
247*25da2beaSAndroid Build Coastguard Worker 			punch_off = -1; /* gcc... */
248*25da2beaSAndroid Build Coastguard Worker 			break;
249*25da2beaSAndroid Build Coastguard Worker 		case PUNCH_FRONT:
250*25da2beaSAndroid Build Coastguard Worker 			punch_off = offset;
251*25da2beaSAndroid Build Coastguard Worker 			break;
252*25da2beaSAndroid Build Coastguard Worker 		case PUNCH_MIDDLE:
253*25da2beaSAndroid Build Coastguard Worker 			punch_off = offset + PUNCH_SIZE;
254*25da2beaSAndroid Build Coastguard Worker 			break;
255*25da2beaSAndroid Build Coastguard Worker 		case PUNCH_END:
256*25da2beaSAndroid Build Coastguard Worker 			punch_off = offset + CHUNK_SIZE - PUNCH_SIZE;
257*25da2beaSAndroid Build Coastguard Worker 			break;
258*25da2beaSAndroid Build Coastguard Worker 		}
259*25da2beaSAndroid Build Coastguard Worker 
260*25da2beaSAndroid Build Coastguard Worker 		offset += CHUNK_SIZE;
261*25da2beaSAndroid Build Coastguard Worker 		if (punch_type == PUNCH_NONE)
262*25da2beaSAndroid Build Coastguard Worker 			continue;
263*25da2beaSAndroid Build Coastguard Worker 		if (posix_fadvise(fd, punch_off, PUNCH_SIZE, POSIX_FADV_DONTNEED) < 0) {
264*25da2beaSAndroid Build Coastguard Worker 			perror("posix_fadivse");
265*25da2beaSAndroid Build Coastguard Worker 			return 1;
266*25da2beaSAndroid Build Coastguard Worker 		}
267*25da2beaSAndroid Build Coastguard Worker 	}
268*25da2beaSAndroid Build Coastguard Worker 
269*25da2beaSAndroid Build Coastguard Worker 	return 0;
270*25da2beaSAndroid Build Coastguard Worker }
271*25da2beaSAndroid Build Coastguard Worker 
provide_buffers(struct io_uring * ring,void ** buf)272*25da2beaSAndroid Build Coastguard Worker static int provide_buffers(struct io_uring *ring, void **buf)
273*25da2beaSAndroid Build Coastguard Worker {
274*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_cqe *cqe;
275*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_sqe *sqe;
276*25da2beaSAndroid Build Coastguard Worker 	int i, ret;
277*25da2beaSAndroid Build Coastguard Worker 
278*25da2beaSAndroid Build Coastguard Worker 	/* real use case would have one buffer chopped up, but... */
279*25da2beaSAndroid Build Coastguard Worker 	for (i = 0; i < READ_BATCH; i++) {
280*25da2beaSAndroid Build Coastguard Worker 		sqe = io_uring_get_sqe(ring);
281*25da2beaSAndroid Build Coastguard Worker 		io_uring_prep_provide_buffers(sqe, buf[i], CHUNK_SIZE, 1, 0, i);
282*25da2beaSAndroid Build Coastguard Worker 	}
283*25da2beaSAndroid Build Coastguard Worker 
284*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_submit(ring);
285*25da2beaSAndroid Build Coastguard Worker 	if (ret != READ_BATCH) {
286*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "Submit failed %d\n", ret);
287*25da2beaSAndroid Build Coastguard Worker 		return 1;
288*25da2beaSAndroid Build Coastguard Worker 	}
289*25da2beaSAndroid Build Coastguard Worker 
290*25da2beaSAndroid Build Coastguard Worker 	for (i = 0; i < READ_BATCH; i++) {
291*25da2beaSAndroid Build Coastguard Worker 		ret = io_uring_wait_cqe(ring, &cqe);
292*25da2beaSAndroid Build Coastguard Worker 		if (ret) {
293*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "wait cqe %d\n", ret);
294*25da2beaSAndroid Build Coastguard Worker 			return 1;
295*25da2beaSAndroid Build Coastguard Worker 		}
296*25da2beaSAndroid Build Coastguard Worker 		if (cqe->res < 0) {
297*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "cqe res provide %d\n", cqe->res);
298*25da2beaSAndroid Build Coastguard Worker 			return 1;
299*25da2beaSAndroid Build Coastguard Worker 		}
300*25da2beaSAndroid Build Coastguard Worker 		io_uring_cqe_seen(ring, cqe);
301*25da2beaSAndroid Build Coastguard Worker 	}
302*25da2beaSAndroid Build Coastguard Worker 
303*25da2beaSAndroid Build Coastguard Worker 	return 0;
304*25da2beaSAndroid Build Coastguard Worker }
305*25da2beaSAndroid Build Coastguard Worker 
test(struct io_uring * ring,const char * fname,int buffered,int vectored,int small_vecs,int registered,int provide)306*25da2beaSAndroid Build Coastguard Worker static int test(struct io_uring *ring, const char *fname, int buffered,
307*25da2beaSAndroid Build Coastguard Worker 		int vectored, int small_vecs, int registered, int provide)
308*25da2beaSAndroid Build Coastguard Worker {
309*25da2beaSAndroid Build Coastguard Worker 	struct iovec vecs[READ_BATCH][MAX_VECS];
310*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_cqe *cqe;
311*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_sqe *sqe;
312*25da2beaSAndroid Build Coastguard Worker 	void *buf[READ_BATCH];
313*25da2beaSAndroid Build Coastguard Worker 	int ret, fd, flags;
314*25da2beaSAndroid Build Coastguard Worker 	int i, j, nr_vecs;
315*25da2beaSAndroid Build Coastguard Worker 	off_t off, voff;
316*25da2beaSAndroid Build Coastguard Worker 	size_t left;
317*25da2beaSAndroid Build Coastguard Worker 
318*25da2beaSAndroid Build Coastguard Worker 	if (registered) {
319*25da2beaSAndroid Build Coastguard Worker 		assert(!provide);
320*25da2beaSAndroid Build Coastguard Worker 		assert(!vectored && !small_vecs);
321*25da2beaSAndroid Build Coastguard Worker 	}
322*25da2beaSAndroid Build Coastguard Worker 	if (provide) {
323*25da2beaSAndroid Build Coastguard Worker 		assert(!registered);
324*25da2beaSAndroid Build Coastguard Worker 		assert(!vectored && !small_vecs);
325*25da2beaSAndroid Build Coastguard Worker 	}
326*25da2beaSAndroid Build Coastguard Worker 
327*25da2beaSAndroid Build Coastguard Worker 	flags = O_RDONLY;
328*25da2beaSAndroid Build Coastguard Worker 	if (!buffered)
329*25da2beaSAndroid Build Coastguard Worker 		flags |= O_DIRECT;
330*25da2beaSAndroid Build Coastguard Worker 	fd = open(fname, flags);
331*25da2beaSAndroid Build Coastguard Worker 	if (fd < 0) {
332*25da2beaSAndroid Build Coastguard Worker 		perror("open");
333*25da2beaSAndroid Build Coastguard Worker 		return 1;
334*25da2beaSAndroid Build Coastguard Worker 	}
335*25da2beaSAndroid Build Coastguard Worker 
336*25da2beaSAndroid Build Coastguard Worker 	if (do_punch(fd))
337*25da2beaSAndroid Build Coastguard Worker 		return 1;
338*25da2beaSAndroid Build Coastguard Worker 
339*25da2beaSAndroid Build Coastguard Worker 	if (vectored) {
340*25da2beaSAndroid Build Coastguard Worker 		if (small_vecs)
341*25da2beaSAndroid Build Coastguard Worker 			nr_vecs = MIN_VECS;
342*25da2beaSAndroid Build Coastguard Worker 		else
343*25da2beaSAndroid Build Coastguard Worker 			nr_vecs = MAX_VECS;
344*25da2beaSAndroid Build Coastguard Worker 
345*25da2beaSAndroid Build Coastguard Worker 		for (j = 0; j < READ_BATCH; j++) {
346*25da2beaSAndroid Build Coastguard Worker 			for (i = 0; i < nr_vecs; i++) {
347*25da2beaSAndroid Build Coastguard Worker 				void *ptr;
348*25da2beaSAndroid Build Coastguard Worker 
349*25da2beaSAndroid Build Coastguard Worker 				t_posix_memalign(&ptr, 4096, CHUNK_SIZE / nr_vecs);
350*25da2beaSAndroid Build Coastguard Worker 				vecs[j][i].iov_base = ptr;
351*25da2beaSAndroid Build Coastguard Worker 				vecs[j][i].iov_len = CHUNK_SIZE / nr_vecs;
352*25da2beaSAndroid Build Coastguard Worker 			}
353*25da2beaSAndroid Build Coastguard Worker 		}
354*25da2beaSAndroid Build Coastguard Worker 	} else {
355*25da2beaSAndroid Build Coastguard Worker 		for (j = 0; j < READ_BATCH; j++)
356*25da2beaSAndroid Build Coastguard Worker 			t_posix_memalign(&buf[j], 4096, CHUNK_SIZE);
357*25da2beaSAndroid Build Coastguard Worker 		nr_vecs = 0;
358*25da2beaSAndroid Build Coastguard Worker 	}
359*25da2beaSAndroid Build Coastguard Worker 
360*25da2beaSAndroid Build Coastguard Worker 	if (registered) {
361*25da2beaSAndroid Build Coastguard Worker 		struct iovec v[READ_BATCH];
362*25da2beaSAndroid Build Coastguard Worker 
363*25da2beaSAndroid Build Coastguard Worker 		for (i = 0; i < READ_BATCH; i++) {
364*25da2beaSAndroid Build Coastguard Worker 			v[i].iov_base = buf[i];
365*25da2beaSAndroid Build Coastguard Worker 			v[i].iov_len = CHUNK_SIZE;
366*25da2beaSAndroid Build Coastguard Worker 		}
367*25da2beaSAndroid Build Coastguard Worker 		ret = io_uring_register_buffers(ring, v, READ_BATCH);
368*25da2beaSAndroid Build Coastguard Worker 		if (ret) {
369*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "Error buffer reg %d\n", ret);
370*25da2beaSAndroid Build Coastguard Worker 			goto err;
371*25da2beaSAndroid Build Coastguard Worker 		}
372*25da2beaSAndroid Build Coastguard Worker 	}
373*25da2beaSAndroid Build Coastguard Worker 
374*25da2beaSAndroid Build Coastguard Worker 	i = 0;
375*25da2beaSAndroid Build Coastguard Worker 	left = FSIZE;
376*25da2beaSAndroid Build Coastguard Worker 	off = 0;
377*25da2beaSAndroid Build Coastguard Worker 	while (left) {
378*25da2beaSAndroid Build Coastguard Worker 		int pending = 0;
379*25da2beaSAndroid Build Coastguard Worker 
380*25da2beaSAndroid Build Coastguard Worker 		if (provide && provide_buffers(ring, buf))
381*25da2beaSAndroid Build Coastguard Worker 			goto err;
382*25da2beaSAndroid Build Coastguard Worker 
383*25da2beaSAndroid Build Coastguard Worker 		for (i = 0; i < READ_BATCH; i++) {
384*25da2beaSAndroid Build Coastguard Worker 			size_t this = left;
385*25da2beaSAndroid Build Coastguard Worker 
386*25da2beaSAndroid Build Coastguard Worker 			if (this > CHUNK_SIZE)
387*25da2beaSAndroid Build Coastguard Worker 				this = CHUNK_SIZE;
388*25da2beaSAndroid Build Coastguard Worker 
389*25da2beaSAndroid Build Coastguard Worker 			sqe = io_uring_get_sqe(ring);
390*25da2beaSAndroid Build Coastguard Worker 			if (!sqe) {
391*25da2beaSAndroid Build Coastguard Worker 				fprintf(stderr, "get sqe failed\n");
392*25da2beaSAndroid Build Coastguard Worker 				goto err;
393*25da2beaSAndroid Build Coastguard Worker 			}
394*25da2beaSAndroid Build Coastguard Worker 
395*25da2beaSAndroid Build Coastguard Worker 			if (vectored) {
396*25da2beaSAndroid Build Coastguard Worker 				io_uring_prep_readv(sqe, fd, vecs[i], nr_vecs, off);
397*25da2beaSAndroid Build Coastguard Worker 			} else {
398*25da2beaSAndroid Build Coastguard Worker 				if (registered) {
399*25da2beaSAndroid Build Coastguard Worker 					io_uring_prep_read_fixed(sqe, fd, buf[i], this, off, i);
400*25da2beaSAndroid Build Coastguard Worker 				} else if (provide) {
401*25da2beaSAndroid Build Coastguard Worker 					io_uring_prep_read(sqe, fd, NULL, this, off);
402*25da2beaSAndroid Build Coastguard Worker 					sqe->flags |= IOSQE_BUFFER_SELECT;
403*25da2beaSAndroid Build Coastguard Worker 				} else {
404*25da2beaSAndroid Build Coastguard Worker 					io_uring_prep_read(sqe, fd, buf[i], this, off);
405*25da2beaSAndroid Build Coastguard Worker 				}
406*25da2beaSAndroid Build Coastguard Worker 			}
407*25da2beaSAndroid Build Coastguard Worker 			sqe->user_data = ((uint64_t)off << 32) | i;
408*25da2beaSAndroid Build Coastguard Worker 			off += this;
409*25da2beaSAndroid Build Coastguard Worker 			left -= this;
410*25da2beaSAndroid Build Coastguard Worker 			pending++;
411*25da2beaSAndroid Build Coastguard Worker 			if (!left)
412*25da2beaSAndroid Build Coastguard Worker 				break;
413*25da2beaSAndroid Build Coastguard Worker 		}
414*25da2beaSAndroid Build Coastguard Worker 
415*25da2beaSAndroid Build Coastguard Worker 		ret = io_uring_submit(ring);
416*25da2beaSAndroid Build Coastguard Worker 		if (ret != pending) {
417*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "sqe submit failed: %d\n", ret);
418*25da2beaSAndroid Build Coastguard Worker 			goto err;
419*25da2beaSAndroid Build Coastguard Worker 		}
420*25da2beaSAndroid Build Coastguard Worker 
421*25da2beaSAndroid Build Coastguard Worker 		for (i = 0; i < pending; i++) {
422*25da2beaSAndroid Build Coastguard Worker 			int index;
423*25da2beaSAndroid Build Coastguard Worker 
424*25da2beaSAndroid Build Coastguard Worker 			ret = io_uring_wait_cqe(ring, &cqe);
425*25da2beaSAndroid Build Coastguard Worker 			if (ret < 0) {
426*25da2beaSAndroid Build Coastguard Worker 				fprintf(stderr, "wait completion %d\n", ret);
427*25da2beaSAndroid Build Coastguard Worker 				goto err;
428*25da2beaSAndroid Build Coastguard Worker 			}
429*25da2beaSAndroid Build Coastguard Worker 			if (cqe->res < 0) {
430*25da2beaSAndroid Build Coastguard Worker 				fprintf(stderr, "bad read %d, read %d\n", cqe->res, i);
431*25da2beaSAndroid Build Coastguard Worker 				goto err;
432*25da2beaSAndroid Build Coastguard Worker 			}
433*25da2beaSAndroid Build Coastguard Worker 			if (cqe->flags & IORING_CQE_F_BUFFER)
434*25da2beaSAndroid Build Coastguard Worker 				index = cqe->flags >> 16;
435*25da2beaSAndroid Build Coastguard Worker 			else
436*25da2beaSAndroid Build Coastguard Worker 				index = cqe->user_data & 0xffffffff;
437*25da2beaSAndroid Build Coastguard Worker 			voff = cqe->user_data >> 32;
438*25da2beaSAndroid Build Coastguard Worker 			io_uring_cqe_seen(ring, cqe);
439*25da2beaSAndroid Build Coastguard Worker 			if (vectored) {
440*25da2beaSAndroid Build Coastguard Worker 				for (j = 0; j < nr_vecs; j++) {
441*25da2beaSAndroid Build Coastguard Worker 					void *buf = vecs[index][j].iov_base;
442*25da2beaSAndroid Build Coastguard Worker 					size_t len = vecs[index][j].iov_len;
443*25da2beaSAndroid Build Coastguard Worker 
444*25da2beaSAndroid Build Coastguard Worker 					if (verify_buf(buf, len, voff))
445*25da2beaSAndroid Build Coastguard Worker 						goto err;
446*25da2beaSAndroid Build Coastguard Worker 					voff += len;
447*25da2beaSAndroid Build Coastguard Worker 				}
448*25da2beaSAndroid Build Coastguard Worker 			} else {
449*25da2beaSAndroid Build Coastguard Worker 				if (verify_buf(buf[index], CHUNK_SIZE, voff))
450*25da2beaSAndroid Build Coastguard Worker 					goto err;
451*25da2beaSAndroid Build Coastguard Worker 			}
452*25da2beaSAndroid Build Coastguard Worker 		}
453*25da2beaSAndroid Build Coastguard Worker 	}
454*25da2beaSAndroid Build Coastguard Worker 
455*25da2beaSAndroid Build Coastguard Worker 	ret = 0;
456*25da2beaSAndroid Build Coastguard Worker done:
457*25da2beaSAndroid Build Coastguard Worker 	if (registered)
458*25da2beaSAndroid Build Coastguard Worker 		io_uring_unregister_buffers(ring);
459*25da2beaSAndroid Build Coastguard Worker 	if (vectored) {
460*25da2beaSAndroid Build Coastguard Worker 		for (j = 0; j < READ_BATCH; j++)
461*25da2beaSAndroid Build Coastguard Worker 			for (i = 0; i < nr_vecs; i++)
462*25da2beaSAndroid Build Coastguard Worker 				free(vecs[j][i].iov_base);
463*25da2beaSAndroid Build Coastguard Worker 	} else {
464*25da2beaSAndroid Build Coastguard Worker 		for (j = 0; j < READ_BATCH; j++)
465*25da2beaSAndroid Build Coastguard Worker 			free(buf[j]);
466*25da2beaSAndroid Build Coastguard Worker 	}
467*25da2beaSAndroid Build Coastguard Worker 	close(fd);
468*25da2beaSAndroid Build Coastguard Worker 	return ret;
469*25da2beaSAndroid Build Coastguard Worker err:
470*25da2beaSAndroid Build Coastguard Worker 	ret = 1;
471*25da2beaSAndroid Build Coastguard Worker 	goto done;
472*25da2beaSAndroid Build Coastguard Worker }
473*25da2beaSAndroid Build Coastguard Worker 
fill_pattern(const char * fname)474*25da2beaSAndroid Build Coastguard Worker static int fill_pattern(const char *fname)
475*25da2beaSAndroid Build Coastguard Worker {
476*25da2beaSAndroid Build Coastguard Worker 	size_t left = FSIZE;
477*25da2beaSAndroid Build Coastguard Worker 	unsigned int val, *ptr;
478*25da2beaSAndroid Build Coastguard Worker 	void *buf;
479*25da2beaSAndroid Build Coastguard Worker 	int fd, i;
480*25da2beaSAndroid Build Coastguard Worker 
481*25da2beaSAndroid Build Coastguard Worker 	fd = open(fname, O_WRONLY);
482*25da2beaSAndroid Build Coastguard Worker 	if (fd < 0) {
483*25da2beaSAndroid Build Coastguard Worker 		perror("open");
484*25da2beaSAndroid Build Coastguard Worker 		return 1;
485*25da2beaSAndroid Build Coastguard Worker 	}
486*25da2beaSAndroid Build Coastguard Worker 
487*25da2beaSAndroid Build Coastguard Worker 	val = 0;
488*25da2beaSAndroid Build Coastguard Worker 	buf = t_malloc(4096);
489*25da2beaSAndroid Build Coastguard Worker 	while (left) {
490*25da2beaSAndroid Build Coastguard Worker 		int u_in_buf = 4096 / sizeof(val);
491*25da2beaSAndroid Build Coastguard Worker 		size_t this = left;
492*25da2beaSAndroid Build Coastguard Worker 
493*25da2beaSAndroid Build Coastguard Worker 		if (this > 4096)
494*25da2beaSAndroid Build Coastguard Worker 			this = 4096;
495*25da2beaSAndroid Build Coastguard Worker 		ptr = buf;
496*25da2beaSAndroid Build Coastguard Worker 		for (i = 0; i < u_in_buf; i++) {
497*25da2beaSAndroid Build Coastguard Worker 			*ptr = val;
498*25da2beaSAndroid Build Coastguard Worker 			val++;
499*25da2beaSAndroid Build Coastguard Worker 			ptr++;
500*25da2beaSAndroid Build Coastguard Worker 		}
501*25da2beaSAndroid Build Coastguard Worker 		if (write(fd, buf, 4096) != 4096)
502*25da2beaSAndroid Build Coastguard Worker 			return 1;
503*25da2beaSAndroid Build Coastguard Worker 		left -= 4096;
504*25da2beaSAndroid Build Coastguard Worker 	}
505*25da2beaSAndroid Build Coastguard Worker 
506*25da2beaSAndroid Build Coastguard Worker 	fsync(fd);
507*25da2beaSAndroid Build Coastguard Worker 	close(fd);
508*25da2beaSAndroid Build Coastguard Worker 	free(buf);
509*25da2beaSAndroid Build Coastguard Worker 	return 0;
510*25da2beaSAndroid Build Coastguard Worker }
511*25da2beaSAndroid Build Coastguard Worker 
main(int argc,char * argv[])512*25da2beaSAndroid Build Coastguard Worker int main(int argc, char *argv[])
513*25da2beaSAndroid Build Coastguard Worker {
514*25da2beaSAndroid Build Coastguard Worker 	struct io_uring ring;
515*25da2beaSAndroid Build Coastguard Worker 	const char *fname;
516*25da2beaSAndroid Build Coastguard Worker 	char buf[32];
517*25da2beaSAndroid Build Coastguard Worker 	int ret;
518*25da2beaSAndroid Build Coastguard Worker 
519*25da2beaSAndroid Build Coastguard Worker 	srand(getpid());
520*25da2beaSAndroid Build Coastguard Worker 
521*25da2beaSAndroid Build Coastguard Worker 	if (argc > 1) {
522*25da2beaSAndroid Build Coastguard Worker 		fname = argv[1];
523*25da2beaSAndroid Build Coastguard Worker 	} else {
524*25da2beaSAndroid Build Coastguard Worker 		sprintf(buf, ".file-verify.%d", getpid());
525*25da2beaSAndroid Build Coastguard Worker 		fname = buf;
526*25da2beaSAndroid Build Coastguard Worker 		t_create_file(fname, FSIZE);
527*25da2beaSAndroid Build Coastguard Worker 	}
528*25da2beaSAndroid Build Coastguard Worker 
529*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_queue_init(READ_BATCH, &ring, 0);
530*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
531*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "ring setup failed: %d\n", ret);
532*25da2beaSAndroid Build Coastguard Worker 		goto err;
533*25da2beaSAndroid Build Coastguard Worker 	}
534*25da2beaSAndroid Build Coastguard Worker 
535*25da2beaSAndroid Build Coastguard Worker 	if (fill_pattern(fname))
536*25da2beaSAndroid Build Coastguard Worker 		goto err;
537*25da2beaSAndroid Build Coastguard Worker 
538*25da2beaSAndroid Build Coastguard Worker 	ret = test(&ring, fname, 1, 0, 0, 0, 0);
539*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
540*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "Buffered novec test failed\n");
541*25da2beaSAndroid Build Coastguard Worker 		goto err;
542*25da2beaSAndroid Build Coastguard Worker 	}
543*25da2beaSAndroid Build Coastguard Worker 	ret = test(&ring, fname, 1, 0, 0, 1, 0);
544*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
545*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "Buffered novec reg test failed\n");
546*25da2beaSAndroid Build Coastguard Worker 		goto err;
547*25da2beaSAndroid Build Coastguard Worker 	}
548*25da2beaSAndroid Build Coastguard Worker 	ret = test(&ring, fname, 1, 0, 0, 0, 1);
549*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
550*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "Buffered novec provide test failed\n");
551*25da2beaSAndroid Build Coastguard Worker 		goto err;
552*25da2beaSAndroid Build Coastguard Worker 	}
553*25da2beaSAndroid Build Coastguard Worker 	ret = test(&ring, fname, 1, 1, 0, 0, 0);
554*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
555*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "Buffered vec test failed\n");
556*25da2beaSAndroid Build Coastguard Worker 		goto err;
557*25da2beaSAndroid Build Coastguard Worker 	}
558*25da2beaSAndroid Build Coastguard Worker 	ret = test(&ring, fname, 1, 1, 1, 0, 0);
559*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
560*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "Buffered small vec test failed\n");
561*25da2beaSAndroid Build Coastguard Worker 		goto err;
562*25da2beaSAndroid Build Coastguard Worker 	}
563*25da2beaSAndroid Build Coastguard Worker 
564*25da2beaSAndroid Build Coastguard Worker 	ret = test(&ring, fname, 0, 0, 0, 0, 0);
565*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
566*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "O_DIRECT novec test failed\n");
567*25da2beaSAndroid Build Coastguard Worker 		goto err;
568*25da2beaSAndroid Build Coastguard Worker 	}
569*25da2beaSAndroid Build Coastguard Worker 	ret = test(&ring, fname, 0, 0, 0, 1, 0);
570*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
571*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "O_DIRECT novec reg test failed\n");
572*25da2beaSAndroid Build Coastguard Worker 		goto err;
573*25da2beaSAndroid Build Coastguard Worker 	}
574*25da2beaSAndroid Build Coastguard Worker 	ret = test(&ring, fname, 0, 0, 0, 0, 1);
575*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
576*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "O_DIRECT novec provide test failed\n");
577*25da2beaSAndroid Build Coastguard Worker 		goto err;
578*25da2beaSAndroid Build Coastguard Worker 	}
579*25da2beaSAndroid Build Coastguard Worker 	ret = test(&ring, fname, 0, 1, 0, 0, 0);
580*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
581*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "O_DIRECT vec test failed\n");
582*25da2beaSAndroid Build Coastguard Worker 		goto err;
583*25da2beaSAndroid Build Coastguard Worker 	}
584*25da2beaSAndroid Build Coastguard Worker 	ret = test(&ring, fname, 0, 1, 1, 0, 0);
585*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
586*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "O_DIRECT small vec test failed\n");
587*25da2beaSAndroid Build Coastguard Worker 		goto err;
588*25da2beaSAndroid Build Coastguard Worker 	}
589*25da2beaSAndroid Build Coastguard Worker 
590*25da2beaSAndroid Build Coastguard Worker 	ret = test_truncate(&ring, fname, 1, 0, 0);
591*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
592*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "Buffered end truncate read failed\n");
593*25da2beaSAndroid Build Coastguard Worker 		goto err;
594*25da2beaSAndroid Build Coastguard Worker 	}
595*25da2beaSAndroid Build Coastguard Worker 	ret = test_truncate(&ring, fname, 1, 1, 0);
596*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
597*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "Buffered end truncate vec read failed\n");
598*25da2beaSAndroid Build Coastguard Worker 		goto err;
599*25da2beaSAndroid Build Coastguard Worker 	}
600*25da2beaSAndroid Build Coastguard Worker 	ret = test_truncate(&ring, fname, 1, 0, 1);
601*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
602*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "Buffered end truncate pbuf read failed\n");
603*25da2beaSAndroid Build Coastguard Worker 		goto err;
604*25da2beaSAndroid Build Coastguard Worker 	}
605*25da2beaSAndroid Build Coastguard Worker 
606*25da2beaSAndroid Build Coastguard Worker 	ret = test_truncate(&ring, fname, 0, 0, 0);
607*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
608*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "O_DIRECT end truncate read failed\n");
609*25da2beaSAndroid Build Coastguard Worker 		goto err;
610*25da2beaSAndroid Build Coastguard Worker 	}
611*25da2beaSAndroid Build Coastguard Worker 	ret = test_truncate(&ring, fname, 0, 1, 0);
612*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
613*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "O_DIRECT end truncate vec read failed\n");
614*25da2beaSAndroid Build Coastguard Worker 		goto err;
615*25da2beaSAndroid Build Coastguard Worker 	}
616*25da2beaSAndroid Build Coastguard Worker 	ret = test_truncate(&ring, fname, 0, 0, 1);
617*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
618*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "O_DIRECT end truncate pbuf read failed\n");
619*25da2beaSAndroid Build Coastguard Worker 		goto err;
620*25da2beaSAndroid Build Coastguard Worker 	}
621*25da2beaSAndroid Build Coastguard Worker 
622*25da2beaSAndroid Build Coastguard Worker 	if (buf == fname)
623*25da2beaSAndroid Build Coastguard Worker 		unlink(fname);
624*25da2beaSAndroid Build Coastguard Worker 	return 0;
625*25da2beaSAndroid Build Coastguard Worker err:
626*25da2beaSAndroid Build Coastguard Worker 	if (buf == fname)
627*25da2beaSAndroid Build Coastguard Worker 		unlink(fname);
628*25da2beaSAndroid Build Coastguard Worker 	return 1;
629*25da2beaSAndroid Build Coastguard Worker }
630