shithub: neoventi

ref: f31b4ce3b34f7191f7cfdae7b3d88e8e27e6b179
dir: /arena.c/

View raw version
#include <u.h>
#include <libc.h>
#include <bio.h>
#include "neoventi.h"

int
arenarepair(VtArena *arena, uchar *ci, u64int addr)
{
	uchar buf[30];
	u16int tmp;
	if(!vtarenaread(arena, addr, buf, 30)){
		werrstr("arenarepair: %r");
		return 0;
	}
	if(U32GET(buf) != arena->clumpmagic){
		werrstr("arenarepair: magic is incorrect. If this block was not written by old-venti, you may have a problem.");
		return 0;
	}
	// Update the clumpinfo, just in case.
	ci[0] = 1;
	U16PUT(ci + 1, tmp);
	U16PUT(ci + 3, U16GET(buf + 7));
	return 1;
}

int
vtarenasync(VtArena *arena)
{
	// First, check if the directory and the data log are in sync
	fprint(2, "skipping arena sync, logic needs rethought...\n");
	return 1;
	usize n, m, corruptchain;
	char *buf, *ci;
	u32int block, perblock, off;
	u64int addr, goodaddr;
	int good;
	n = arena->arenastats.clumps;
	corruptchain = 0;
	fprint(2, "clumps: %d, %d\n", n, arena->indexstats.clumps);
	if(n == arena->indexstats.clumps)
		return 1;
	buf = nil;
	perblock = arena->blocksize / ClumpInfoSize;
	off = 0;
	addr = 0;
	for(m = 0; m < n; m += 1){
		if(m % perblock == 0){
			// Load next block
			if(buf != nil)
				cacheunlock(arena->index, block);
			block = (arena->size / arena->blocksize) - 1 - (m / perblock);
			buf = vtarenareadblock(arena, block);
			if(buf == nil){
				werrstr("vtarenasync: unable to read CIG: %r");
				return 0;
			}
			off = 0;
		}
		off += ClumpInfoSize;
		ci = &buf[off];
		good = arenarepair(arena, (u8int*)ci, addr);
		addr += (((u64int)(U16GET(ci + 1))) + 38);
		if(!good){
			fprint(2, "clump %d is broken, at address %llud: %r\n", m, addr);
			corruptchain += 1;
			// Skip. old venti creates corruption in some easy-to-repro cases
			// (e.g. write, kill venti within a few seconds) and I don't need people
			// complaining about it.
		} else {
			corruptchain = 0;
			goodaddr = addr;
		}
	}
	if(addr != goodaddr){
		assert(corruptchain > 0);
		fprint(2, "corruption detected: the last %d clumps are corrupt. Dropping them.\n"
				  "\taddr dropped from %llud to %llud\n",
		corruptchain, addr, goodaddr);
		addr = goodaddr;
		arena->arenastats.clumps -= corruptchain;
	}
	if(arena->arenastats.used != addr){
		fprint(2, "corrupt: found addr %d, expected %d", addr, arena->arenastats.used);
		arena->arenastats.used = addr;
	}
	// TODO: we haven't updated indexstats->clumps, so this is safe, but we _do_
	// need to be indexing these clumps.
	vtarenawb(arena);
	return 1;
}

int
vtarenawritedirectory(VtArena *arena, char score[20], u16int uncsize)
{
	return 0;
}

int
vtarenawb(VtArena *arena)
{
	char *buf, *p;
	u32int blockindex, t;
	int ret;
	blockindex = arena->size / arena->blocksize;
	// FIXME rebuild on vtarenareadblock
	if(!cachelookup(&buf, arena->index, blockindex)){
		if(pread(arena->fd, buf, arena->blocksize, arena->base + arena->size) != arena->blocksize)
			sysfatal("failed to pread");
	}
	p = buf + 8 + NameSize;
	// Only support split stats
	U32PUT(p, arena->indexstats.clumps);
	// If it wasn't already using split arenastats and index stats, make it so.
	// If it wasn't, that space should be clear.
	p[37] = 1;
	U32PUT(p + 38, arena->arenastats.clumps);
	U64PUT(p + 46, arena->arenastats.used, t);
	p[62] = arena->arenastats.sealed;
	ret = pwrite(arena->fd, buf, arena->blocksize, arena->base + arena->size);
	cacheunlock(arena->index, blockindex);
	if(ret != arena->blocksize){
		werrstr("writeback failed: %r");
		return 0;
	}
	return 1;
}