| /* |
| * Code taken from an example posted to linux-aio at kvack.org |
| * Original Author: Drangon Zhou |
| * Munged by Jeff Moyer to get it to build and to incorporate it into |
| * the autotest framework. |
| * |
| * Description: This source code implements a test to ensure that an AIO |
| * read of the last block in a file opened with O_DIRECT returns the proper |
| * amount of data. In the past, there was a bug that resulted in a return |
| * value of the requested block size, when in fact there was only a fraction |
| * of that data available. Thus, if the last data block contained 300 bytes |
| * worth of data, and the user issued a 4k read, we want to ensure that |
| * the return value is 300, not 4k. |
| */ |
| |
| #define _GNU_SOURCE |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <libaio.h> |
| #include <fcntl.h> |
| #include <unistd.h> |
| #include <errno.h> |
| |
| /* Create a file of a size that is not a multiple of block size */ |
| #define FILE_SIZE 300 |
| |
| #define fail(fmt , args...) \ |
| do { \ |
| printf(fmt , ##args); \ |
| exit(1); \ |
| } while (0) |
| |
| static unsigned char buffer[4096] __attribute((aligned (512))); |
| |
| int |
| main(int argc, char **argv) |
| { |
| int ret; |
| int fd; |
| const char *filename; |
| struct iocb myiocb; |
| struct iocb *cb = &myiocb; |
| io_context_t ioctx; |
| struct io_event ie; |
| |
| if (argc != 2) |
| fail("only arg should be file name"); |
| |
| filename = argv[1]; |
| fd = open(filename, O_CREAT|O_RDWR|O_DIRECT, 0600); |
| if (fd < 0) |
| fail("open returned error %d\n", errno); |
| |
| ret = ftruncate(fd, FILE_SIZE); |
| if (ret < 0) |
| fail("truncate returned error %d\n", errno); |
| |
| /* <1> use normal disk read, this should be ok */ |
| ret = read(fd, buffer, 4096); |
| if (ret != FILE_SIZE) |
| fail("buffered read returned %d, should be 300\n", ret); |
| |
| /* <2> use AIO disk read, it sees error. */ |
| memset(&myiocb, 0, sizeof(myiocb)); |
| cb->data = 0; |
| cb->key = 0; |
| cb->aio_lio_opcode = IO_CMD_PREAD; |
| cb->aio_reqprio = 0; |
| cb->aio_fildes = fd; |
| cb->u.c.buf = buffer; |
| cb->u.c.nbytes = 4096; |
| cb->u.c.offset = 0; |
| |
| ret = io_queue_init(1, &ioctx); |
| if (ret != 0) |
| fail("io_queue_init returned error %d\n", ret); |
| |
| ret = io_submit(ioctx, 1, &cb); |
| if (ret != 1) |
| fail("io_submit returned error %d\n", ret); |
| |
| ret = io_getevents(ioctx, 1, 1, &ie, NULL); |
| if (ret != 1) |
| fail("io_getevents returned %d\n", ret); |
| |
| /* |
| * If all goes well, we should see 300 bytes read. If things |
| * are broken, we may very well see a result of 4k. |
| */ |
| if (ie.res != FILE_SIZE) |
| fail("AIO read of last block in file returned %d bytes, " |
| "expected %d\n", ret, FILE_SIZE); |
| |
| printf("AIO read of last block in file succeeded.\n"); |
| return 0; |
| } |