shithub: neoventi

ref: f31b4ce3b34f7191f7cfdae7b3d88e8e27e6b179
dir: /checkarena.c/

View raw version
#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");
}