Attached is yet another version ...
Now is.
#include <sys/mman.h>
#include <sys/fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#define TARGETSIZE (120 << 20)
#define CHUNKSIZE (1460)
#define NRCHUNKS (TARGETSIZE / CHUNKSIZE)
#define SIZE (NRCHUNKS * CHUNKSIZE)
static void fillmem(void *start, int nr)
{
memset(start, nr, CHUNKSIZE);
}
#define page_offset(buf, off) (0xfff & ((unsigned)(unsigned long)(buf)+(off)))
static int do_write = 1, do_advise = 1, verbose = 0, linear = 0;
static int first_corrupt = -1;
static int sum_corrupt = 0;
static int chunkorder[NRCHUNKS];
static int order(int nr)
{
int i;
if (nr < 0 || nr >= NRCHUNKS)
return -1;
for (i = 0; i < NRCHUNKS; i++)
if (chunkorder[i] == nr)
return i;
return -2;
}
static void checkmem(void *buf, int nr)
{
unsigned int start = ~0u, end = 0;
unsigned char c = nr, *p = buf, differs = 0;
int i;
for (i = 0; i < CHUNKSIZE; i++) {
unsigned char got = *p++;
if (got != c) {
if (i < start)
start = i;
if (i > end)
end = i;
differs = got;
}
}
if (start < end) {
if ( verbose ) {
printf("Chunk %d corrupted (%u-%u) (%u-%u)\n", nr, start, end,
page_offset(buf, start), page_offset(buf, end));
printf("Expected %u, got %u\n", c, differs);
printf("Written as (%d)%d(%d)\n",order(nr-1),order(nr),order(nr+1));
}
sum_corrupt++;
if ( first_corrupt == -1 )
first_corrupt = nr;
}
else {
if ( first_corrupt != -1 ) {
//printf("chunks %i through %i are corrupted\n", first_corrupt,
nr-1);
first_corrupt = -1;
}
}
}
static char *remap(int fd, char *mapping)
{
if (mapping) {
munmap(mapping, SIZE);
if ( do_advise )
posix_fadvise(fd, 0, SIZE, POSIX_FADV_DONTNEED);
}
return mmap(NULL, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
}
int main(int argc, char **argv)
{
char *mapping = NULL;
int fd, i;
printf("target size: %lu (%u MB)\n", SIZE, SIZE >> 20);
for ( i = 1 ; i < argc ; i++ )
if ( strncmp(argv[i], "-r", 2) == 0 ) {
do_write = 0;
printf("trying read test only\n");
}
else if ( strncmp(argv[i], "-a", 2) == 0 ) { /* AFS mode ;-( */
do_advise = 0;
printf("disabling call to posix_fadvise\n");
}
else if ( strncmp(argv[i], "-v", 2) == 0 ) {
verbose = 1;
printf("enabeling verbose mode\n");
}
else if ( strncmp(argv[i], "-l", 2) == 0 ) {
linear = 1;
printf("writing data linearly, NOT randomly\n");
}
/*
* Make some random ordering of writing the chunks to the
* memory map..
*
* Start with fully ordered..
*/
for (i = 0; i < NRCHUNKS; i++)
chunkorder[i] = i;
/* ..and then mix it up randomly */
if ( !linear ) {
srandom(time(NULL));
for (i = 0; i < NRCHUNKS; i++) {
int index = (unsigned int) random() % NRCHUNKS;
int nr = chunkorder[index];
chunkorder[index] = chunkorder[i];
chunkorder[i] = nr;
}
}
fd = open("mapfile", O_RDWR | O_CREAT | (do_write ? O_TRUNC : 0), 0666);
if (fd < 0)
return -1;
if (ftruncate(fd, SIZE) < 0)
return -1;
if ( do_write ) {
mapping = remap(fd, NULL);
if (-1 == (int)(long)mapping)
return -1;
printf("Writing chunks...\n");
for (i = 0; i < NRCHUNKS; i++) {
int chunk = chunkorder[i];
printf("Writing chunk %d/%d (%d%%) \r",i, NRCHUNKS,
100*i/NRCHUNKS);
fillmem(mapping + chunk * CHUNKSIZE, chunk);
}
//printf("\n");
}
/* Unmap, drop, and remap.. */
mapping = remap(fd, mapping);
/* .. and check */
printf("Checking chunks...\n");
for (i = 0; i < NRCHUNKS; i++) {
int chunk = i;
printf("Checking chunk %d/%d (%d%%) \r", i, NRCHUNKS,
100*i/NRCHUNKS);
checkmem(mapping + chunk * CHUNKSIZE, chunk);
}
printf("\n");
printf("%i corrupted blocks (i.e. %i%%)\n",
sum_corrupt, 100 * sum_corrupt / NRCHUNKS );
printf("%i OK blocks\n", NRCHUNKS - sum_corrupt);
return 0;
}