示例#1
0
文件: fs.c 项目: bhanug/harvey
Fs *
fsOpen(char *file, VtSession *z, int32_t ncache, int mode)
{
	int fd, m;
	uint8_t oscore[VtScoreSize];
	Block *b, *bs;
	Disk *disk;
	Fs *fs;
	Super super;

	switch(mode){
	default:
		vtSetError(EBadMode);
		return nil;
	case OReadOnly:
		m = OREAD;
		break;
	case OReadWrite:
		m = ORDWR;
		break;
	}
	fd = open(file, m);
	if(fd < 0){
		vtSetError("open %s: %r", file);
		return nil;
	}

	bwatchInit();
	disk = diskAlloc(fd);
	if(disk == nil){
		vtSetError("diskAlloc: %R");
		close(fd);
		return nil;
	}

	fs = vtMemAllocZ(sizeof(Fs));
	fs->mode = mode;
	fs->name = vtStrDup(file);
	fs->blockSize = diskBlockSize(disk);
	fs->elk = vtLockAlloc();
	fs->cache = cacheAlloc(disk, z, ncache, mode);
	if(mode == OReadWrite && z)
		fs->arch = archInit(fs->cache, disk, fs, z);
	fs->z = z;

	b = cacheLocal(fs->cache, PartSuper, 0, mode);
	if(b == nil)
		goto Err;
	if(!superUnpack(&super, b->data)){
		blockPut(b);
		vtSetError("bad super block");
		goto Err;
	}
	blockPut(b);

	fs->ehi = super.epochHigh;
	fs->elo = super.epochLow;

//fprint(2, "%s: fs->ehi %d fs->elo %d active=%d\n", argv0, fs->ehi, fs->elo, super.active);

	fs->source = sourceRoot(fs, super.active, mode);
	if(fs->source == nil){
		/*
		 * Perhaps it failed because the block is copy-on-write.
		 * Do the copy and try again.
		 */
		if(mode == OReadOnly || strcmp(vtGetError(), EBadRoot) != 0)
			goto Err;
		b = cacheLocalData(fs->cache, super.active, BtDir, RootTag,
			OReadWrite, 0);
		if(b == nil){
			vtSetError("cacheLocalData: %R");
			goto Err;
		}
		if(b->l.epoch == fs->ehi){
			blockPut(b);
			vtSetError("bad root source block");
			goto Err;
		}
		b = blockCopy(b, RootTag, fs->ehi, fs->elo);
		if(b == nil)
			goto Err;
		localToGlobal(super.active, oscore);
		super.active = b->addr;
		bs = cacheLocal(fs->cache, PartSuper, 0, OReadWrite);
		if(bs == nil){
			blockPut(b);
			vtSetError("cacheLocal: %R");
			goto Err;
		}
		superPack(&super, bs->data);
		blockDependency(bs, b, 0, oscore, nil);
		blockPut(b);
		blockDirty(bs);
		blockRemoveLink(bs, globalToLocal(oscore), BtDir, RootTag, 0);
		blockPut(bs);
		fs->source = sourceRoot(fs, super.active, mode);
		if(fs->source == nil){
			vtSetError("sourceRoot: %R");
			goto Err;
		}
	}

//fprint(2, "%s: got fs source\n", argv0);

	vtRLock(fs->elk);
	fs->file = fileRoot(fs->source);
	fs->source->file = fs->file;		/* point back */
	vtRUnlock(fs->elk);
	if(fs->file == nil){
		vtSetError("fileRoot: %R");
		goto Err;
	}

//fprint(2, "%s: got file root\n", argv0);

	if(mode == OReadWrite){
		fs->metaFlush = periodicAlloc(fsMetaFlush, fs, 1000);
		fs->snap = snapInit(fs);
	}
	return fs;

Err:
fprint(2, "%s: fsOpen error\n", argv0);
	fsClose(fs);
	return nil;
}
示例#2
0
void
main(int argc, char *argv[])
{
	int fd, force;
	Header h;
	ulong bn;
	Entry e;
	char *label = "vfs";
	char *host = nil;
	char *score = nil;
	u32int root;
	Dir *d;

	force = 0;
	ARGBEGIN{
	default:
		usage();
	case 'b':
		bsize = unittoull(EARGF(usage()));
		if(bsize == ~0)
			usage();
		break;
	case 'h':
		host = EARGF(usage());
		break;
	case 'i':
		iso9660file = EARGF(usage());
		iso9660off = atoi(EARGF(usage()));
		break;
	case 'l':
		label = EARGF(usage());
		break;
	case 'v':
		score = EARGF(usage());
		break;

	/*
	 * This is -y instead of -f because flchk has a
	 * (frequently used) -f option.  I type flfmt instead
	 * of flchk all the time, and want to make it hard
	 * to reformat my file system accidentally.
	 */
	case 'y':
		force = 1;
		break;
	}ARGEND

	if(argc != 1)
		usage();

	if(iso9660file && score)
		vtFatal("cannot use -i with -v");

	vtAttach();

	fmtinstall('V', scoreFmt);
	fmtinstall('R', vtErrFmt);
	fmtinstall('L', labelFmt);

	fd = open(argv[0], ORDWR);
	if(fd < 0)
		vtFatal("could not open file: %s: %r", argv[0]);

	buf = vtMemAllocZ(bsize);
	if(pread(fd, buf, bsize, HeaderOffset) != bsize)
		vtFatal("could not read fs header block: %r");

	if(headerUnpack(&h, buf) && !force
	&& !confirm("fs header block already exists; are you sure?"))
		goto Out;

	if((d = dirfstat(fd)) == nil)
		vtFatal("dirfstat: %r");

	if(d->type == 'M' && !force
	&& !confirm("fs file is mounted via devmnt (is not a kernel device); are you sure?"))
		goto Out;

	partition(fd, bsize, &h);
	headerPack(&h, buf);
	if(pwrite(fd, buf, bsize, HeaderOffset) < bsize)
		vtFatal("could not write fs header: %r");

	disk = diskAlloc(fd);
	if(disk == nil)
		vtFatal("could not open disk: %r");

	if(iso9660file)
		iso9660init(fd, &h, iso9660file, iso9660off);

	/* zero labels */
	memset(buf, 0, bsize);
	for(bn = 0; bn < diskSize(disk, PartLabel); bn++)
		blockWrite(PartLabel, bn);

	if(iso9660file)
		iso9660labels(disk, buf, blockWrite);

	if(score)
		root = ventiRoot(host, score);
	else{
		rootMetaInit(&e);
		root = rootInit(&e);
	}

	superInit(label, root, vtZeroScore);
	diskFree(disk);

	if(score == nil)
		topLevel(argv[0]);

Out:
	vtDetach();
	exits(0);
}