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