1/*
2 *  Code taken from an example posted to linux-aio at kvack.org
3 *  Original Author: Drangon Zhou
4 *  Munged by Jeff Moyer to get it to build and to incorporate it into
5 *  the autotest framework.
6 *
7 *  Description:  This source code implements a test to ensure that an AIO
8 *  read of the last block in a file opened with O_DIRECT returns the proper
9 *  amount of data.  In the past, there was a bug that resulted in a return
10 *  value of the requested block size, when in fact there was only a fraction
11 *  of that data available.  Thus, if the last data block contained 300 bytes
12 *  worth of data, and the user issued a 4k read, we want to ensure that
13 *  the return value is 300, not 4k.
14 */
15
16#define _GNU_SOURCE
17#include <stdio.h>
18#include <stdlib.h>
19#include <libaio.h>
20#include <fcntl.h>
21#include <unistd.h>
22#include <errno.h>
23
24/* Create a file of a size that is not a multiple of block size */
25#define FILE_SIZE	300
26
27#define fail(fmt , args...) 	\
28do {				\
29	printf(fmt , ##args);	\
30	exit(1);		\
31} while (0)
32
33static unsigned char buffer[4096] __attribute((aligned (512)));
34
35int
36main(int argc, char **argv)
37{
38	int ret;
39	int fd;
40	const char *filename;
41	struct iocb myiocb;
42	struct iocb *cb = &myiocb;
43	io_context_t ioctx;
44	struct io_event ie;
45
46	if (argc != 2)
47		fail("only arg should be file name");
48
49	filename = argv[1];
50	fd = open(filename, O_CREAT|O_RDWR|O_DIRECT, 0600);
51	if (fd < 0)
52		fail("open returned error %d\n", errno);
53
54	ret = ftruncate(fd, FILE_SIZE);
55	if (ret < 0)
56		fail("truncate returned error %d\n", errno);
57
58	/* <1> use normal disk read, this should be ok */
59	ret = read(fd, buffer, 4096);
60	if (ret != FILE_SIZE)
61		fail("buffered read returned %d, should be 300\n", ret);
62
63	/* <2> use AIO disk read, it sees error. */
64	memset(&myiocb, 0, sizeof(myiocb));
65	cb->data = 0;
66	cb->key = 0;
67	cb->aio_lio_opcode = IO_CMD_PREAD;
68	cb->aio_reqprio = 0;
69	cb->aio_fildes = fd;
70	cb->u.c.buf = buffer;
71	cb->u.c.nbytes = 4096;
72	cb->u.c.offset = 0;
73
74	ret = io_queue_init(1, &ioctx);
75	if (ret != 0)
76		fail("io_queue_init returned error %d\n", ret);
77
78	ret = io_submit(ioctx, 1, &cb);
79	if (ret != 1)
80		fail("io_submit returned error %d\n", ret);
81
82	ret = io_getevents(ioctx, 1, 1, &ie, NULL);
83	if (ret != 1)
84		fail("io_getevents returned %d\n", ret);
85
86	/*
87	 *  If all goes well, we should see 300 bytes read.  If things
88	 *  are broken, we may very well see a result of 4k.
89	 */
90	if (ie.res != FILE_SIZE)
91		fail("AIO read of last block in file returned %d bytes, "
92		     "expected %d\n", ret, FILE_SIZE);
93
94	printf("AIO read of last block in file succeeded.\n");
95	return 0;
96}
97