Beispiel #1
0
static int
dirEntrySize(Source *s, ulong elem, ulong gen, uvlong *size)
{
	Block *b;
	ulong bn;
	Entry e;
	int epb;

	epb = s->dsize/VtEntrySize;
	bn = elem/epb;
	elem -= bn*epb;

	b = sourceBlock(s, bn, OReadOnly);
	if(b == nil)
		goto Err;
	if(!entryUnpack(&e, b->data, elem))
		goto Err;

	/* hanging entries are returned as zero size */
	if(!(e.flags & VtEntryActive) || e.gen != gen)
		*size = 0;
	else
		*size = e.size;
	blockPut(b);
	return 1;

Err:
	blockPut(b);
	return 0;
}
Beispiel #2
0
/* assume file is locked, assume f->msource is locked */
static int
fileCheckEmpty(File *f)
{
	u32int i, n;
	Block *b;
	MetaBlock mb;
	Source *r;

	r = f->msource;
	n = (sourceGetSize(r)+r->dsize-1)/r->dsize;
	for(i=0; i<n; i++){
		b = sourceBlock(r, i, OReadOnly);
		if(b == nil)
			goto Err;
		if(!mbUnpack(&mb, b->data, r->dsize))
			goto Err;
		if(mb.nindex > 0){
			vtSetError(ENotEmpty);
			goto Err;
		}
		blockPut(b);
	}
	return 1;
Err:
	blockPut(b);
	return 0;
}
Beispiel #3
0
Tnode*
initxsuper(void)
{
    Block *b;
    Tnode *t;

    b = readBlock(PartSuper, 0);
    if(b == nil)
        return stringnode("reading super: %r");
    if(!superUnpack(&super, b->data)) {
        blockPut(b);
        return stringnode("unpacking super: %r");
    }
    blockPut(b);
    t = stringnode("super "
                   "version=%#ux "
                   "epoch=[%#ux,%#ux) "
                   "qid=%#llux "
                   "active=%#x "
                   "next=%#x "
                   "current=%#x "
                   "last=%V "
                   "name=%s",
                   super.version, super.epochLow, super.epochHigh,
                   super.qid, super.active, super.next, super.current,
                   super.last, super.name);
    t->expand = xsuperexpand;
    return t;
}
Beispiel #4
0
static int
getEntry(Source *r, Entry *e, int checkepoch)
{
	u32int epoch;
	Block *b;

	if(r == nil){
		memset(&e, 0, sizeof e);
		return 1;
	}

	b = cacheGlobal(r->fs->cache, r->score, BtDir, r->tag, OReadOnly);
	if(b == nil)
		return 0;
	if(!entryUnpack(e, b->data, r->offset % r->epb)){
		blockPut(b);
		return 0;
	}
	epoch = b->l.epoch;
	blockPut(b);

	if(checkepoch){
		b = cacheGlobal(r->fs->cache, e->score, entryType(e), e->tag, OReadOnly);
		if(b){
			if(b->l.epoch >= epoch)
				fprint(2, "warning: entry %p epoch not older %#.8ux/%d %V/%d in getEntry\n",
					r, b->addr, b->l.epoch, r->score, epoch);
			blockPut(b);
		}
	}

	return 1;
}
Beispiel #5
0
static int
sourceKill(Source *r, int doremove)
{
    Entry e;
    Block *b;
    uint32_t addr;
    uint32_t tag;
    int type;

    assert(sourceIsLocked(r));
    b = sourceLoad(r, &e);
    if(b == nil)
        return 0;

    assert(b->l.epoch == r->fs->ehi);

    if(doremove==0 && e.size == 0) {
        /* already truncated */
        blockPut(b);
        return 1;
    }

    /* remember info on link we are removing */
    addr = globalToLocal(e.score);
    type = entryType(&e);
    tag = e.tag;

    if(doremove) {
        if(e.gen != ~0)
            e.gen++;
        e.dsize = 0;
        e.psize = 0;
        e.flags = 0;
    } else {
        e.flags &= ~VtEntryLocal;
    }
    e.depth = 0;
    e.size = 0;
    e.tag = 0;
    memmove(e.score, vtZeroScore, VtScoreSize);
    entryPack(&e, b->data, r->offset % r->epb);
    blockDirty(b);
    if(addr != NilBlock)
        blockRemoveLink(b, addr, type, tag, 1);
    blockPut(b);

    if(doremove) {
        sourceUnlock(r);
        sourceClose(r);
    }

    return 1;
}
Beispiel #6
0
static void
checkEpoch(Fsck *chk, u32int epoch)
{
	u32int a;
	Block *b;
	Entry e;
	Label l;

	chk->print("checking epoch %ud...\n", epoch);

	for(a=0; a<chk->nblocks; a++){
		if(!readLabel(chk->cache, &l, (a+chk->hint)%chk->nblocks)){
			error(chk, "could not read label for addr 0x%.8#ux", a);
			continue;
		}
		if(l.tag == RootTag && l.epoch == epoch)
			break;
	}

	if(a == chk->nblocks){
		chk->print("could not find root block for epoch %ud", epoch);
		return;
	}

	a = (a+chk->hint)%chk->nblocks;
	b = cacheLocalData(chk->cache, a, BtDir, RootTag, OReadOnly, 0);
	if(b == nil){
		error(chk, "could not read root block 0x%.8#ux: %R", a);
		return;
	}

	/* no one should point at root blocks */
	setBit(chk->amap, a);
	setBit(chk->emap, a);
	setBit(chk->xmap, a);

	/*
	 * First entry is the rest of the file system.
	 * Second entry is link to previous epoch root,
	 * just a convenience to help the search.
	 */
	if(!entryUnpack(&e, b->data, 0)){
		error(chk, "could not unpack root block 0x%.8#ux: %R", a);
		blockPut(b);
		return;
	}
	walkEpoch(chk, b, e.score, BtDir, e.tag, epoch);
	if(entryUnpack(&e, b->data, 1))
		chk->hint = globalToLocal(e.score);
	blockPut(b);
}
Beispiel #7
0
/*
 * Change the depth of the source r.
 * The entry e for r is contained in block p.
 */
