1 #include <sys/mman.h>
2 #include <sys/fcntl.h>
3 #include <unistd.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <stdio.h>
7 #include <time.h>
8
9 #define TARGETSIZE (100 << 20)
10 #define CHUNKSIZE (1460)
11 #define NRCHUNKS (TARGETSIZE / CHUNKSIZE)
12 #define SIZE (NRCHUNKS * CHUNKSIZE)
13
fillmem(void * start,int nr)14 static void fillmem(void *start, int nr)
15 {
16 memset(start, nr, CHUNKSIZE);
17 }
18
19 #define page_offset(buf, off) (0xfff & ((unsigned)(unsigned long)(buf)+(off)))
20
21 static int chunkorder[NRCHUNKS];
22
order(int nr)23 static int order(int nr)
24 {
25 int i;
26 if (nr < 0 || nr >= NRCHUNKS)
27 return -1;
28 for (i = 0; i < NRCHUNKS; i++)
29 if (chunkorder[i] == nr)
30 return i;
31 return -2;
32 }
33
checkmem(void * buf,int nr)34 static void checkmem(void *buf, int nr)
35 {
36 unsigned int start = ~0u, end = 0;
37 unsigned char c = nr, *p = buf, differs = 0;
38 int i;
39 for (i = 0; i < CHUNKSIZE; i++) {
40 unsigned char got = *p++;
41 if (got != c) {
42 if (i < start)
43 start = i;
44 if (i > end)
45 end = i;
46 differs = got;
47 }
48 }
49 if (start < end) {
50 printf("Chunk %d corrupted (%u-%u) (%u-%u) \n", nr, start, end,
51 page_offset(buf, start), page_offset(buf, end));
52 printf("Expected %u, got %u\n", c, differs);
53 printf("Written as (%d)%d(%d)\n", order(nr-1), order(nr), order(nr+1));
54 }
55 }
56
remap(int fd,char * mapping)57 static char *remap(int fd, char *mapping)
58 {
59 if (mapping) {
60 munmap(mapping, SIZE);
61 posix_fadvise(fd, 0, SIZE, POSIX_FADV_DONTNEED);
62 }
63 return mmap(NULL, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
64 }
65
main(int argc,char ** argv)66 int main(int argc, char **argv)
67 {
68 char *mapping;
69 int fd, i;
70
71 /*
72 * Make some random ordering of writing the chunks to the
73 * memory map..
74 *
75 * Start with fully ordered..
76 */
77 for (i = 0; i < NRCHUNKS; i++)
78 chunkorder[i] = i;
79
80 /* ..and then mix it up randomly */
81 srandom(time(NULL));
82 for (i = 0; i < NRCHUNKS; i++) {
83 int index = (unsigned int) random() % NRCHUNKS;
84 int nr = chunkorder[index];
85 chunkorder[index] = chunkorder[i];
86 chunkorder[i] = nr;
87 }
88
89 fd = open("mapfile", O_RDWR | O_TRUNC | O_CREAT, 0666);
90 if (fd < 0)
91 return -1;
92 if (ftruncate(fd, SIZE) < 0)
93 return -1;
94 mapping = remap(fd, NULL);
95 if (-1 == (int)(long)mapping)
96 return -1;
97
98 for (i = 0; i < NRCHUNKS; i++) {
99 int chunk = chunkorder[i];
100 printf("Writing chunk %d/%d (%d%%) \r", i, NRCHUNKS, 100*i/NRCHUNKS);
101 fillmem(mapping + chunk * CHUNKSIZE, chunk);
102 }
103 printf("\n");
104
105 /* Unmap, drop, and remap.. */
106 mapping = remap(fd, mapping);
107
108 /* .. and check */
109 for (i = 0; i < NRCHUNKS; i++) {
110 int chunk = i;
111 printf("Checking chunk %d/%d (%d%%) \r", i, NRCHUNKS, 100*i/NRCHUNKS);
112 checkmem(mapping + chunk * CHUNKSIZE, chunk);
113 }
114 printf("\n");
115
116 return 0;
117 }
118
119