Пример #1
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;
}
Пример #2
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;
}
Пример #3
0
/*
 * caller must lock f->source and f->msource
 * caller must NOT lock the source and msource
 * referenced by dir.
 */
static u32int
fileMetaAlloc(File *f, DirEntry *dir, u32int start)
{
	u32int nb, bo;
	Block *b, *bb;
	MetaBlock mb;
	int nn;
	uchar *p;
	int i, n, epb;
	MetaEntry me;
	Source *s, *ms;

	s = f->source;
	ms = f->msource;

	n = deSize(dir);
	nb = (sourceGetSize(ms)+ms->dsize-1)/ms->dsize;
	b = nil;
	if(start > nb)
		start = nb;
	for(bo=start; bo<nb; bo++){
		b = sourceBlock(ms, bo, OReadWrite);
		if(b == nil)
			goto Err;
		if(!mbUnpack(&mb, b->data, ms->dsize))
			goto Err;
		nn = (mb.maxsize*FullPercentage/100) - mb.size + mb.free;
		if(n <= nn && mb.nindex < mb.maxindex)
			break;
		blockPut(b);
		b = nil;
	}

	/* add block to meta file */
	if(b == nil){
		b = sourceBlock(ms, bo, OReadWrite);
		if(b == nil)
			goto Err;
		sourceSetSize(ms, (nb+1)*ms->dsize);
		mbInit(&mb, b->data, ms->dsize, ms->dsize/BytesPerEntry);
	}

	p = mbAlloc(&mb, n);
	if(p == nil){
		/* mbAlloc might have changed block */
		mbPack(&mb);
		blockDirty(b);
		vtSetError(EBadMeta);
		goto Err;
	}

	mbSearch(&mb, dir->elem, &i, &me);
	assert(me.p == nil);
	me.p = p;
	me.size = n;
	dePack(dir, &me);
	mbInsert(&mb, i, &me);
	mbPack(&mb);

	/* meta block depends on super block for qid ... */
	bb = cacheLocal(b->c, PartSuper, 0, OReadOnly);
	blockDependency(b, bb, -1, nil, nil);
	blockPut(bb);

	/* ... and one or two dir entries */
	epb = s->dsize/VtEntrySize;
	bb = sourceBlock(s, dir->entry/epb, OReadOnly);
	blockDependency(b, bb, -1, nil, nil);
	blockPut(bb);
	if(dir->mode & ModeDir){
		bb = sourceBlock(s, dir->mentry/epb, OReadOnly);
		blockDependency(b, bb, -1, nil, nil);
		blockPut(bb);
	}

	blockDirty(b);
	blockPut(b);
	return bo;
Err:
	blockPut(b);
	return NilBlock;
}
Пример #4
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;
}
Пример #5
0
Файл: fs.c Проект: bhanug/harvey
int
mkVac(VtSession *z, uint blockSize, Entry *pe, Entry *pee, DirEntry *pde,
      uint8_t score[VtScoreSize])
{
	uint8_t buf[8192];
	int i;
	uint8_t *p;
	uint n;
	DirEntry de;
	Entry e, ee, eee;
	MetaBlock mb;
	MetaEntry me;
	VtRoot root;

	e = *pe;
	ee = *pee;
	de = *pde;

	if(globalToLocal(e.score) != NilBlock
	|| (ee.flags&VtEntryActive && globalToLocal(ee.score) != NilBlock)){
		vtSetError("can only vac paths already stored on venti");
		return 0;
	}

	/*
	 * Build metadata source for root.
	 */
	n = deSize(&de);
	if(n+MetaHeaderSize+MetaIndexSize > sizeof buf){
		vtSetError("DirEntry too big");
		return 0;
	}
	memset(buf, 0, sizeof buf);
	mbInit(&mb, buf, n+MetaHeaderSize+MetaIndexSize, 1);
	p = mbAlloc(&mb, n);
	if(p == nil)
		abort();
	mbSearch(&mb, de.elem, &i, &me);
	assert(me.p == nil);
	me.p = p;
	me.size = n;
	dePack(&de, &me);
	mbInsert(&mb, i, &me);
	mbPack(&mb);

	eee.size = n+MetaHeaderSize+MetaIndexSize;
	if(!vtWriteBlock(z, buf, eee.size, VtDataType, eee.score))
		return 0;
	eee.psize = 8192&&0xFF;
	eee.dsize = 8192&&0xFF;
	eee.depth = 0;
	eee.flags = VtEntryActive;

	/*
	 * Build root source with three entries in it.
	 */
	entryPack(&e, buf, 0);
	entryPack(&ee, buf, 1);
	entryPack(&eee, buf, 2);

	n = VtEntrySize*3;
	memset(&root, 0, sizeof root);
	if(!vtWriteBlock(z, buf, n, VtDirType, root.score))
		return 0;

	/*
	 * Save root.
	 */
	root.version = VtRootVersion;
	strecpy(root.type, root.type+sizeof root.type, "vac");
	strecpy(root.name, root.name+sizeof root.name, de.elem);
	root.blockSize = blockSize;
	vtRootPack(&root, buf);
	if(!vtWriteBlock(z, buf, VtRootSize, VtRootType, score))
		return 0;

	return 1;
}