static int
sourceGrowDepth(Source *r, Block *p, Entry *e, int depth)
{
    Block *b, *bb;
    uint32_t tag;
    int type;
    Entry oe;

    assert(sourceIsLocked(r));
    assert(depth <= VtPointerDepth);

    type = entryType(e);
    b = cacheGlobal(r->fs->cache, e->score, type, e->tag, OReadWrite);
    if(b == nil)
        return 0;

    tag = e->tag;
    if(tag == 0)
        tag = tagGen();

    oe = *e;

    /*
     * Keep adding layers until we get to the right depth
     * or an error occurs.
     */
    while(e->depth < depth) {
        bb = cacheAllocBlock(r->fs->cache, type+1, tag, r->fs->ehi, r->fs->elo);
        if(bb == nil)
            break;
//fprint(2, "alloc %lux grow %V\n", bb->addr, b->score);
        memmove(bb->data, b->score, VtScoreSize);
        memmove(e->score, bb->score, VtScoreSize);
        e->depth++;
        type++;
        e->tag = tag;
        e->flags |= VtEntryLocal;
        blockDependency(bb, b, 0, vtZeroScore, nil);
        blockPut(b);
        b = bb;
        blockDirty(b);
    }

    entryPack(e, p->data, r->offset % r->epb);
    blockDependency(p, b, r->offset % r->epb, nil, &oe);
    blockPut(b);
    blockDirty(p);

    return e->depth == depth;
}
Beispiel #8
0
int
sourceSetSize(Source *r, uint64_t size)
{
    int depth;
    Entry e;
    Block *b;

    assert(sourceIsLocked(r));
    if(size == 0)
        return sourceTruncate(r);

    if(size > VtMaxFileSize || size > ((uint64_t)MaxBlock)*r->dsize) {
        vtSetError(ETooBig);
        return 0;
    }

    b = sourceLoad(r, &e);
    if(b == nil)
        return 0;

    /* quick out */
    if(e.size == size) {
        blockPut(b);
        return 1;
    }

    depth = sizeToDepth(size, e.psize, e.dsize);

    if(depth < e.depth) {
        if(!sourceShrinkDepth(r, b, &e, depth)) {
            blockPut(b);
            return 0;
        }
    } else if(depth > e.depth) {
        if(!sourceGrowDepth(r, b, &e, depth)) {
            blockPut(b);
            return 0;
        }
    }

    if(size < e.size)
        sourceShrinkSize(r, &e, size);

    e.size = size;
    entryPack(&e, b->data, r->offset % r->epb);
    blockDirty(b);
    blockPut(b);

    return 1;
}
Beispiel #9
0
static int
fileMetaRemove(File *f, char *uid)
{
	Block *b;
	MetaBlock mb;
	MetaEntry me;
	int i;
	File *up;

	up = f->up;

	fileWAccess(up, uid);

	fileMetaLock(f);

	sourceLock(up->msource, OReadWrite);
	b = sourceBlock(up->msource, f->boff, OReadWrite);
	if(b == nil)
		goto Err;

	if(!mbUnpack(&mb, b->data, up->msource->dsize))
{
fprint(2, "U\n");
		goto Err;
}
	if(!mbSearch(&mb, f->dir.elem, &i, &me))
{
fprint(2, "S\n");
		goto Err;
}
	mbDelete(&mb, i);
	mbPack(&mb);
	sourceUnlock(up->msource);

	blockDirty(b);
	blockPut(b);

	f->removed = 1;
	f->boff = NilBlock;
	f->dirty = 0;

	fileMetaUnlock(f);
	return 1;

Err:
	sourceUnlock(up->msource);
	blockPut(b);
	fileMetaUnlock(f);
	return 0;
}
Beispiel #10
0
static int
deeFill(DirEntryEnum *dee)
{
	int i, n;
	Source *meta, *source;
	MetaBlock mb;
	MetaEntry me;
	File *f;
	Block *b;
	DirEntry *de;

	/* clean up first */
	for(i=dee->i; i<dee->n; i++)
		deCleanup(dee->buf+i);
	vtMemFree(dee->buf);
	dee->buf = nil;
	dee->i = 0;
	dee->n = 0;

	f = dee->file;

	source = f->source;
	meta = f->msource;

	b = sourceBlock(meta, dee->boff, OReadOnly);
	if(b == nil)
		goto Err;
	if(!mbUnpack(&mb, b->data, meta->dsize))
		goto Err;

	n = mb.nindex;
	dee->buf = vtMemAlloc(n * sizeof(DirEntry));

	for(i=0; i<n; i++){
		de = dee->buf + i;
		meUnpack(&me, &mb, i);
		if(!deUnpack(de, &me))
			goto Err;
		dee->n++;
		if(!(de->mode & ModeDir))
		if(!dirEntrySize(source, de->entry, de->gen, &de->size))
			goto Err;
	}
	dee->boff++;
	blockPut(b);
	return 1;
Err:
	blockPut(b);
	return 0;
}
Beispiel #11
0
static void
scanSource(Fsck *chk, char *name, Source *r)
{
	u32int a, nb, o;
	Block *b;
	Entry e;

	if(!chk->useventi && globalToLocal(r->score)==NilBlock)
		return;
	if(!sourceGetEntry(r, &e)){
		error(chk, "could not get entry for %s", name);
		return;
	}
	a = globalToLocal(e.score);
	if(!chk->useventi && a==NilBlock)
		return;
	if(getBit(chk->smap, a))
		return;
	setBit(chk->smap, a);

	nb = (sourceGetSize(r) + r->dsize-1) / r->dsize;
	for(o = 0; o < nb; o++){
		b = sourceBlock(r, o, OReadOnly);
		if(b == nil){
			error(chk, "could not read block in data file %s", name);
			continue;
		}
		if(b->addr != NilBlock && getBit(chk->errmap, b->addr)){
			warn(chk, "previously reported error in block %ux is in file %s",
				b->addr, name);
		}
		blockPut(b);
	}
}
Beispiel #12
0
int
fsEpochLow(Fs *fs, uint32_t low)
{
	Block *bs;
	Super super;

	vtLock(fs->elk);
	if(low > fs->ehi){
		vtSetError("bad low epoch (must be <= %ud)", fs->ehi);
		vtUnlock(fs->elk);
		return 0;
	}

	if((bs = superGet(fs->cache, &super)) == nil){
		vtUnlock(fs->elk);
		return 0;
	}

	super.epochLow = low;
	fs->elo = low;
	superWrite(bs, &super, 1);
	blockPut(bs);
	vtUnlock(fs->elk);

	return 1;
}
Beispiel #13
0
/*
 * Lock two (usually sibling) sources.  This needs special care
 * because the Entries for both sources might be in the same block.
 * We also try to lock blocks in left-to-right order within the tree.
 */
