Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include "stdinc.h"
#include "dat.h"
#include "fns.h"

static int      verbose;

static void
checkarena(Arena *arena, int scan, int fix)
{
        ATailStats old;
        int err, e;

        if(verbose && arena->memstats.clumps)
                printarena(2, arena);

        old = arena->memstats;

        if(scan){
                arena->memstats.used = 0;
                arena->memstats.clumps = 0;
                arena->memstats.cclumps = 0;
                arena->memstats.uncsize = 0;
        }

        err = 0;
        for(;;){
                e = syncarena(arena, 1000, 0, fix);
                err |= e;
                if(!(e & SyncHeader))
                        break;
                if(verbose && arena->memstats.clumps)
                        fprint(2, ".");
        }
        if(verbose && arena->memstats.clumps)
                fprint(2, "\n");

        err &= ~SyncHeader;
        if(arena->memstats.used != old.used
        || arena->memstats.clumps != old.clumps
        || arena->memstats.cclumps != old.cclumps
        || arena->memstats.uncsize != old.uncsize){
                fprint(2, "%s: incorrect arena header fields\n", arena->name);
                printarena(2, arena);
                err |= SyncHeader;
        }

        if(!err || !fix)
                return;

        fprint(2, "%s: writing fixed arena header fields\n", arena->name);
        arena->diskstats = arena->memstats;
        if(wbarena(arena) < 0)
                fprint(2, "arena header write failed: %r\n");
        flushdcache();
}

void
usage(void)
{
        fprint(2, "usage: checkarenas [-afv] file [arenaname...]\n");
        threadexitsall(0);
}

int
should(char *name, int argc, char **argv)
{
        int i;

        if(argc == 0)
                return 1;
        for(i=0; i<argc; i++)
                if(strcmp(name, argv[i]) == 0)
                        return 1;
        return 0;
}

void
threadmain(int argc, char *argv[])
{
        ArenaPart *ap;
        Part *part;
        char *file;
        int i, fix, scan;

        ventifmtinstall();
        statsinit();

        fix = 0;
        scan = 0;
        ARGBEGIN{
        case 'f':
                fix++;
                break;
        case 'a':
                scan = 1;
                break;
        case 'v':
                verbose++;
                break;
        default:
                usage();
                break;
        }ARGEND

        if(!fix)
                readonly = 1;

        if(argc < 1)
                usage();

        file = argv[0];
        argc--;
        argv++;

        part = initpart(file, (fix ? ORDWR : OREAD)|ODIRECT);
        if(part == nil)
                sysfatal("can't open partition %s: %r", file);

        ap = initarenapart(part);
        if(ap == nil)
                sysfatal("can't initialize arena partition in %s: %r", file);

        if(verbose > 1){
                printarenapart(2, ap);
                fprint(2, "\n");
        }

        initdcache(8 * MaxDiskBlock);

        for(i = 0; i < ap->narenas; i++)
                if(should(ap->arenas[i]->name, argc, argv)) {
                        debugarena = i;
                        checkarena(ap->arenas[i], scan, fix);
                }

        if(verbose > 1)
                printstats();
        threadexitsall(0);
}