Home | History | Annotate | Download | only in linus_stress
      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 
     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 
     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 
     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 
     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 
     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