check: try reloading modules
[xfstests-dev.git] / src / t_mmap_write_ro.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <fcntl.h>
5 #include <unistd.h>
6 #include <libgen.h>
7 #include <errno.h>
8 #include <sys/mman.h>
9
10 void
11 err_exit(char *op)
12 {
13         fprintf(stderr, "%s: %s\n", op, strerror(errno));
14         exit(1);
15 }
16
17 int
18 main(int argc, char **argv)
19 {
20         int fd, pfd, ret;
21         char *buf;
22         /*
23          * gcc -O2 will optimize foo's storage, prevent reproducing
24          * this issue.
25          * foo is never actually used after fault in value stored.
26          */
27         volatile char foo __attribute__((__unused__));
28         int pagesize = getpagesize();
29
30         if (argc < 3) {
31                 printf("Usage: %s <file> <pmem file>\n", basename(argv[0]));
32                 exit(0);
33         }
34
35          /* O_DIRECT is necessary for reproduce this bug. */
36         fd = open(argv[1], O_RDONLY|O_DIRECT);
37         if (fd < 0)
38                 err_exit("open");
39
40         pfd = open(argv[2], O_RDONLY);
41         if (pfd < 0)
42                 err_exit("pmem open");
43
44         buf = mmap(NULL, pagesize, PROT_READ, MAP_SHARED, pfd, 0);
45         if (buf == MAP_FAILED)
46                 err_exit("mmap");
47
48         /*
49          * Read from the DAX mmap to populate the first page in the
50          * address_space with a read-only mapping.
51          */
52         foo = *buf;
53
54         /*
55          * Now write to the DAX mmap.  This *should* fail, but if the bug is
56          * present in __get_user_pages_fast(), it will succeed.
57          */
58         ret = read(fd, buf, pagesize);
59         if (ret != pagesize)
60                 err_exit("read");
61
62         ret = msync(buf, pagesize, MS_SYNC);
63         if (ret != 0)
64                 err_exit("msync");
65
66         ret = munmap(buf, pagesize);
67         if (ret < 0)
68                 err_exit("munmap");
69
70         ret = close(fd);
71         if (ret < 0)
72                 err_exit("clsoe fd");
73
74         ret = close(pfd);
75         if (ret < 0)
76                 err_exit("close pfd");
77
78         exit(0);
79 }