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...) \
28 do { \
29 printf(fmt , ##args); \
30 exit(1); \
31 } while (0)
32
33 static unsigned char buffer[4096] __attribute((aligned (512)));
34
35 int
main(int argc,char ** argv)36 main(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