int
sourceLock2(Source *r, Source *rr, int mode)
{
    Block *b, *bb;

    if(rr == nil)
        return sourceLock(r, mode);

    if(mode == -1)
        mode = r->mode;

    if(r->parent==rr->parent && r->offset/r->epb == rr->offset/rr->epb) {
        b = sourceLoadBlock(r, mode);
        if(b == nil)
            return 0;
        if(memcmp(r->score, rr->score, VtScoreSize) != 0) {
            memmove(rr->score, b->score, VtScoreSize);
            rr->scoreEpoch = b->l.epoch;
            rr->tag = b->l.tag;
            rr->epoch = rr->fs->ehi;
        }
        blockDupLock(b);
        bb = b;
    } else if(r->parent==rr->parent || r->offset > rr->offset) {
        bb = sourceLoadBlock(rr, mode);
        b = sourceLoadBlock(r, mode);
    } else {
        b = sourceLoadBlock(r, mode);
        bb = sourceLoadBlock(rr, mode);
    }
    if(b == nil || bb == nil) {
        if(b)
            blockPut(b);
        if(bb)
            blockPut(bb);
        return 0;
    }

    /*
     * The fact that we are holding b and bb serves
     * as the lock entitling us to write to r->b and rr->b.
     */
    r->b = b;
    rr->b = bb;
    return 1;
}
Beispiel #14
0
/*
 * the file is locked already
 * f->msource is unlocked
 */
