Exemplo n.º 1
0
int
fileTruncate(File *f, char *uid)
{
	if(fileIsDir(f)){
		vtSetError(ENotFile);
		return 0;
	}

	if(!fileLock(f))
		return 0;

	if(f->source->mode != OReadWrite){
		vtSetError(EReadOnly);
		fileUnlock(f);
		return 0;
	}
	if(!sourceLock(f->source, -1)){
		fileUnlock(f);
		return 0;
	}
	if(!sourceTruncate(f->source)){
		sourceUnlock(f->source);
		fileUnlock(f);
		return 0;
	}
	sourceUnlock(f->source);
	fileUnlock(f);

	fileWAccess(f, uid);

	return 1;
}
Exemplo n.º 2
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;
}
Exemplo n.º 3
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;
}
Exemplo n.º 4
0
int
deeRead(DirEntryEnum *dee, DirEntry *de)
{
	int ret, didread;
	File *f;
	u32int nb;

	if(dee == nil){
		vtSetError("cannot happen in deeRead");
		return -1;
	}

	f = dee->file;
	if(!fileRLock(f))
		return -1;

	if(!sourceLock2(f->source, f->msource, OReadOnly)){
		fileRUnlock(f);
		return -1;
	}

	nb = (sourceGetSize(f->msource)+f->msource->dsize-1)/f->msource->dsize;

	didread = 0;
	while(dee->i >= dee->n){
		if(dee->boff >= nb){
			ret = 0;
			goto Return;
		}
		didread = 1;
		if(!deeFill(dee)){
			ret = -1;
			goto Return;
		}
	}

	memmove(de, dee->buf + dee->i, sizeof(DirEntry));
	dee->i++;
	ret = 1;

Return:
	sourceUnlock(f->source);
	sourceUnlock(f->msource);
	fileRUnlock(f);

	if(didread)
		fileRAccess(f);
	return ret;
}
Exemplo n.º 5
0
int
fileRemove(File *f, char *uid)
{
	File *ff;

	/* can not remove the root */
	if(fileIsRoot(f)){
		vtSetError(ERoot);
		return 0;
	}

	if(!fileLock(f))
		return 0;

	if(f->source->mode != OReadWrite){
		vtSetError(EReadOnly);
		goto Err1;
	}
	if(!sourceLock2(f->source, f->msource, -1))
		goto Err1;
	if(fileIsDir(f) && !fileCheckEmpty(f))
		goto Err;

	for(ff=f->down; ff; ff=ff->next)
		assert(ff->removed);

	sourceRemove(f->source);
	f->source->file = nil;		/* erase back pointer */
	f->source = nil;
	if(f->msource){
		sourceRemove(f->msource);
		f->msource = nil;
	}

	fileUnlock(f);

	if(!fileMetaRemove(f, uid))
		return 0;

	return 1;

Err:
	sourceUnlock(f->source);
	if(f->msource)
		sourceUnlock(f->msource);
Err1:
	fileUnlock(f);
	return 0;
}
Exemplo n.º 6
0
/*
 * Walk down to the block(s) containing the Entries
 * for f->source and f->msource, copying as we go.
 */
