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;
}

Reply via email to