static File *
dirLookup(File *f, char *elem)
{
	int i;
	MetaBlock mb;
	MetaEntry me;
	Block *b;
	Source *meta;
	File *ff;
	u32int bo, nb;

	meta = f->msource;
	b = nil;
	if(!sourceLock(meta, -1))
		return nil;
	nb = (sourceGetSize(meta)+meta->dsize-1)/meta->dsize;
	for(bo=0; bo<nb; bo++){
		b = sourceBlock(meta, bo, OReadOnly);
		if(b == nil)
			goto Err;
		if(!mbUnpack(&mb, b->data, meta->dsize))
			goto Err;
		if(mbSearch(&mb, elem, &i, &me)){
			ff = fileAlloc(f->fs);
			if(!deUnpack(&ff->dir, &me)){
				fileFree(ff);
				goto Err;
			}
			sourceUnlock(meta);
			blockPut(b);
			ff->boff = bo;
			ff->mode = f->mode;
			ff->issnapshot = f->issnapshot;
			return ff;
		}

		blockPut(b);
		b = nil;
	}
	vtSetError(ENoFile);
	/* fall through */
Err:
	sourceUnlock(meta);
	blockPut(b);
	return nil;
}
Beispiel #15
0
void
sourceUnlock(Source *r)
{
    Block *b;

    if(r->b == nil) {
        fprint(2, "sourceUnlock: already unlocked\n");
        abort();
    }
    b = r->b;
    r->b = nil;
    blockPut(b);
}
Beispiel #16
0
int
sourceGetEntry(Source *r, Entry *e)
{
    Block *b;

    assert(sourceIsLocked(r));
    b = sourceLoad(r, e);
    if(b == nil)
        return 0;
    blockPut(b);

    return 1;
}
Beispiel #17
0
Source *
sourceRoot(Fs *fs, uint32_t addr, int mode)
{
    Source *r;
    Block *b;

    b = cacheLocalData(fs->cache, addr, BtDir, RootTag, mode, 0);
    if(b == nil)
        return nil;

    if(mode == OReadWrite && b->l.epoch != fs->ehi) {
        consPrint("sourceRoot: fs->ehi = %ud, b->l = %L\n",
                  fs->ehi, &b->l);
        blockPut(b);
        vtSetError(EBadRoot);
        return nil;
    }

    r = sourceAlloc(fs, b, nil, 0, mode, 0);
    blockPut(b);
    return r;
}
Beispiel #18
0
/*
 * Changes the file block bn to be the given block score.
 * Very sneaky.  Only used by flfmt.
 */
