Esempio n. 1
0
File: file.c Progetto: bhanug/harvey
static int
flushblock(VtCache *c, VtBlock *bb, uint8_t score[VtScoreSize], int ppb,
	   int epb,
	int type)
{
	uint32_t addr;
	VtBlock *b;
	VtEntry e;
	int i;

	addr = vtglobaltolocal(score);
	if(addr == NilBlock)
		return 0;

	if(bb){
		b = bb;
		if(memcmp(b->score, score, VtScoreSize) != 0)
			abort();
	}else
		if((b = vtcachelocal(c, addr, type)) == nil)
			return -1;

	switch(type){
	case VtDataType:
		break;

	case VtDirType:
		for(i=0; i<epb; i++){
			if(vtentryunpack(&e, b->data, i) < 0)
				goto Err;
			if(!(e.flags&VtEntryActive))
				continue;
			if(flushblock(c, nil, e.score, e.psize/VtScoreSize, e.dsize/VtEntrySize,
				e.type) < 0)
				goto Err;
			vtentrypack(&e, b->data, i);
		}
		break;
	
	default:	/* VtPointerTypeX */
		for(i=0; i<ppb; i++){
			if(flushblock(c, nil, b->data+VtScoreSize*i, ppb, epb, type-1) < 0)
				goto Err;
		}
		break;
	}

	if(vtblockwrite(b) < 0)
		goto Err;
	memmove(score, b->score, VtScoreSize);
	if(b != bb)
		vtblockput(b);
	return 0;

Err:
	if(b != bb)
		vtblockput(b);
	return -1;
}
Esempio n. 2
0
VtFile *
vtfileroot(VtCache *c, u32int addr, int mode)
{
	VtFile *r;
	VtBlock *b;

	b = vtcachelocal(c, addr, VtDirType);
	if(b == nil)
		return nil;
	r = vtfilealloc(c, b, nil, 0, mode);
	vtblockput(b);
	return r;
}
Esempio n. 3
0
/*
 * Retrieve the block containing the entry for r.
 * If a snapshot has happened, we might need
 * to get a new copy of the block.  We avoid this
 * in the common case by caching the score for
 * the block and the last epoch in which it was valid.
 *
 * We use r->mode to tell the difference between active
 * file system VtFiles (VtORDWR) and VtFiles for the
 * snapshot file system (VtOREAD).
 */
static VtBlock*
fileloadblock(VtFile *r, int mode)
{
	char e[ERRMAX];
	u32int addr;
	VtBlock *b;

	switch(r->mode){
	default:
		assert(0);
	case VtOWRITE:
		assert(r->mode == VtORDWR);
		if(r->local == 1){
			b = vtcacheglobal(r->c, r->score, VtDirType);
			if(b == nil)
				return nil;
			b->pc = getcallerpc(&r);
			return b;
		}
		assert(r->parent != nil);
		if(vtfilelock(r->parent, VtORDWR) < 0)
			return nil;
		b = vtfileblock(r->parent, r->offset/r->epb, VtORDWR);
		if(b == nil)
			b = vtfileblock(r->parent, r->offset/r->epb, VtOWRITE);
		vtfileunlock(r->parent);
		if(b == nil)
			return nil;
		memmove(r->score, b->score, VtScoreSize);
		r->local = 1;
		return b;

	case VtORDWR:
		assert(r->mode == VtORDWR);
		if(r->local == 1){
			b = vtcacheglobal(r->c, r->score, VtDirType);
			if(b == nil)
				return nil;
			b->pc = getcallerpc(&r);
			return b;
		}
		assert(r->parent != nil);
		if(vtfilelock(r->parent, VtORDWR) < 0)
			return nil;
		b = vtfileblock(r->parent, r->offset/r->epb, VtORDWR);
		vtfileunlock(r->parent);
		if(b == nil)
			return nil;
		memmove(r->score, b->score, VtScoreSize);
		r->local = 1;
		return b;

	case VtOREAD:
		if(mode == VtORDWR){
			werrstr("read/write lock of read-only file");
			return nil;
		}
		addr = vtglobaltolocal(r->score);
		if(addr == NilBlock)
			return vtcacheglobal(r->c, r->score, VtDirType);

		b = vtcachelocal(r->c, addr, VtDirType);
		if(b)
			return b;

		/*
		 * If it failed because the epochs don't match, the block has been
		 * archived and reclaimed.  Rewalk from the parent and get the
		 * new pointer.  This can't happen in the VtORDWR case
		 * above because blocks in the current epoch don't get
		 * reclaimed.  The fact that we're VtOREAD means we're
		 * a snapshot.  (Or else the file system is read-only, but then
		 * the archiver isn't going around deleting blocks.)
		 */
		rerrstr(e, sizeof e);
		if(strcmp(e, ELabelMismatch) == 0){
			if(vtfilelock(r->parent, VtOREAD) < 0)
				return nil;
			b = vtfileblock(r->parent, r->offset/r->epb, VtOREAD);
			vtfileunlock(r->parent);
			if(b){
				fprint(2, "vtfilealloc: lost %V found %V\n",
					r->score, b->score);
				memmove(r->score, b->score, VtScoreSize);
				return b;
			}
		}
		return nil;
	}
}