183 lines · 3.4 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include "all.h" enum{	MAXWREN = 7,}; #define WMAGIC	"kfs wren device\n" typedef struct Wren	Wren; struct Wren{	QLock;	Device	dev;	uvlong	size;	int	fd;}; static Wren	*wrens;static int	maxwren;char		*wrenfile;int		nwren;int		badmagic; static Wren *wren(Device dev){	int i; 	for(i = 0; i < maxwren; i++)		if(devcmp(dev, wrens[i].dev) == 0)			return &wrens[i];	panic("can't find wren for %D", dev);	return 0;} voidwreninit(Device dev){	char buf[MAXBUFSIZE];	Wren *w;	Dir *d;	int fd, i; 	if(wrens == 0)		wrens = ialloc(MAXWREN * sizeof *wrens);	w = &wrens[maxwren];	fd = open(wrenfile, ORDWR);	if(fd < 0)		panic("can't open %s", wrenfile);	if((d = dirfstat(fd)) == nil)		panic("can't stat %s\n", wrenfile);	seek(fd, 0, 0);	i = read(fd, buf, sizeof buf);	if(i < sizeof buf)		panic("can't read %s", wrenfile);	badmagic = 0;	RBUFSIZE = 1024;	if(strncmp(buf+256, WMAGIC, strlen(WMAGIC)) == 0){		RBUFSIZE = atol(buf+256+strlen(WMAGIC));		if(RBUFSIZE % 512){			fprint(2, "kfs: bad buffersize(%d): assuming 1k blocks\n", RBUFSIZE);			RBUFSIZE = 1024;		}	}else		badmagic = 1;	w->dev = dev;	w->size = d->length;	free(d);	w->fd = fd;	maxwren++;} voidwrenream(Device dev){	Wren *w;	char buf[MAXBUFSIZE];	int fd, i; 	if(RBUFSIZE % 512)		panic("kfs: bad buffersize(%d): restart a multiple of 512\n", RBUFSIZE);	if(RBUFSIZE > sizeof(buf))		panic("kfs: bad buffersize(%d): must be at most %d\n", RBUFSIZE, sizeof(buf)); 	print("kfs: reaming the file system using %d byte blocks\n", RBUFSIZE);	w = wren(dev);	fd = w->fd;	memset(buf, 0, sizeof buf);	sprint(buf+256, "%s%d\n", WMAGIC, RBUFSIZE);	qlock(w);	i = seek(fd, 0, 0) < 0 || write(fd, buf, RBUFSIZE) != RBUFSIZE;	qunlock(w);	if(i < 0)		panic("can't ream disk");} intwrentag(char *p, int tag, long qpath){	Tag *t; 	t = (Tag*)(p+BUFSIZE);	return t->tag != tag || (qpath&~QPDIR) != t->path;} intwrencheck(Device dev){	char buf[MAXBUFSIZE]; 	if(badmagic)		return 1;	if(RBUFSIZE > sizeof(buf))		panic("kfs: bad buffersize(%d): must be at most %d\n", RBUFSIZE, sizeof(buf)); 	if(wrenread(dev, wrensuper(dev), buf) || wrentag(buf, Tsuper, QPSUPER)	|| wrenread(dev, wrenroot(dev), buf) || wrentag(buf, Tdir, QPROOT))		return 1;	if(((Dentry *)buf)[0].mode & DALLOC)		return 0;	return 1;} longwrensize(Device dev){	return wren(dev)->size / RBUFSIZE;} longwrensuper(Device dev){	USED(dev);	return 1;} longwrenroot(Device dev){	USED(dev);	return 2;} intwrenread(Device dev, long addr, void *b){	Wren *w;	int fd, i; 	w = wren(dev);	fd = w->fd;	qlock(w);	i = seek(fd, (vlong)addr*RBUFSIZE, 0) == -1 || read(fd, b, RBUFSIZE) != RBUFSIZE;	qunlock(w);	if(i)		print("wrenread failed: %r\n");	return i;} intwrenwrite(Device dev, long addr, void *b){	Wren *w;	int fd, i; 	w = wren(dev);	fd = w->fd;	qlock(w);	i = seek(fd, (vlong)addr*RBUFSIZE, 0) == -1 || write(fd, b, RBUFSIZE) != RBUFSIZE;	qunlock(w);	if(i)		print("wrenwrite failed: %r\n");	return i;}