int
fileMapBlock(File *f, ulong bn, uchar score[VtScoreSize], ulong tag)
{
	Block *b;
	Entry e;
	Source *s;

	if(!fileLock(f))
		return 0;

	s = nil;
	if(f->dir.mode & ModeDir){
		vtSetError(ENotFile);
		goto Err;
	}

	if(f->source->mode != OReadWrite){
		vtSetError(EReadOnly);
		goto Err;
	}

	if(!sourceLock(f->source, -1))
		goto Err;

	s = f->source;
	b = _sourceBlock(s, bn, OReadWrite, 1, tag);
	if(b == nil)
		goto Err;

	if(!sourceGetEntry(s, &e))
		goto Err;
	if(b->l.type == BtDir){
		memmove(e.score, score, VtScoreSize);
		assert(e.tag == tag || e.tag == 0);
		e.tag = tag;
		e.flags |= VtEntryLocal;
		entryPack(&e, b->data, f->source->offset % f->source->epb);
	}else
		memmove(b->data + (bn%(e.psize/VtScoreSize))*VtScoreSize, score, VtScoreSize);
	blockDirty(b);
	blockPut(b);
	sourceUnlock(s);
	fileUnlock(f);
	return 1;

Err:
	if(s)
		sourceUnlock(s);
	fileUnlock(f);
	return 0;
}
Beispiel #19
0
Block*
readBlock(int part, u32int addr)
{
    u32int start, end;
    u64int offset;
    int n, nn;
    Block *b;
    uchar *buf;

    start = partStart(part);
    end = partEnd(part);
    if(addr >= end-start) {
        werrstr("bad addr 0x%.8ux; wanted 0x%.8ux - 0x%.8ux", addr, start, end);
        return nil;
    }

    b = allocBlock();
    b->addr = addr;
    buf = b->data;
    offset = ((u64int)(addr+start))*h.blockSize;
    n = h.blockSize;
    while(n > 0) {
        nn = pread(fd, buf, n, offset);
        if(nn < 0) {
            blockPut(b);
            return nil;
        }
        if(nn == 0) {
            werrstr("short read");
            blockPut(b);
            return nil;
        }
        n -= nn;
        offset += nn;
        buf += nn;
    }
    return b;
}
Beispiel #20
0
Block*
dataBlock(uchar score[VtScoreSize], uint type, uint tag)
{
    Block *b, *bl;
    int lpb;
    Label l;
    u32int addr;

    addr = globalToLocal(score);
    if(addr == NilBlock)
        return ventiBlock(score, type);

    lpb = h.blockSize/LabelSize;
    bl = readBlock(PartLabel, addr/lpb);
    if(bl == nil)
        return nil;
    if(!labelUnpack(&l, bl->data, addr%lpb)) {
        werrstr("%r");
        blockPut(bl);
        return nil;
    }
    blockPut(bl);
    if(l.type != type) {
        werrstr("type mismatch; got %d (%s) wanted %d (%s)",
                l.type, btStr(l.type), type, btStr(type));
        return nil;
    }
    if(tag && l.tag != tag) {
        werrstr("tag mismatch; got 0x%.8ux wanted 0x%.8ux",
                l.tag, tag);
        return nil;
    }
    b = readBlock(PartData, addr);
    if(b == nil)
        return nil;
    b->l = l;
    return b;
}
Beispiel #21
0
static int
setEntry(Source *r, Entry *e)
{
	Block *b;
	Entry oe;

	b = cacheGlobal(r->fs->cache, r->score, BtDir, r->tag, OReadWrite);
	if(0) fprint(2, "setEntry: b %#ux %d score=%V\n", b->addr, r->offset % r->epb, e->score);
	if(b == nil)
		return 0;
	if(!entryUnpack(&oe, b->data, r->offset % r->epb)){
		blockPut(b);
		return 0;
	}
	e->gen = oe.gen;
	entryPack(e, b->data, r->offset % r->epb);

	/* BUG b should depend on the entry pointer */

	blockDirty(b);
	blockPut(b);
	return 1;
}
Beispiel #22
0
uint64_t
sourceGetSize(Source *r)
{
    Entry e;
    Block *b;

    assert(sourceIsLocked(r));
    b = sourceLoad(r, &e);
    if(b == nil)
        return 0;
    blockPut(b);

    return e.size;
}
Beispiel #23
0
/*
 * Must be careful with this.  Doesn't record
 * dependencies, so don't introduce any!
 */
int
sourceSetEntry(Source *r, Entry *e)
{
    Block *b;
    Entry oe;

    assert(sourceIsLocked(r));
    b = sourceLoad(r, &oe);
    if(b == nil)
        return 0;
    entryPack(e, b->data, r->offset%r->epb);
    blockDirty(b);
    blockPut(b);

    return 1;
}
Beispiel #24
0
/*
 * We've just walked the whole write buffer.  Notice blocks that
 * aren't marked available but that we didn't visit.  They are lost.
 */
