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
38static 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
45void 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
78void 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
89static void alarm_handler(int signum)
90{
91}
92
93int 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