1 #define _XOPEN_SOURCE 500 /* pwrite */
2 #include <unistd.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <sys/types.h>
6 #include <sys/stat.h>
7 #include <fcntl.h>
8 #include <libaio.h>
9 #include <errno.h>
10 #include <time.h>
11 #include <sys/types.h>
12 #include <sys/wait.h>
13
14 /*
15 * DIO invalidates the read cache after it writes. At one point it tried to
16 * return EIO if this failed. When called from AIO, though, this EIO return
17 * would clobber EIOCBQUEUED and cause fs/aio.c and fs/direct-io.c to complete
18 * an iocb twice. This typically references freed memory from an interrupt
19 * handler and oopses.
20 *
21 * This test hits the race after at most two minutes on a single spindle. It
22 * spins performing large dio writes. It also spins racing buffered writes.
23 * It assumes it's on ext3 using ordered writes. The ordered write bhs can be
24 * pinned by jbd as a transaction commits. If invalidate_inode_pages2_range()
25 * hits pages backed by those buffers ->releasepage will fail and it'll try to
26 * return -EIO.
27 */
28 #ifndef O_DIRECT
29 #define O_DIRECT 040000 /* direct disk access hint */
30 #endif
31
32 #define GINORMOUS (32 * 1024 * 1024)
33
34
35 /* This test never survived to 180 seconds on a single spindle */
36 #define SECONDS 200
37
38 static unsigned char buf[GINORMOUS] __attribute((aligned (512)));
39
40 #define fail(fmt , args...) do {\
41 printf(fmt , ##args); \
42 exit(1); \
43 } while (0)
44
spin_dio(int fd)45 void spin_dio(int fd)
46 {
47 io_context_t ctx;
48 struct iocb iocb;
49 struct iocb *iocbs[1] = { &iocb };
50 struct io_event event;
51 int ret;
52
53 io_prep_pwrite(&iocb, fd, buf, GINORMOUS, 0);
54
55 ret = io_queue_init(1, &ctx);
56 if (ret)
57 fail("io_queue_init returned %d", ret);
58
59 while (1) {
60 ret = io_submit(ctx, 1, iocbs);
61 if (ret != 1)
62 fail("io_submit returned %d instead of 1", ret);
63
64 ret = io_getevents(ctx, 1, 1, &event, NULL);
65 if (ret != 1)
66 fail("io_getevents returned %d instead of 1", ret);
67
68 if (event.res == -EIO) {
69 printf("invalidation returned -EIO, OK\n");
70 exit(0);
71 }
72
73 if (event.res != GINORMOUS)
74 fail("event res %ld\n", event.res);
75 }
76 }
77
spin_buffered(int fd)78 void spin_buffered(int fd)
79 {
80 int ret;
81
82 while (1) {
83 ret = pwrite(fd, buf, GINORMOUS, 0);
84 if (ret != GINORMOUS)
85 fail("buffered write returned %d", ret);
86 }
87 }
88
alarm_handler(int signum)89 static void alarm_handler(int signum)
90 {
91 }
92
main(int argc,char ** argv)93 int main(int argc, char **argv)
94 {
95 pid_t buffered_pid;
96 pid_t dio_pid;
97 pid_t pid;
98 int fd;
99 int fd2;
100 int status;
101
102 if (argc != 2)
103 fail("only arg should be file name");
104
105 fd = open(argv[1], O_DIRECT|O_CREAT|O_RDWR, 0644);
106 if (fd < 0)
107 fail("open dio failed: %d\n", errno);
108
109 fd2 = open(argv[1], O_RDWR, 0644);
110 if (fd < 0)
111 fail("open failed: %d\n", errno);
112
113 buffered_pid = fork();
114 if (buffered_pid < 0)
115 fail("fork failed: %d\n", errno);
116
117 if (buffered_pid == 0) {
118 spin_buffered(fd2);
119 exit(0);
120 }
121
122 dio_pid = fork();
123 if (dio_pid < 0) {
124 kill(buffered_pid, SIGKILL);
125 fail("fork failed: %d\n", errno);
126 }
127
128 if (dio_pid == 0) {
129 spin_dio(fd);
130 exit(0);
131 }
132
133 signal(SIGALRM, alarm_handler);
134 alarm(SECONDS);
135
136 pid = wait(&status);
137 if (pid < 0 && errno == EINTR) {
138 /* if we timed out then we're done */
139 kill(buffered_pid, SIGKILL);
140 kill(dio_pid, SIGKILL);
141 printf("ran for %d seconds without error, passing\n", SECONDS);
142 exit(0);
143 }
144
145 if (pid == dio_pid)
146 kill(buffered_pid, SIGKILL);
147 else
148 kill(dio_pid, SIGKILL);
149
150 /*
151 * pass on the child's pass/fail return code or fail if the child
152 * didn't exit cleanly.
153 */
154 exit(WIFEXITED(status) ? WEXITSTATUS(status) : 1);
155 }
156