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