int
fileWalkSources(File *f)
{
	if(f->mode == OReadOnly){
		fprint(2, "readonly in fileWalkSources\n");
		return 1;
	}
	if(!sourceLock2(f->source, f->msource, OReadWrite)){
		fprint(2, "sourceLock2 failed in fileWalkSources\n");
		return 0;
	}
	sourceUnlock(f->source);
	sourceUnlock(f->msource);
	return 1;
}
Exemplo n.º 7
0
static Source *
fileOpenSource(File *f, u32int offset, u32int gen, int dir, uint mode,
	int issnapshot)
{
	char *rname, *fname;
	Source *r;

	if(!sourceLock(f->source, mode))
		return nil;
	r = sourceOpen(f->source, offset, mode, issnapshot);
	sourceUnlock(f->source);
	if(r == nil)
		return nil;
	if(r->gen != gen){
		vtSetError(ERemoved);
		goto Err;
	}
	if(r->dir != dir && r->mode != -1){
		/* this hasn't been as useful as we hoped it would be. */
		rname = sourceName(r);
		fname = fileName(f);
		consPrint("%s: source %s for file %s: fileOpenSource: "
			"dir mismatch %d %d\n",
			f->source->fs->name, rname, fname, r->dir, dir);
		free(rname);
		free(fname);

		vtSetError(EBadMeta);
		goto Err;
	}
	return r;
Err:
	sourceClose(r);
	return nil;
}
Exemplo n.º 8
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;
}
Exemplo n.º 9
0
Arquivo: source.c Projeto: npe9/harvey
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;
}
Exemplo n.º 10
0
static void
checkDirs(Fsck *chk)
{
	Source *r, *mr;

	sourceLock(chk->fs->source, OReadOnly);
	r = sourceOpen(chk->fs->source, 0, OReadOnly, 0);
	mr = sourceOpen(chk->fs->source, 1, OReadOnly, 0);
	sourceUnlock(chk->fs->source);
	chkDir(chk, "", r, mr);

	sourceClose(r);
	sourceClose(mr);
}
Exemplo n.º 11
0
int
fileGetSize(File *f, uvlong *size)
{
	if(!fileRLock(f))
		return 0;
	if(!sourceLock(f->source, OReadOnly)){
		fileRUnlock(f);
		return 0;
	}
	*size = sourceGetSize(f->source);
	sourceUnlock(f->source);
	fileRUnlock(f);

	return 1;
}
Exemplo n.º 12
0
int
fileGetDir(File *f, DirEntry *dir)
{
	if(!fileRLock(f))
		return 0;

	fileMetaLock(f);
	deCopy(dir, &f->dir);
	fileMetaUnlock(f);

	if(!fileIsDir(f)){
		if(!sourceLock(f->source, OReadOnly)){
			fileRUnlock(f);
			return 0;
		}
		dir->size = sourceGetSize(f->source);
		sourceUnlock(f->source);
	}
	fileRUnlock(f);

	return 1;
}
Exemplo n.º 13
0
int
fileSetSize(File *f, uvlong size)
{
	int r;

	if(!fileLock(f))
		return 0;
	r = 0;
	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;
	r = sourceSetSize(f->source, size);
	sourceUnlock(f->source);
Err:
	fileUnlock(f);
	return r;
}
Exemplo n.º 14
0
int
fileSetDir(File *f, DirEntry *dir, char *uid)
{
	File *ff;
	char *oelem;
	u32int mask;
	u64int size;

	/* can not set permissions for the root */
	if(fileIsRoot(f)){
		vtSetError(ERoot);
		return 0;
	}

	if(!fileLock(f))
		return 0;

	if(f->source->mode != OReadWrite){
		vtSetError(EReadOnly);
		fileUnlock(f);
		return 0;
	}

	fileMetaLock(f);

	/* check new name does not already exist */
	if(strcmp(f->dir.elem, dir->elem) != 0){
		for(ff = f->up->down; ff; ff=ff->next){
			if(strcmp(dir->elem, ff->dir.elem) == 0 && !ff->removed){
				vtSetError(EExists);
				goto Err;
			}
		}

		ff = dirLookup(f->up, dir->elem);
		if(ff != nil){
			fileDecRef(ff);
			vtSetError(EExists);
			goto Err;
		}
	}

	if(!sourceLock2(f->source, f->msource, -1))
		goto Err;
	if(!fileIsDir(f)){
		size = sourceGetSize(f->source);
		if(size != dir->size){
			if(!sourceSetSize(f->source, dir->size)){
				sourceUnlock(f->source);
				if(f->msource)
					sourceUnlock(f->msource);
				goto Err;
			}
			/* commited to changing it now */
		}
	}
	/* commited to changing it now */
	if((f->dir.mode&ModeTemporary) != (dir->mode&ModeTemporary))
		fileSetTmp(f, dir->mode&ModeTemporary);
	sourceUnlock(f->source);
	if(f->msource)
		sourceUnlock(f->msource);

	oelem = nil;
	if(strcmp(f->dir.elem, dir->elem) != 0){
		oelem = f->dir.elem;
		f->dir.elem = vtStrDup(dir->elem);
	}

	if(strcmp(f->dir.uid, dir->uid) != 0){
		vtMemFree(f->dir.uid);
		f->dir.uid = vtStrDup(dir->uid);
	}

	if(strcmp(f->dir.gid, dir->gid) != 0){
		vtMemFree(f->dir.gid);
		f->dir.gid = vtStrDup(dir->gid);
	}

	f->dir.mtime = dir->mtime;
	f->dir.atime = dir->atime;

//fprint(2, "mode %x %x ", f->dir.mode, dir->mode);
	mask = ~(ModeDir|ModeSnapshot);
	f->dir.mode &= ~mask;
	f->dir.mode |= mask & dir->mode;
	f->dirty = 1;
//fprint(2, "->%x\n", f->dir.mode);

	fileMetaFlush2(f, oelem);
	vtMemFree(oelem);

	fileMetaUnlock(f);
	fileUnlock(f);

	fileWAccess(f->up, uid);

	return 1;
Err:
	fileMetaUnlock(f);
	fileUnlock(f);
	return 0;
}
Exemplo n.º 15
0
/*
 * Walk the source tree making sure that the BtData
 * sources containing directory entries are okay.
 */
