ref: f31b4ce3b34f7191f7cfdae7b3d88e8e27e6b179
dir: /checkarena.c/
#include <u.h>
#include <libc.h>
#include <bio.h>
#include "neoventi.h"
extern VtArena *arenas;
char *arenapath;
char *isectpath;
extern u32int numarenas;
int mainstacksize = 128*1024;
char *configpath = "/dev/kaladin/arenas";
int
checkarenas(void)
{
int bad = 0;
u8int magicbuf[4];
u32int magic;
u64int addr;
for(int i = numarenas-1; i >= 0; i -= 1){
addr = arenas[i].indexstats.used;
fprint(2, ".");
if(i % 20 == 19 || i+1 == numarenas)
fprint(2, "\n");
for(int j = 0 ; 1 ; j += 1){
if(vtarenaread(&arenas[i], addr, magicbuf, 4) != 4){
fprint(2, "corrupt arena");
bad = 1;
break;
}
magic = U32GET(magicbuf);
if(magic == 0 || addr == 0) // TODO: verify stopping point
break;
if(magic == arenas[i].clumpmagic)
fprint(2, ".");
else{
bad = 1;
fprint(2, "arena contains invalid clumps! magic: %08x, clumpmagic: %08x", magic, arenas[i].clumpmagic);
break;
}
}
};
return !bad;
}
void
parseargs(int argc, char **argv)
{
ARGBEGIN {
case 'c':
configpath = ARGF();
if(configpath == nil)
sysfatal("must specify a config path");
break;
default:
sysfatal("unsupported flag '%c'", ARGC());
break;
} ARGEND;
}
static void
configvalidate(char *buf)
{
if(memcmp(buf, "venti config\n", 13) != 0)
sysfatal("invalid config");
}
static void
configparse(char *buf)
{
char *lines[16];
char *fields[2];
int nlines = getfields(buf+13, lines, 16, 0, "\n");
for(int i = 0; i < nlines; i += 1){
if(strlen(lines[i]) == 0)
continue;
if(tokenize(lines[i], fields, 2) != 2)
sysfatal("invalid config, bad tokenize on line %d", i);
if(strcmp(fields[0], "arenas") == 0)
arenapath = strdup(fields[1]);
else if(strcmp(fields[0], "isect") == 0)
isectpath = strdup(fields[1]);
else if(strcmp(fields[0], "bcmem") == 0 || strcmp(fields[0], "mem") == 0 || strcmp(fields[0], "icmem") == 0)
// ignore cache sizing
{}
else if(strcmp(fields[0], "addr") == 0)
// no tcp server her
{}
else if(strcmp(fields[0], "httpaddr") == 0)
// no http server, fuck that
{}
else if(strcmp(fields[0], "index") == 0)
// apparently no effect????
{}
else
fprint(2, "ignoring config directive '%s'\n", fields[0]);
}
}
static void
loadconfig(void)
{
// Config is either a flat file, or is the last 8K of a 256K block
int fd = open(configpath, OREAD);
Dir *dir = dirfstat(fd);
// NOTE venti technically allows for 8K bytes of config. Fuck that.
// 8191 bytes is enough for anybody.
char buf[8192];
if(fd < 0 || dir == nil)
sysfatal("unable to open config '%s'", configpath);
if(dir->length > 256*1024){
// Config partition
vlong w = pread(fd, buf, 8192, 248*1024);
if(w < 0)
sysfatal("unable to read configpart '%s'", configpath);
else if(w == 0)
sysfatal("configpart empty!");
} else if(pread(fd, buf, 8192, 0) <= 0)
sysfatal("unable to read config file '%s'", configpath);
// Just in case.
buf[8191] = 0;
configvalidate(buf);
configparse(buf);
}
void
threadmain(int argc, char **argv)
{
parseargs(argc, argv);
fprint(2, "loading config... ");
loadconfig();
cacheinit();
fprint(2, "loading arena partition metadata... ");
initarenas();
fprint(2, "...scanning.\n");
if(!checkarenas())
sysfatal("arenas do be corrupt, yo!");
fprint(2, "looks like you're good - for now...\n");
}