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