static void
chkDir(Fsck *chk, char *name, Source *source, Source *meta)
{
	int i;
	u32int a1, a2, nb, o;
	char *s, *nn;
	uchar *bm;
	Block *b, *bb;
	DirEntry de;
	Entry e1, e2;
	MetaBlock mb;
	MetaEntry me;
	Source *r, *mr;

	if(!chk->useventi && globalToLocal(source->score)==NilBlock &&
	    globalToLocal(meta->score)==NilBlock)
		return;

	if(!sourceLock2(source, meta, OReadOnly)){
		warn(chk, "could not lock sources for %s: %R", name);
		return;
	}
	if(!sourceGetEntry(source, &e1) || !sourceGetEntry(meta, &e2)){
		warn(chk, "could not load entries for %s: %R", name);
		return;
	}
	a1 = globalToLocal(e1.score);
	a2 = globalToLocal(e2.score);
	if((!chk->useventi && a1==NilBlock && a2==NilBlock)
	|| (getBit(chk->smap, a1) && getBit(chk->smap, a2))){
		sourceUnlock(source);
		sourceUnlock(meta);
		return;
	}
	setBit(chk->smap, a1);
	setBit(chk->smap, a2);

	bm = vtMemAllocZ(sourceGetDirSize(source)/8 + 1);

	nb = (sourceGetSize(meta) + meta->dsize - 1)/meta->dsize;
	for(o = 0; o < nb; o++){
		b = sourceBlock(meta, o, OReadOnly);
		if(b == nil){
			error(chk, "could not read block in meta file: %s[%ud]: %R",
				name, o);
			continue;
		}
if(0)		fprint(2, "source %V:%d block %d addr %d\n", source->score,
			source->offset, o, b->addr);
		if(b->addr != NilBlock && getBit(chk->errmap, b->addr))
			warn(chk, "previously reported error in block %ux is in %s",
				b->addr, name);

		if(!mbUnpack(&mb, b->data, meta->dsize)){
			error(chk, "could not unpack meta block: %s[%ud]: %R",
				name, o);
			blockPut(b);
			continue;
		}
		if(!chkMetaBlock(&mb)){
			error(chk, "bad meta block: %s[%ud]: %R", name, o);
			blockPut(b);
			continue;
		}
		s = nil;
		for(i=mb.nindex-1; i>=0; i--){
			meUnpack(&me, &mb, i);
			if(!deUnpack(&de, &me)){
				error(chk,
				  "could not unpack dir entry: %s[%ud][%d]: %R",
					name, o, i);
				continue;
			}
			if(s && strcmp(s, de.elem) <= 0)
				error(chk,
			   "dir entry out of order: %s[%ud][%d] = %s last = %s",
					name, o, i, de.elem, s);
			vtMemFree(s);
			s = vtStrDup(de.elem);
			nn = smprint("%s/%s", name, de.elem);
			if(nn == nil){
				error(chk, "out of memory");
				continue;
			}
			if(chk->printdirs)
				if(de.mode&ModeDir)
					chk->print("%s/\n", nn);
			if(chk->printfiles)
				if(!(de.mode&ModeDir))
					chk->print("%s\n", nn);
			if(!(de.mode & ModeDir)){
				r = openSource(chk, source, nn, bm, de.entry,
					de.gen, 0, &mb, i, b);
				if(r != nil){
					if(sourceLock(r, OReadOnly)){
						scanSource(chk, nn, r);
						sourceUnlock(r);
					}
					sourceClose(r);
				}
				deCleanup(&de);
				free(nn);
				continue;
			}

			r = openSource(chk, source, nn, bm, de.entry,
				de.gen, 1, &mb, i, b);
			if(r == nil){
				deCleanup(&de);
				free(nn);
				continue;
			}

			mr = openSource(chk, source, nn, bm, de.mentry,
				de.mgen, 0, &mb, i, b);
			if(mr == nil){
				sourceClose(r);
				deCleanup(&de);
				free(nn);
				continue;
			}

			if(!(de.mode&ModeSnapshot) || chk->walksnapshots)
				chkDir(chk, nn, r, mr);

			sourceClose(mr);
			sourceClose(r);
			deCleanup(&de);
			free(nn);
			deCleanup(&de);

		}
		vtMemFree(s);
		blockPut(b);
	}

	nb = sourceGetDirSize(source);
	for(o=0; o<nb; o++){
		if(getBit(bm, o))
			continue;
		r = sourceOpen(source, o, OReadOnly, 0);
		if(r == nil)
			continue;
		warn(chk, "non referenced entry in source %s[%d]", name, o);
		if((bb = sourceBlock(source, o/(source->dsize/VtEntrySize),
		    OReadOnly)) != nil){
			if(bb->addr != NilBlock){
				setBit(chk->errmap, bb->addr);
				chk->clre(chk, bb, o%(source->dsize/VtEntrySize));
				chk->nclre++;
			}
			blockPut(bb);
		}
		sourceClose(r);
	}

	sourceUnlock(source);
	sourceUnlock(meta);
	vtMemFree(bm);
}
Exemplo n.º 16
0
int
fileWrite(File *f, void *buf, int cnt, vlong offset, char *uid)
{
	Source *s;
	ulong bn;
	int off, dsize, n;
	Block *b;
	uchar *p;
	vlong eof;

if(0)fprint(2, "fileWrite: %s %d, %lld\n", f->dir.elem, cnt, offset);

	if(!fileLock(f))
		return -1;

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

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

	fileWAccess(f, uid);

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

	eof = sourceGetSize(s);
	if(f->dir.mode & ModeAppend)
		offset = eof;
	bn = offset/dsize;
	off = offset%dsize;
	p = buf;
	while(cnt > 0){
		n = cnt;
		if(n > dsize-off)
			n = dsize-off;
		b = sourceBlock(s, bn, n<dsize?OReadWrite:OOverWrite);
		if(b == nil){
			if(offset > eof)
				sourceSetSize(s, offset);
			goto Err;
		}
		memmove(b->data+off, p, n);
		off = 0;
		cnt -= n;
		p += n;
		offset += n;
		bn++;
		blockDirty(b);
		blockPut(b);
	}
	if(offset > eof && !sourceSetSize(s, offset))
		goto Err;
	sourceUnlock(s);
	fileUnlock(f);
	return p-(uchar*)buf;
Err:
	if(s)
		sourceUnlock(s);
	fileUnlock(f);
	return -1;
}
Exemplo n.º 17
0
int
fileRead(File *f, void *buf, int cnt, vlong offset)
{
	Source *s;
	uvlong size;
	u32int bn;
	int off, dsize, n, nn;
	Block *b;
	uchar *p;

if(0)fprint(2, "fileRead: %s %d, %lld\n", f->dir.elem, cnt, offset);

	if(!fileRLock(f))
		return -1;

	if(offset < 0){
		vtSetError(EBadOffset);
		goto Err1;
	}

	fileRAccess(f);

	if(!sourceLock(f->source, OReadOnly))
		goto Err1;

	s = f->source;
	dsize = s->dsize;
	size = sourceGetSize(s);

	if(offset >= size)
		offset = size;

	if(cnt > size-offset)
		cnt = size-offset;
	bn = offset/dsize;
	off = offset%dsize;
	p = buf;
	while(cnt > 0){
		b = sourceBlock(s, bn, OReadOnly);
		if(b == nil)
			goto Err;
		n = cnt;
		if(n > dsize-off)
			n = dsize-off;
		nn = dsize-off;
		if(nn > n)
			nn = n;
		memmove(p, b->data+off, nn);
		memset(p+nn, 0, nn-n);
		off = 0;
		bn++;
		cnt -= n;
		p += n;
		blockPut(b);
	}
	sourceUnlock(s);
	fileRUnlock(f);
	return p-(uchar*)buf;

Err:
	sourceUnlock(s);
Err1:
	fileRUnlock(f);
	return -1;
}
Exemplo n.º 18
0
File *
fileCreate(File *f, char *elem, ulong mode, char *uid)
{
	File *ff;
	DirEntry *dir;
	Source *pr, *r, *mr;
	int isdir;

	if(!fileLock(f))
		return nil;

	r = nil;
	mr = nil;
	for(ff = f->down; ff; ff=ff->next){
		if(strcmp(elem, ff->dir.elem) == 0 && !ff->removed){
			ff = nil;
			vtSetError(EExists);
			goto Err1;
		}
	}

	ff = dirLookup(f, elem);
	if(ff != nil){
		vtSetError(EExists);
		goto Err1;
	}

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

	if(!sourceLock2(f->source, f->msource, -1))
		goto Err1;

	ff = fileAlloc(f->fs);
	isdir = mode & ModeDir;

	r = sourceCreate(pr, pr->dsize, isdir, 0);
	if(r == nil)
		goto Err;
	if(isdir){
		mr = sourceCreate(pr, pr->dsize, 0, r->offset);
		if(mr == nil)
			goto Err;
	}

	dir = &ff->dir;
	dir->elem = vtStrDup(elem);
	dir->entry = r->offset;
	dir->gen = r->gen;
	if(isdir){
		dir->mentry = mr->offset;
		dir->mgen = mr->gen;
	}
	dir->size = 0;
	if(!fsNextQid(f->fs, &dir->qid))
		goto Err;
	dir->uid = vtStrDup(uid);
	dir->gid = vtStrDup(f->dir.gid);
	dir->mid = vtStrDup(uid);
	dir->mtime = time(0L);
	dir->mcount = 0;
	dir->ctime = dir->mtime;
	dir->atime = dir->mtime;
	dir->mode = mode;

	ff->boff = fileMetaAlloc(f, dir, 0);
	if(ff->boff == NilBlock)
		goto Err;

	sourceUnlock(f->source);
	sourceUnlock(f->msource);

	ff->source = r;
	r->file = ff;			/* point back */
	ff->msource = mr;

	if(mode&ModeTemporary){
		if(!sourceLock2(r, mr, -1))
			goto Err1;
		fileSetTmp(ff, 1);
		sourceUnlock(r);
		if(mr)
			sourceUnlock(mr);
	}

	/* committed */

	/* link in and up parent ref count */
	ff->next = f->down;
	f->down = ff;
	ff->up = f;
	fileIncRef(f);

	fileWAccess(f, uid);

	fileUnlock(f);
	return ff;

Err:
	sourceUnlock(f->source);
	sourceUnlock(f->msource);
Err1:
	if(r){
		sourceLock(r, -1);
		sourceRemove(r);
	}
	if(mr){
		sourceLock(mr, -1);
		sourceRemove(mr);
	}
	if(ff)
		fileDecRef(ff);
	fileUnlock(f);
	return 0;
}
Exemplo n.º 19
0
Arquivo: source.c Projeto: npe9/harvey
/*
 * 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 sources (OReadWrite) and sources for the
 * snapshot file system (OReadOnly).
 */
