xref: /aosp_15_r20/external/ltp/testcases/kernel/io/ltp-aiodio/aiocp.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*49cdfc7eSAndroid Build Coastguard Worker /*
3*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (c) 2004 Stephen Hemminger <[email protected]>
4*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (c) 2004 Daniel McNeil <[email protected]>
5*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (c) 2004 Marty Ridgeway <[email protected]>
6*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (C) 2021 SUSE LLC Andrea Cervesato <[email protected]>
7*49cdfc7eSAndroid Build Coastguard Worker  */
8*49cdfc7eSAndroid Build Coastguard Worker 
9*49cdfc7eSAndroid Build Coastguard Worker /*\
10*49cdfc7eSAndroid Build Coastguard Worker  * [Description]
11*49cdfc7eSAndroid Build Coastguard Worker  *
12*49cdfc7eSAndroid Build Coastguard Worker  * Copy file by using an async I/O state machine.
13*49cdfc7eSAndroid Build Coastguard Worker  *
14*49cdfc7eSAndroid Build Coastguard Worker  * - Start read request
15*49cdfc7eSAndroid Build Coastguard Worker  * - When read completes turn it into a write request
16*49cdfc7eSAndroid Build Coastguard Worker  * - When write completes decrement counter and free up resources
17*49cdfc7eSAndroid Build Coastguard Worker  */
18*49cdfc7eSAndroid Build Coastguard Worker 
19*49cdfc7eSAndroid Build Coastguard Worker #define _GNU_SOURCE
20*49cdfc7eSAndroid Build Coastguard Worker 
21*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
22*49cdfc7eSAndroid Build Coastguard Worker 
23*49cdfc7eSAndroid Build Coastguard Worker #ifdef HAVE_LIBAIO
24*49cdfc7eSAndroid Build Coastguard Worker #include <libaio.h>
25*49cdfc7eSAndroid Build Coastguard Worker #include <string.h>
26*49cdfc7eSAndroid Build Coastguard Worker #include <limits.h>
27*49cdfc7eSAndroid Build Coastguard Worker #include <sys/stat.h>
28*49cdfc7eSAndroid Build Coastguard Worker #include "common.h"
29*49cdfc7eSAndroid Build Coastguard Worker 
30*49cdfc7eSAndroid Build Coastguard Worker #include "tst_rand_data.h"
31*49cdfc7eSAndroid Build Coastguard Worker 
32*49cdfc7eSAndroid Build Coastguard Worker static const char *srcname = "srcfile.bin";
33*49cdfc7eSAndroid Build Coastguard Worker static const char *dstname = "dstfile.bin";
34*49cdfc7eSAndroid Build Coastguard Worker 
35*49cdfc7eSAndroid Build Coastguard Worker static char *str_aio_blksize;
36*49cdfc7eSAndroid Build Coastguard Worker static char *str_filesize;
37*49cdfc7eSAndroid Build Coastguard Worker static char *str_aionum;
38*49cdfc7eSAndroid Build Coastguard Worker static char *str_oflag;
39*49cdfc7eSAndroid Build Coastguard Worker 
40*49cdfc7eSAndroid Build Coastguard Worker static long long aio_blksize = 64 * 1024;
41*49cdfc7eSAndroid Build Coastguard Worker static long long filesize = 1 * 1024 * 1024;
42*49cdfc7eSAndroid Build Coastguard Worker static long long alignment;
43*49cdfc7eSAndroid Build Coastguard Worker static int aionum = 16;
44*49cdfc7eSAndroid Build Coastguard Worker static int srcflags = O_RDONLY;
45*49cdfc7eSAndroid Build Coastguard Worker static int dstflags = O_WRONLY;
46*49cdfc7eSAndroid Build Coastguard Worker 
47*49cdfc7eSAndroid Build Coastguard Worker static int srcfd;
48*49cdfc7eSAndroid Build Coastguard Worker static int dstfd;
49*49cdfc7eSAndroid Build Coastguard Worker static long long busy;
50*49cdfc7eSAndroid Build Coastguard Worker static long long tocopy;
51*49cdfc7eSAndroid Build Coastguard Worker static struct iocb **iocb_free;
52*49cdfc7eSAndroid Build Coastguard Worker static int iocb_free_count;
53*49cdfc7eSAndroid Build Coastguard Worker 
54*49cdfc7eSAndroid Build Coastguard Worker #ifndef howmany
55*49cdfc7eSAndroid Build Coastguard Worker # define howmany(x, y)  (((x) + ((y) - 1)) / (y))
56*49cdfc7eSAndroid Build Coastguard Worker #endif
57*49cdfc7eSAndroid Build Coastguard Worker 
fill_with_rand_data(int fd,long long size)58*49cdfc7eSAndroid Build Coastguard Worker static void fill_with_rand_data(int fd, long long size)
59*49cdfc7eSAndroid Build Coastguard Worker {
60*49cdfc7eSAndroid Build Coastguard Worker 	long long i = size;
61*49cdfc7eSAndroid Build Coastguard Worker 
62*49cdfc7eSAndroid Build Coastguard Worker 	while (i > 0) {
63*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_WRITE(1, fd, tst_rand_data,
64*49cdfc7eSAndroid Build Coastguard Worker 			   MIN((long long)tst_rand_data_len, i));
65*49cdfc7eSAndroid Build Coastguard Worker 		i -= tst_rand_data_len;
66*49cdfc7eSAndroid Build Coastguard Worker 	}
67*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_FSYNC(fd);
68*49cdfc7eSAndroid Build Coastguard Worker }
69*49cdfc7eSAndroid Build Coastguard Worker 
async_init(void)70*49cdfc7eSAndroid Build Coastguard Worker static void async_init(void)
71*49cdfc7eSAndroid Build Coastguard Worker {
72*49cdfc7eSAndroid Build Coastguard Worker 	int i;
73*49cdfc7eSAndroid Build Coastguard Worker 	char *buff;
74*49cdfc7eSAndroid Build Coastguard Worker 
75*49cdfc7eSAndroid Build Coastguard Worker 	iocb_free = SAFE_MALLOC(aionum * sizeof(struct iocb *));
76*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < aionum; i++) {
77*49cdfc7eSAndroid Build Coastguard Worker 		iocb_free[i] = SAFE_MALLOC(sizeof(struct iocb));
78*49cdfc7eSAndroid Build Coastguard Worker 		buff = SAFE_MEMALIGN(alignment, aio_blksize);
79*49cdfc7eSAndroid Build Coastguard Worker 
80*49cdfc7eSAndroid Build Coastguard Worker 		io_prep_pread(iocb_free[i], -1, buff, aio_blksize, 0);
81*49cdfc7eSAndroid Build Coastguard Worker 	}
82*49cdfc7eSAndroid Build Coastguard Worker 
83*49cdfc7eSAndroid Build Coastguard Worker 	iocb_free_count = i;
84*49cdfc7eSAndroid Build Coastguard Worker }
85*49cdfc7eSAndroid Build Coastguard Worker 
get_iocb(void)86*49cdfc7eSAndroid Build Coastguard Worker static struct iocb *get_iocb(void)
87*49cdfc7eSAndroid Build Coastguard Worker {
88*49cdfc7eSAndroid Build Coastguard Worker 	if (!iocb_free_count)
89*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
90*49cdfc7eSAndroid Build Coastguard Worker 
91*49cdfc7eSAndroid Build Coastguard Worker 	return iocb_free[--iocb_free_count];
92*49cdfc7eSAndroid Build Coastguard Worker }
93*49cdfc7eSAndroid Build Coastguard Worker 
put_iocb(struct iocb * io)94*49cdfc7eSAndroid Build Coastguard Worker static void put_iocb(struct iocb *io)
95*49cdfc7eSAndroid Build Coastguard Worker {
96*49cdfc7eSAndroid Build Coastguard Worker 	iocb_free[iocb_free_count++] = io;
97*49cdfc7eSAndroid Build Coastguard Worker }
98*49cdfc7eSAndroid Build Coastguard Worker 
async_write_done(LTP_ATTRIBUTE_UNUSED io_context_t ctx,struct iocb * iocb,long res,long res2)99*49cdfc7eSAndroid Build Coastguard Worker static void async_write_done(LTP_ATTRIBUTE_UNUSED io_context_t ctx, struct iocb *iocb, long res, long res2)
100*49cdfc7eSAndroid Build Coastguard Worker {
101*49cdfc7eSAndroid Build Coastguard Worker 	int iosize = iocb->u.c.nbytes;
102*49cdfc7eSAndroid Build Coastguard Worker 
103*49cdfc7eSAndroid Build Coastguard Worker 	if (res != iosize)
104*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "Write missing bytes expect %d got %ld", iosize, res);
105*49cdfc7eSAndroid Build Coastguard Worker 
106*49cdfc7eSAndroid Build Coastguard Worker 	if (res2 != 0)
107*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "Write error: %s", tst_strerrno(-res2));
108*49cdfc7eSAndroid Build Coastguard Worker 
109*49cdfc7eSAndroid Build Coastguard Worker 	put_iocb(iocb);
110*49cdfc7eSAndroid Build Coastguard Worker 
111*49cdfc7eSAndroid Build Coastguard Worker 	--busy;
112*49cdfc7eSAndroid Build Coastguard Worker 	--tocopy;
113*49cdfc7eSAndroid Build Coastguard Worker 
114*49cdfc7eSAndroid Build Coastguard Worker 	if (dstflags & O_DIRECT)
115*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_FSYNC(dstfd);
116*49cdfc7eSAndroid Build Coastguard Worker 
117*49cdfc7eSAndroid Build Coastguard Worker 	if (!tst_remaining_runtime())
118*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TCONF, "Out of runtime!");
119*49cdfc7eSAndroid Build Coastguard Worker }
120*49cdfc7eSAndroid Build Coastguard Worker 
async_copy(io_context_t ctx,struct iocb * iocb,long res,long res2)121*49cdfc7eSAndroid Build Coastguard Worker static void async_copy(io_context_t ctx, struct iocb *iocb, long res, long res2)
122*49cdfc7eSAndroid Build Coastguard Worker {
123*49cdfc7eSAndroid Build Coastguard Worker 	int iosize = iocb->u.c.nbytes;
124*49cdfc7eSAndroid Build Coastguard Worker 	char *buf = iocb->u.c.buf;
125*49cdfc7eSAndroid Build Coastguard Worker 	off_t offset = iocb->u.c.offset;
126*49cdfc7eSAndroid Build Coastguard Worker 	int w;
127*49cdfc7eSAndroid Build Coastguard Worker 
128*49cdfc7eSAndroid Build Coastguard Worker 	if (res != iosize)
129*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "Read missing bytes expect %d got %ld", iosize, res);
130*49cdfc7eSAndroid Build Coastguard Worker 
131*49cdfc7eSAndroid Build Coastguard Worker 	if (res2 != 0)
132*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "Read error: %s", tst_strerrno(-res2));
133*49cdfc7eSAndroid Build Coastguard Worker 
134*49cdfc7eSAndroid Build Coastguard Worker 	io_prep_pwrite(iocb, dstfd, buf, iosize, offset);
135*49cdfc7eSAndroid Build Coastguard Worker 	io_set_callback(iocb, async_write_done);
136*49cdfc7eSAndroid Build Coastguard Worker 
137*49cdfc7eSAndroid Build Coastguard Worker 	w = io_submit(ctx, 1, &iocb);
138*49cdfc7eSAndroid Build Coastguard Worker 	if (w < 0)
139*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "io_submit error: %s", tst_strerrno(-w));
140*49cdfc7eSAndroid Build Coastguard Worker }
141*49cdfc7eSAndroid Build Coastguard Worker 
io_wait_run(io_context_t ctx,struct timespec * to)142*49cdfc7eSAndroid Build Coastguard Worker static void io_wait_run(io_context_t ctx, struct timespec *to)
143*49cdfc7eSAndroid Build Coastguard Worker {
144*49cdfc7eSAndroid Build Coastguard Worker 	struct io_event events[aionum];
145*49cdfc7eSAndroid Build Coastguard Worker 	struct io_event *ep;
146*49cdfc7eSAndroid Build Coastguard Worker 	int n;
147*49cdfc7eSAndroid Build Coastguard Worker 
148*49cdfc7eSAndroid Build Coastguard Worker 	n = io_getevents(ctx, 1, aionum, events, to);
149*49cdfc7eSAndroid Build Coastguard Worker 	if (n < 0)
150*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "io_getevents() failed: %s", tst_strerrno(-n));
151*49cdfc7eSAndroid Build Coastguard Worker 
152*49cdfc7eSAndroid Build Coastguard Worker 	for (ep = events; n-- > 0; ep++) {
153*49cdfc7eSAndroid Build Coastguard Worker 		io_callback_t cb = (io_callback_t) ep->data;
154*49cdfc7eSAndroid Build Coastguard Worker 		struct iocb *iocb = ep->obj;
155*49cdfc7eSAndroid Build Coastguard Worker 
156*49cdfc7eSAndroid Build Coastguard Worker 		cb(ctx, iocb, ep->res, ep->res2);
157*49cdfc7eSAndroid Build Coastguard Worker 	}
158*49cdfc7eSAndroid Build Coastguard Worker }
159*49cdfc7eSAndroid Build Coastguard Worker 
async_run(io_context_t ctx,int fd,io_callback_t cb)160*49cdfc7eSAndroid Build Coastguard Worker static void async_run(io_context_t ctx, int fd, io_callback_t cb)
161*49cdfc7eSAndroid Build Coastguard Worker {
162*49cdfc7eSAndroid Build Coastguard Worker 	long long offset = 0;
163*49cdfc7eSAndroid Build Coastguard Worker 	int rc, i, n;
164*49cdfc7eSAndroid Build Coastguard Worker 	int iosize;
165*49cdfc7eSAndroid Build Coastguard Worker 
166*49cdfc7eSAndroid Build Coastguard Worker 	tocopy = filesize / aio_blksize;
167*49cdfc7eSAndroid Build Coastguard Worker 	busy = 0;
168*49cdfc7eSAndroid Build Coastguard Worker 
169*49cdfc7eSAndroid Build Coastguard Worker 	while (tocopy > 0) {
170*49cdfc7eSAndroid Build Coastguard Worker 		n = MIN(aionum - busy, tocopy);
171*49cdfc7eSAndroid Build Coastguard Worker 
172*49cdfc7eSAndroid Build Coastguard Worker 		if (n > 0) {
173*49cdfc7eSAndroid Build Coastguard Worker 			struct iocb *ioq[n];
174*49cdfc7eSAndroid Build Coastguard Worker 
175*49cdfc7eSAndroid Build Coastguard Worker 			for (i = 0; i < n; i++) {
176*49cdfc7eSAndroid Build Coastguard Worker 				struct iocb *io = get_iocb();
177*49cdfc7eSAndroid Build Coastguard Worker 
178*49cdfc7eSAndroid Build Coastguard Worker 				iosize = MIN(filesize - offset, aio_blksize);
179*49cdfc7eSAndroid Build Coastguard Worker 
180*49cdfc7eSAndroid Build Coastguard Worker 				/* If we don't have any byte to write, exit */
181*49cdfc7eSAndroid Build Coastguard Worker 				if (iosize <= 0)
182*49cdfc7eSAndroid Build Coastguard Worker 					break;
183*49cdfc7eSAndroid Build Coastguard Worker 
184*49cdfc7eSAndroid Build Coastguard Worker 				io_prep_pread(io, fd, io->u.c.buf, iosize, offset);
185*49cdfc7eSAndroid Build Coastguard Worker 				io_set_callback(io, cb);
186*49cdfc7eSAndroid Build Coastguard Worker 
187*49cdfc7eSAndroid Build Coastguard Worker 				ioq[i] = io;
188*49cdfc7eSAndroid Build Coastguard Worker 				offset += iosize;
189*49cdfc7eSAndroid Build Coastguard Worker 			}
190*49cdfc7eSAndroid Build Coastguard Worker 
191*49cdfc7eSAndroid Build Coastguard Worker 			rc = io_submit(ctx, i, ioq);
192*49cdfc7eSAndroid Build Coastguard Worker 			if (rc < 0)
193*49cdfc7eSAndroid Build Coastguard Worker 				tst_brk(TBROK, "io_submit write error: %s", tst_strerrno(-rc));
194*49cdfc7eSAndroid Build Coastguard Worker 
195*49cdfc7eSAndroid Build Coastguard Worker 			busy += n;
196*49cdfc7eSAndroid Build Coastguard Worker 		}
197*49cdfc7eSAndroid Build Coastguard Worker 
198*49cdfc7eSAndroid Build Coastguard Worker 		io_wait_run(ctx, 0);
199*49cdfc7eSAndroid Build Coastguard Worker 	}
200*49cdfc7eSAndroid Build Coastguard Worker }
201*49cdfc7eSAndroid Build Coastguard Worker 
setup(void)202*49cdfc7eSAndroid Build Coastguard Worker static void setup(void)
203*49cdfc7eSAndroid Build Coastguard Worker {
204*49cdfc7eSAndroid Build Coastguard Worker 	int maxaio;
205*49cdfc7eSAndroid Build Coastguard Worker 	long long leftover;
206*49cdfc7eSAndroid Build Coastguard Worker 
207*49cdfc7eSAndroid Build Coastguard Worker 	if (tst_parse_int(str_aionum, &aionum, 1, INT_MAX))
208*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "Invalid number of I/O '%s'", str_aionum);
209*49cdfc7eSAndroid Build Coastguard Worker 
210*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_FILE_SCANF("/proc/sys/fs/aio-max-nr", "%d", &maxaio);
211*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "Maximum AIO blocks: %d", maxaio);
212*49cdfc7eSAndroid Build Coastguard Worker 
213*49cdfc7eSAndroid Build Coastguard Worker 	if (aionum > maxaio)
214*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TCONF, "Number of async IO blocks passed the maximum (%d)", maxaio);
215*49cdfc7eSAndroid Build Coastguard Worker 
216*49cdfc7eSAndroid Build Coastguard Worker 	if (tst_parse_filesize(str_aio_blksize, &aio_blksize, 1, LLONG_MAX))
217*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "Invalid write blocks size '%s'", str_aio_blksize);
218*49cdfc7eSAndroid Build Coastguard Worker 
219*49cdfc7eSAndroid Build Coastguard Worker 	if (str_oflag) {
220*49cdfc7eSAndroid Build Coastguard Worker 		if (strncmp(str_oflag, "SYNC", 4) == 0) {
221*49cdfc7eSAndroid Build Coastguard Worker 			dstflags |= O_SYNC;
222*49cdfc7eSAndroid Build Coastguard Worker 		} else if (strncmp(str_oflag, "DIRECT", 6) == 0) {
223*49cdfc7eSAndroid Build Coastguard Worker 			if (tst_fs_type(".") == TST_TMPFS_MAGIC)
224*49cdfc7eSAndroid Build Coastguard Worker 				tst_brk(TCONF, "O_DIRECT not supported on tmpfs");
225*49cdfc7eSAndroid Build Coastguard Worker 
226*49cdfc7eSAndroid Build Coastguard Worker 			srcflags |= O_DIRECT;
227*49cdfc7eSAndroid Build Coastguard Worker 			dstflags |= O_DIRECT;
228*49cdfc7eSAndroid Build Coastguard Worker 		}
229*49cdfc7eSAndroid Build Coastguard Worker 	}
230*49cdfc7eSAndroid Build Coastguard Worker 
231*49cdfc7eSAndroid Build Coastguard Worker 	if (tst_fs_type(".") == TST_TMPFS_MAGIC)
232*49cdfc7eSAndroid Build Coastguard Worker 		alignment = getpagesize();
233*49cdfc7eSAndroid Build Coastguard Worker 	else
234*49cdfc7eSAndroid Build Coastguard Worker 		alignment = tst_dev_block_size(".");
235*49cdfc7eSAndroid Build Coastguard Worker 
236*49cdfc7eSAndroid Build Coastguard Worker 	if (dstflags & O_DIRECT && aio_blksize % alignment)
237*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TCONF, "Block size is not multiple of drive block size");
238*49cdfc7eSAndroid Build Coastguard Worker 
239*49cdfc7eSAndroid Build Coastguard Worker 	if (tst_parse_filesize(str_filesize, &filesize, 1, LLONG_MAX))
240*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "Invalid file size '%s'", str_filesize);
241*49cdfc7eSAndroid Build Coastguard Worker 
242*49cdfc7eSAndroid Build Coastguard Worker 	leftover = filesize % aio_blksize;
243*49cdfc7eSAndroid Build Coastguard Worker 
244*49cdfc7eSAndroid Build Coastguard Worker 	if (leftover > 0) {
245*49cdfc7eSAndroid Build Coastguard Worker 		filesize = filesize - leftover + aio_blksize;
246*49cdfc7eSAndroid Build Coastguard Worker 
247*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TINFO, "Rounded filesize to the next block size multiple: %llu", filesize);
248*49cdfc7eSAndroid Build Coastguard Worker 	}
249*49cdfc7eSAndroid Build Coastguard Worker 
250*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "Fill %s with random data", srcname);
251*49cdfc7eSAndroid Build Coastguard Worker 
252*49cdfc7eSAndroid Build Coastguard Worker 	srcfd = SAFE_OPEN(srcname, (srcflags & ~O_DIRECT) | O_RDWR | O_CREAT, 0666);
253*49cdfc7eSAndroid Build Coastguard Worker 	fill_with_rand_data(srcfd, filesize);
254*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_CLOSE(srcfd);
255*49cdfc7eSAndroid Build Coastguard Worker }
256*49cdfc7eSAndroid Build Coastguard Worker 
cleanup(void)257*49cdfc7eSAndroid Build Coastguard Worker static void cleanup(void)
258*49cdfc7eSAndroid Build Coastguard Worker {
259*49cdfc7eSAndroid Build Coastguard Worker 	if (srcfd > 0)
260*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_CLOSE(srcfd);
261*49cdfc7eSAndroid Build Coastguard Worker 
262*49cdfc7eSAndroid Build Coastguard Worker 	if (dstfd > 0)
263*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_CLOSE(dstfd);
264*49cdfc7eSAndroid Build Coastguard Worker }
265*49cdfc7eSAndroid Build Coastguard Worker 
run(void)266*49cdfc7eSAndroid Build Coastguard Worker static void run(void)
267*49cdfc7eSAndroid Build Coastguard Worker {
268*49cdfc7eSAndroid Build Coastguard Worker 	const int buffsize = 4096;
269*49cdfc7eSAndroid Build Coastguard Worker 	io_context_t myctx;
270*49cdfc7eSAndroid Build Coastguard Worker 	struct stat st;
271*49cdfc7eSAndroid Build Coastguard Worker 	char srcbuff[buffsize];
272*49cdfc7eSAndroid Build Coastguard Worker 	char dstbuff[buffsize];
273*49cdfc7eSAndroid Build Coastguard Worker 	int reads = 0;
274*49cdfc7eSAndroid Build Coastguard Worker 	int i, r;
275*49cdfc7eSAndroid Build Coastguard Worker 
276*49cdfc7eSAndroid Build Coastguard Worker 	srcfd = SAFE_OPEN(srcname, srcflags | O_RDWR | O_CREAT, 0666);
277*49cdfc7eSAndroid Build Coastguard Worker 	dstfd = SAFE_OPEN(dstname, dstflags | O_WRONLY | O_CREAT, 0666);
278*49cdfc7eSAndroid Build Coastguard Worker 
279*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "Copy %s -> %s", srcname, dstname);
280*49cdfc7eSAndroid Build Coastguard Worker 
281*49cdfc7eSAndroid Build Coastguard Worker 	memset(&myctx, 0, sizeof(myctx));
282*49cdfc7eSAndroid Build Coastguard Worker 	io_queue_init(aionum, &myctx);
283*49cdfc7eSAndroid Build Coastguard Worker 
284*49cdfc7eSAndroid Build Coastguard Worker 	async_init();
285*49cdfc7eSAndroid Build Coastguard Worker 	async_run(myctx, srcfd, async_copy);
286*49cdfc7eSAndroid Build Coastguard Worker 
287*49cdfc7eSAndroid Build Coastguard Worker 	io_destroy(myctx);
288*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_CLOSE(srcfd);
289*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_CLOSE(dstfd);
290*49cdfc7eSAndroid Build Coastguard Worker 
291*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "Comparing %s with %s", srcname, dstname);
292*49cdfc7eSAndroid Build Coastguard Worker 
293*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_STAT(dstname, &st);
294*49cdfc7eSAndroid Build Coastguard Worker 	if (st.st_size != filesize) {
295*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TFAIL, "Expected destination file size %lld but it's %ld", filesize, st.st_size);
296*49cdfc7eSAndroid Build Coastguard Worker 		/* no need to compare files */
297*49cdfc7eSAndroid Build Coastguard Worker 		return;
298*49cdfc7eSAndroid Build Coastguard Worker 	}
299*49cdfc7eSAndroid Build Coastguard Worker 
300*49cdfc7eSAndroid Build Coastguard Worker 	srcfd = SAFE_OPEN(srcname, O_RDONLY, 0666);
301*49cdfc7eSAndroid Build Coastguard Worker 	dstfd = SAFE_OPEN(dstname, O_RDONLY, 0666);
302*49cdfc7eSAndroid Build Coastguard Worker 
303*49cdfc7eSAndroid Build Coastguard Worker 	reads = howmany(filesize, buffsize);
304*49cdfc7eSAndroid Build Coastguard Worker 
305*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < reads; i++) {
306*49cdfc7eSAndroid Build Coastguard Worker 		r = SAFE_READ(0, srcfd, srcbuff, buffsize);
307*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_READ(0, dstfd, dstbuff, buffsize);
308*49cdfc7eSAndroid Build Coastguard Worker 		if (memcmp(srcbuff, dstbuff, r)) {
309*49cdfc7eSAndroid Build Coastguard Worker 			tst_res(TFAIL, "Files are not identical");
310*49cdfc7eSAndroid Build Coastguard Worker 			return;
311*49cdfc7eSAndroid Build Coastguard Worker 		}
312*49cdfc7eSAndroid Build Coastguard Worker 	}
313*49cdfc7eSAndroid Build Coastguard Worker 
314*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TPASS, "Files are identical");
315*49cdfc7eSAndroid Build Coastguard Worker 
316*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_CLOSE(srcfd);
317*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_CLOSE(dstfd);
318*49cdfc7eSAndroid Build Coastguard Worker }
319*49cdfc7eSAndroid Build Coastguard Worker 
320*49cdfc7eSAndroid Build Coastguard Worker static struct tst_test test = {
321*49cdfc7eSAndroid Build Coastguard Worker 	.test_all = run,
322*49cdfc7eSAndroid Build Coastguard Worker 	.setup = setup,
323*49cdfc7eSAndroid Build Coastguard Worker 	.cleanup = cleanup,
324*49cdfc7eSAndroid Build Coastguard Worker 	.needs_tmpdir = 1,
325*49cdfc7eSAndroid Build Coastguard Worker 	.max_runtime = 1800,
326*49cdfc7eSAndroid Build Coastguard Worker 	.needs_root = 1,
327*49cdfc7eSAndroid Build Coastguard Worker 	.options = (struct tst_option[]) {
328*49cdfc7eSAndroid Build Coastguard Worker 		{"b:", &str_aio_blksize, "Size of writing blocks (default 1K)"},
329*49cdfc7eSAndroid Build Coastguard Worker 		{"s:", &str_filesize, "Size of file (default 10M)"},
330*49cdfc7eSAndroid Build Coastguard Worker 		{"n:", &str_aionum, "Number of Async IO blocks (default 16)"},
331*49cdfc7eSAndroid Build Coastguard Worker 		{"f:", &str_oflag, "Open flag: SYNC | DIRECT (default O_CREAT only)"},
332*49cdfc7eSAndroid Build Coastguard Worker 		{},
333*49cdfc7eSAndroid Build Coastguard Worker 	},
334*49cdfc7eSAndroid Build Coastguard Worker };
335*49cdfc7eSAndroid Build Coastguard Worker #else
336*49cdfc7eSAndroid Build Coastguard Worker TST_TEST_TCONF("test requires libaio and its development packages");
337*49cdfc7eSAndroid Build Coastguard Worker #endif
338