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
14static 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
21static int chunkorder[NRCHUNKS];
22
23static 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
34static 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
57static 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
66int 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