Home | History | Annotate | Download | only in src
      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