static Block*
sourceLoadBlock(Source *r, int mode)
{
    uint32_t addr;
    Block *b;

    switch(r->mode) {
    default:
        assert(0);
    case OReadWrite:
        assert(r->mode == OReadWrite);
        /*
         * This needn't be true -- we might bump the low epoch
         * to reclaim some old blocks, but since this score is
         * OReadWrite, the blocks must all still be open, so none
         * are reclaimed.  Thus it's okay that the epoch is so low.
         * Proceed.
        assert(r->epoch >= r->fs->elo);
         */
        if(r->epoch == r->fs->ehi) {
            b = cacheGlobal(r->fs->cache, r->score, BtDir, r->tag, OReadWrite);
            if(b == nil)
                return nil;
            assert(r->epoch == b->l.epoch);
            return b;
        }
        assert(r->parent != nil);
        if(!sourceLock(r->parent, OReadWrite))
            return nil;
        b = sourceBlock(r->parent, r->offset/r->epb, OReadWrite);
        sourceUnlock(r->parent);
        if(b == nil)
            return nil;
        assert(b->l.epoch == r->fs->ehi);
        //	fprint(2, "sourceLoadBlock %p %V => %V\n", r, r->score, b->score);
        memmove(r->score, b->score, VtScoreSize);
        r->scoreEpoch = b->l.epoch;
        r->tag = b->l.tag;
        r->epoch = r->fs->ehi;
        return b;

    case OReadOnly:
        addr = globalToLocal(r->score);
        if(addr == NilBlock)
            return cacheGlobal(r->fs->cache, r->score, BtDir, r->tag, mode);

        b = cacheLocalData(r->fs->cache, addr, BtDir, r->tag, mode, r->scoreEpoch);
        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 OReadWrite case
         * above because blocks in the current epoch don't get
         * reclaimed.  The fact that we're OReadOnly means we're
         * a snapshot.  (Or else the file system is read-only, but then
         * the archiver isn't going around deleting blocks.)
         */
        if(strcmp(vtGetError(), ELabelMismatch) == 0) {
            if(!sourceLock(r->parent, OReadOnly))
                return nil;
            b = sourceBlock(r->parent, r->offset/r->epb, OReadOnly);
            sourceUnlock(r->parent);
            if(b) {
                fprint(2, "sourceAlloc: lost %V found %V\n",
                       r->score, b->score);
                memmove(r->score, b->score, VtScoreSize);
                r->scoreEpoch = b->l.epoch;
                return b;
            }
        }
        return nil;
    }
}
Exemplo n.º 20
0
/* assumes metaLock is held */
static int
fileMetaFlush2(File *f, char *oelem)
{
	File *fp;
	Block *b, *bb;
	MetaBlock mb;
	MetaEntry me, me2;
	int i, n;
	u32int boff;

	if(!f->dirty)
		return 0;

	if(oelem == nil)
		oelem = f->dir.elem;

//print("fileMetaFlush %s->%s\n", oelem, f->dir.elem);

	fp = f->up;

	if(!sourceLock(fp->msource, -1))
		return -1;
	/* can happen if source is clri'ed out from under us */
	if(f->boff == NilBlock)
		goto Err1;
	b = sourceBlock(fp->msource, f->boff, OReadWrite);
	if(b == nil)
		goto Err1;

	if(!mbUnpack(&mb, b->data, fp->msource->dsize))
		goto Err;
	if(!mbSearch(&mb, oelem, &i, &me))
		goto Err;

	n = deSize(&f->dir);
if(0)fprint(2, "old size %d new size %d\n", me.size, n);

	if(mbResize(&mb, &me, n)){
		/* fits in the block */
		mbDelete(&mb, i);
		if(strcmp(f->dir.elem, oelem) != 0)
			mbSearch(&mb, f->dir.elem, &i, &me2);
		dePack(&f->dir, &me);
		mbInsert(&mb, i, &me);
		mbPack(&mb);
		blockDirty(b);
		blockPut(b);
		sourceUnlock(fp->msource);
		f->dirty = 0;

		return 1;
	}

	/*
	 * moving entry to another block
	 * it is feasible for the fs to crash leaving two copies
	 * of the directory entry.  This is just too much work to
	 * fix.  Given that entries are only allocated in a block that
	 * is less than PercentageFull, most modifications of meta data
	 * will fit within the block.  i.e. this code should almost
	 * never be executed.
	 */
	boff = fileMetaAlloc(fp, &f->dir, f->boff+1);
	if(boff == NilBlock){
		/* mbResize might have modified block */
		mbPack(&mb);
		blockDirty(b);
		goto Err;
	}
fprint(2, "fileMetaFlush moving entry from %ud -> %ud\n", f->boff, boff);
	f->boff = boff;

	/* make sure deletion goes to disk after new entry */
	bb = sourceBlock(fp->msource, f->boff, OReadWrite);
	mbDelete(&mb, i);
	mbPack(&mb);
	blockDependency(b, bb, -1, nil, nil);
	blockPut(bb);
	blockDirty(b);
	blockPut(b);
	sourceUnlock(fp->msource);

	f->dirty = 0;

	return 1;

Err:
	blockPut(b);
Err1:
	sourceUnlock(fp->msource);
	return -1;
}
Exemplo n.º 21
0
File *
fileRoot(Source *r)
{
	Block *b;
	Source *r0, *r1, *r2;
	MetaBlock mb;
	MetaEntry me;
	File *root, *mr;
	Fs *fs;

	b = nil;
	root = nil;
	mr = nil;
	r1 = nil;
	r2 = nil;

	fs = r->fs;
	if(!sourceLock(r, -1))
		return nil;
	r0 = sourceOpen(r, 0, fs->mode, 0);
	if(r0 == nil)
		goto Err;
	r1 = sourceOpen(r, 1, fs->mode, 0);
	if(r1 == nil)
		goto Err;
	r2 = sourceOpen(r, 2, fs->mode, 0);
	if(r2 == nil)
		goto Err;

	mr = fileAlloc(fs);
	mr->msource = r2;
	r2 = nil;

	root = fileAlloc(fs);
	root->boff = 0;
	root->up = mr;
	root->source = r0;
	r0->file = root;			/* point back to source */
	r0 = nil;
	root->msource = r1;
	r1 = nil;

	mr->down = root;

	if(!sourceLock(mr->msource, -1))
		goto Err;
	b = sourceBlock(mr->msource, 0, OReadOnly);
	sourceUnlock(mr->msource);
	if(b == nil)
		goto Err;

	if(!mbUnpack(&mb, b->data, mr->msource->dsize))
		goto Err;

	meUnpack(&me, &mb, 0);
	if(!deUnpack(&root->dir, &me))
		goto Err;
	blockPut(b);
	sourceUnlock(r);
	fileRAccess(root);

	return root;
Err:
	blockPut(b);
	if(r0)
		sourceClose(r0);
	if(r1)
		sourceClose(r1);
	if(r2)
		sourceClose(r2);
	if(mr)
		fileFree(mr);
	if(root)
		fileFree(root);
	sourceUnlock(r);

	return nil;
}