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 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