static void
checkLeak(Fsck *chk)
{
	u32int a, nfree, nlost;
	Block *b;
	Label l;

	nfree = 0;
	nlost = 0;

	for(a = 0; a < chk->nblocks; a++){
		if(!readLabel(chk->cache, &l, a)){
			error(chk, "could not read label: addr 0x%ux %d %d: %R",
				a, l.type, l.state);
			continue;
		}
		if(getBit(chk->amap, a))
			continue;
		if(l.state == BsFree || l.epochClose <= chk->fs->elo ||
		    l.epochClose == l.epoch){
			nfree++;
			setBit(chk->amap, a);
			continue;
		}
		if(l.state&BsClosed)
			continue;
		nlost++;
//		warn(chk, "unreachable block: addr 0x%ux type %d tag 0x%ux "
//			"state %s epoch %ud close %ud", a, l.type, l.tag,
//			bsStr(l.state), l.epoch, l.epochClose);
		b = cacheLocal(chk->cache, PartData, a, OReadOnly);
		if(b == nil){
			error(chk, "could not read block 0x%#.8ux", a);
			continue;
		}
		chk->close(chk, b, 0);
		chk->nclose++;
		setBit(chk->amap, a);
		blockPut(b);
	}
	chk->print("fsys blocks: total=%ud used=%ud(%.1f%%) free=%ud(%.1f%%) lost=%ud(%.1f%%)\n",
		chk->nblocks,
		chk->nblocks - nfree-nlost,
		100.*(chk->nblocks - nfree - nlost)/chk->nblocks,
		nfree, 100.*nfree/chk->nblocks,
		nlost, 100.*nlost/chk->nblocks);
}
Beispiel #25
0
int
saveQid(Fs *fs)
{
	Block *b;
	Super super;
	uint64_t qidMax;

	if((b = superGet(fs->cache, &super)) == nil)
		return 0;
	qidMax = super.qid;
	blockPut(b);

	if(!fileSetQidSpace(fs->file, 0, qidMax))
		return 0;

	return 1;
}
Beispiel #26
0
Block*
superGet(Cache *c, Super* super)
{
	Block *b;

	if((b = cacheLocal(c, PartSuper, 0, OReadWrite)) == nil){
		fprint(2, "%s: superGet: cacheLocal failed: %R\n", argv0);
		return nil;
	}
	if(!superUnpack(super, b->data)){
		fprint(2, "%s: superGet: superUnpack failed: %R\n", argv0);
		blockPut(b);
		return nil;
	}

	return b;
}
Beispiel #27
0
int
fsNextQid(Fs *fs, uint64_t *qid)
{
	Block *b;
	Super super;

	if((b = superGet(fs->cache, &super)) == nil)
		return 0;

	*qid = super.qid++;

	/*
	 * It's okay if the super block doesn't go to disk immediately,
	 * since fileMetaAlloc will record a dependency between the
	 * block holding this qid and the super block.  See file.c:/^fileMetaAlloc.
	 */
	superWrite(b, &super, 0);
	blockPut(b);
	return 1;
}
Beispiel #28
0
void
fsCheck(Fsck *chk)
{
	Block *b;
	Super super;

	checkInit(chk);
	b = superGet(chk->cache, &super);
	if(b == nil){
		chk->print("could not load super block: %R");
		return;
	}
	blockPut(b);

	chk->hint = super.active;
	checkEpochs(chk);

	chk->smap = vtMemAllocZ(chk->nblocks/8+1);
	checkDirs(chk);
	vtMemFree(chk->smap);
}
Beispiel #29
0
Source *
sourceOpen(Source *r, uint32_t offset, int mode, int issnapshot)
{
    uint32_t bn;
    Block *b;

    assert(sourceIsLocked(r));
    if(r->mode == OReadWrite)
        assert(r->epoch == r->b->l.epoch);
    if(!r->dir) {
        vtSetError(ENotDir);
        return nil;
    }

    bn = offset/(r->dsize/VtEntrySize);

    b = sourceBlock(r, bn, mode);
    if(b == nil)
        return nil;
    r = sourceAlloc(r->fs, b, r, offset, mode, issnapshot);
    blockPut(b);
    return r;
}
Beispiel #30
0
Block*
ventiBlock(uchar score[VtScoreSize], uint type)
{
    int n;
    Block *b;

    b = allocBlock();
    memmove(b->score, score, VtScoreSize);
    b->addr = NilBlock;

    n = vtread(z, b->score, vtType[type], b->data, h.blockSize);
    if(n < 0) {
        fprint(2, "vtread returns %d: %r\n", n);
        blockPut(b);
        return nil;
    }
    vtzeroextend(vtType[type], b->data, n, h.blockSize);
    b->l.type = type;
    b->l.state = 0;
    b->l.tag = 0;
    b->l.epoch = 0;
    return b;
}