xref: /plan9/sys/src/cmd/unix/drawterm/exportfs/exportfs.c (revision 58da3067adcdccaaa043d0bfde28ba83b7ced07d)
18ccd4a63SDavid du Colombier /*
28ccd4a63SDavid du Colombier  * exportfs - Export a plan 9 name space across a network
38ccd4a63SDavid du Colombier  */
48ccd4a63SDavid du Colombier #include <u.h>
58ccd4a63SDavid du Colombier #include <libc.h>
68ccd4a63SDavid du Colombier #include <fcall.h>
78ccd4a63SDavid du Colombier #include <libsec.h>
88ccd4a63SDavid du Colombier #include "drawterm.h"
98ccd4a63SDavid du Colombier #define Extern
108ccd4a63SDavid du Colombier #include "exportfs.h"
118ccd4a63SDavid du Colombier 
128ccd4a63SDavid du Colombier /* #define QIDPATH	((1LL<<48)-1) */
138ccd4a63SDavid du Colombier #define QIDPATH	((((vlong)1)<<48)-1)
148ccd4a63SDavid du Colombier vlong newqid = 0;
158ccd4a63SDavid du Colombier 
168ccd4a63SDavid du Colombier void (*fcalls[256])(Fsrpc*);
178ccd4a63SDavid du Colombier 
188ccd4a63SDavid du Colombier /* accounting and debugging counters */
198ccd4a63SDavid du Colombier int	filecnt;
208ccd4a63SDavid du Colombier int	freecnt;
218ccd4a63SDavid du Colombier int	qidcnt;
228ccd4a63SDavid du Colombier int	qfreecnt;
238ccd4a63SDavid du Colombier int	ncollision;
248ccd4a63SDavid du Colombier int	netfd;
258ccd4a63SDavid du Colombier 
268ccd4a63SDavid du Colombier int
exportfs(int fd,int msgsz)278ccd4a63SDavid du Colombier exportfs(int fd, int msgsz)
288ccd4a63SDavid du Colombier {
298ccd4a63SDavid du Colombier 	char buf[ERRMAX], ebuf[ERRMAX];
308ccd4a63SDavid du Colombier 	Fsrpc *r;
318ccd4a63SDavid du Colombier 	int i, n;
328ccd4a63SDavid du Colombier 
338ccd4a63SDavid du Colombier 	fcalls[Tversion] = Xversion;
348ccd4a63SDavid du Colombier 	fcalls[Tauth] = Xauth;
358ccd4a63SDavid du Colombier 	fcalls[Tflush] = Xflush;
368ccd4a63SDavid du Colombier 	fcalls[Tattach] = Xattach;
378ccd4a63SDavid du Colombier 	fcalls[Twalk] = Xwalk;
388ccd4a63SDavid du Colombier 	fcalls[Topen] = slave;
398ccd4a63SDavid du Colombier 	fcalls[Tcreate] = Xcreate;
408ccd4a63SDavid du Colombier 	fcalls[Tclunk] = Xclunk;
418ccd4a63SDavid du Colombier 	fcalls[Tread] = slave;
428ccd4a63SDavid du Colombier 	fcalls[Twrite] = slave;
438ccd4a63SDavid du Colombier 	fcalls[Tremove] = Xremove;
448ccd4a63SDavid du Colombier 	fcalls[Tstat] = Xstat;
458ccd4a63SDavid du Colombier 	fcalls[Twstat] = Xwstat;
468ccd4a63SDavid du Colombier 
478ccd4a63SDavid du Colombier 	srvfd = -1;
488ccd4a63SDavid du Colombier 	netfd = fd;
498ccd4a63SDavid du Colombier 	//dbg = 1;
508ccd4a63SDavid du Colombier 
518ccd4a63SDavid du Colombier 	strcpy(buf, "this is buf");
528ccd4a63SDavid du Colombier 	strcpy(ebuf, "this is ebuf");
538ccd4a63SDavid du Colombier 	DEBUG(DFD, "exportfs: started\n");
548ccd4a63SDavid du Colombier 
558ccd4a63SDavid du Colombier //	rfork(RFNOTEG);
568ccd4a63SDavid du Colombier 
578ccd4a63SDavid du Colombier 	messagesize = msgsz;
588ccd4a63SDavid du Colombier 	if(messagesize == 0){
598ccd4a63SDavid du Colombier 		messagesize = iounit(netfd);
608ccd4a63SDavid du Colombier 		if(messagesize == 0)
61*58da3067SDavid du Colombier 			messagesize = 8*8192+IOHDRSZ;
628ccd4a63SDavid du Colombier 	}
638ccd4a63SDavid du Colombier 
648ccd4a63SDavid du Colombier 	Workq = emallocz(sizeof(Fsrpc)*Nr_workbufs);
658ccd4a63SDavid du Colombier //	for(i=0; i<Nr_workbufs; i++)
668ccd4a63SDavid du Colombier //		Workq[i].buf = emallocz(messagesize);
678ccd4a63SDavid du Colombier 	fhash = emallocz(sizeof(Fid*)*FHASHSIZE);
688ccd4a63SDavid du Colombier 
698ccd4a63SDavid du Colombier 	fmtinstall('F', fcallfmt);
708ccd4a63SDavid du Colombier 
718ccd4a63SDavid du Colombier 	initroot();
728ccd4a63SDavid du Colombier 
738ccd4a63SDavid du Colombier 	DEBUG(DFD, "exportfs: %s\n", buf);
748ccd4a63SDavid du Colombier 
758ccd4a63SDavid du Colombier 	/*
768ccd4a63SDavid du Colombier 	 * Start serving file requests from the network
778ccd4a63SDavid du Colombier 	 */
788ccd4a63SDavid du Colombier 	for(;;) {
798ccd4a63SDavid du Colombier 		r = getsbuf();
808ccd4a63SDavid du Colombier 		if(r == 0)
818ccd4a63SDavid du Colombier 			fatal("Out of service buffers");
828ccd4a63SDavid du Colombier 
838ccd4a63SDavid du Colombier 		DEBUG(DFD, "read9p...");
848ccd4a63SDavid du Colombier 		n = read9pmsg(netfd, r->buf, messagesize);
858ccd4a63SDavid du Colombier 		if(n <= 0)
868ccd4a63SDavid du Colombier 			fatal("eof: n=%d %r", n);
878ccd4a63SDavid du Colombier 
888ccd4a63SDavid du Colombier 		if(convM2S(r->buf, n, &r->work) == 0){
898ccd4a63SDavid du Colombier 			iprint("convM2S %d byte message\n", n);
908ccd4a63SDavid du Colombier 			for(i=0; i<n; i++){
918ccd4a63SDavid du Colombier 				iprint(" %.2ux", r->buf[i]);
928ccd4a63SDavid du Colombier 				if(i%16 == 15)
938ccd4a63SDavid du Colombier 					iprint("\n");
948ccd4a63SDavid du Colombier 			}
958ccd4a63SDavid du Colombier 			if(i%16)
968ccd4a63SDavid du Colombier 				iprint("\n");
978ccd4a63SDavid du Colombier 			fatal("convM2S format error");
988ccd4a63SDavid du Colombier 		}
998ccd4a63SDavid du Colombier 
1008ccd4a63SDavid du Colombier if(0) iprint("<- %F\n", &r->work);
1018ccd4a63SDavid du Colombier 		DEBUG(DFD, "%F\n", &r->work);
1028ccd4a63SDavid du Colombier 		(fcalls[r->work.type])(r);
1038ccd4a63SDavid du Colombier 	}
1048ccd4a63SDavid du Colombier }
1058ccd4a63SDavid du Colombier 
1068ccd4a63SDavid du Colombier void
reply(Fcall * r,Fcall * t,char * err)1078ccd4a63SDavid du Colombier reply(Fcall *r, Fcall *t, char *err)
1088ccd4a63SDavid du Colombier {
1098ccd4a63SDavid du Colombier 	uchar *data;
1108ccd4a63SDavid du Colombier 	int m, n;
1118ccd4a63SDavid du Colombier 
1128ccd4a63SDavid du Colombier 	t->tag = r->tag;
1138ccd4a63SDavid du Colombier 	t->fid = r->fid;
1148ccd4a63SDavid du Colombier 	if(err) {
1158ccd4a63SDavid du Colombier 		t->type = Rerror;
1168ccd4a63SDavid du Colombier 		t->ename = err;
1178ccd4a63SDavid du Colombier 	}
1188ccd4a63SDavid du Colombier 	else
1198ccd4a63SDavid du Colombier 		t->type = r->type + 1;
1208ccd4a63SDavid du Colombier 
1218ccd4a63SDavid du Colombier if(0) iprint("-> %F\n", t);
1228ccd4a63SDavid du Colombier 	DEBUG(DFD, "\t%F\n", t);
1238ccd4a63SDavid du Colombier 
1248ccd4a63SDavid du Colombier 	data = malloc(messagesize);	/* not mallocz; no need to clear */
1258ccd4a63SDavid du Colombier 	if(data == nil)
1268ccd4a63SDavid du Colombier 		fatal(Enomem);
1278ccd4a63SDavid du Colombier 	n = convS2M(t, data, messagesize);
1288ccd4a63SDavid du Colombier 	if((m=write(netfd, data, n))!=n){
1298ccd4a63SDavid du Colombier 		iprint("wrote %d got %d (%r)\n", n, m);
1308ccd4a63SDavid du Colombier 		fatal("write");
1318ccd4a63SDavid du Colombier 	}
1328ccd4a63SDavid du Colombier 	free(data);
1338ccd4a63SDavid du Colombier }
1348ccd4a63SDavid du Colombier 
1358ccd4a63SDavid du Colombier Fid *
getfid(int nr)1368ccd4a63SDavid du Colombier getfid(int nr)
1378ccd4a63SDavid du Colombier {
1388ccd4a63SDavid du Colombier 	Fid *f;
1398ccd4a63SDavid du Colombier 
1408ccd4a63SDavid du Colombier 	for(f = fidhash(nr); f; f = f->next)
1418ccd4a63SDavid du Colombier 		if(f->nr == nr)
1428ccd4a63SDavid du Colombier 			return f;
1438ccd4a63SDavid du Colombier 
1448ccd4a63SDavid du Colombier 	return 0;
1458ccd4a63SDavid du Colombier }
1468ccd4a63SDavid du Colombier 
1478ccd4a63SDavid du Colombier int
freefid(int nr)1488ccd4a63SDavid du Colombier freefid(int nr)
1498ccd4a63SDavid du Colombier {
1508ccd4a63SDavid du Colombier 	Fid *f, **l;
1518ccd4a63SDavid du Colombier 	char buf[128];
1528ccd4a63SDavid du Colombier 
1538ccd4a63SDavid du Colombier 	l = &fidhash(nr);
1548ccd4a63SDavid du Colombier 	for(f = *l; f; f = f->next) {
1558ccd4a63SDavid du Colombier 		if(f->nr == nr) {
1568ccd4a63SDavid du Colombier 			if(f->mid) {
1578ccd4a63SDavid du Colombier 				sprint(buf, "/mnt/exportfs/%d", f->mid);
1588ccd4a63SDavid du Colombier 				unmount(0, buf);
1598ccd4a63SDavid du Colombier 				psmap[f->mid] = 0;
1608ccd4a63SDavid du Colombier 			}
1618ccd4a63SDavid du Colombier 			if(f->f) {
1628ccd4a63SDavid du Colombier 				freefile(f->f);
1638ccd4a63SDavid du Colombier 				f->f = nil;
1648ccd4a63SDavid du Colombier 			}
1658ccd4a63SDavid du Colombier 			*l = f->next;
1668ccd4a63SDavid du Colombier 			f->next = fidfree;
1678ccd4a63SDavid du Colombier 			fidfree = f;
1688ccd4a63SDavid du Colombier 			return 1;
1698ccd4a63SDavid du Colombier 		}
1708ccd4a63SDavid du Colombier 		l = &f->next;
1718ccd4a63SDavid du Colombier 	}
1728ccd4a63SDavid du Colombier 
1738ccd4a63SDavid du Colombier 	return 0;
1748ccd4a63SDavid du Colombier }
1758ccd4a63SDavid du Colombier 
1768ccd4a63SDavid du Colombier Fid *
newfid(int nr)1778ccd4a63SDavid du Colombier newfid(int nr)
1788ccd4a63SDavid du Colombier {
1798ccd4a63SDavid du Colombier 	Fid *new, **l;
1808ccd4a63SDavid du Colombier 	int i;
1818ccd4a63SDavid du Colombier 
1828ccd4a63SDavid du Colombier 	l = &fidhash(nr);
1838ccd4a63SDavid du Colombier 	for(new = *l; new; new = new->next)
1848ccd4a63SDavid du Colombier 		if(new->nr == nr)
1858ccd4a63SDavid du Colombier 			return 0;
1868ccd4a63SDavid du Colombier 
1878ccd4a63SDavid du Colombier 	if(fidfree == 0) {
1888ccd4a63SDavid du Colombier 		fidfree = emallocz(sizeof(Fid) * Fidchunk);
1898ccd4a63SDavid du Colombier 
1908ccd4a63SDavid du Colombier 		for(i = 0; i < Fidchunk-1; i++)
1918ccd4a63SDavid du Colombier 			fidfree[i].next = &fidfree[i+1];
1928ccd4a63SDavid du Colombier 
1938ccd4a63SDavid du Colombier 		fidfree[Fidchunk-1].next = 0;
1948ccd4a63SDavid du Colombier 	}
1958ccd4a63SDavid du Colombier 
1968ccd4a63SDavid du Colombier 	new = fidfree;
1978ccd4a63SDavid du Colombier 	fidfree = new->next;
1988ccd4a63SDavid du Colombier 
1998ccd4a63SDavid du Colombier 	memset(new, 0, sizeof(Fid));
2008ccd4a63SDavid du Colombier 	new->next = *l;
2018ccd4a63SDavid du Colombier 	*l = new;
2028ccd4a63SDavid du Colombier 	new->nr = nr;
2038ccd4a63SDavid du Colombier 	new->fid = -1;
2048ccd4a63SDavid du Colombier 	new->mid = 0;
2058ccd4a63SDavid du Colombier 
2068ccd4a63SDavid du Colombier 	return new;
2078ccd4a63SDavid du Colombier }
2088ccd4a63SDavid du Colombier 
2098ccd4a63SDavid du Colombier Fsrpc *
getsbuf(void)2108ccd4a63SDavid du Colombier getsbuf(void)
2118ccd4a63SDavid du Colombier {
2128ccd4a63SDavid du Colombier 	static int ap;
2138ccd4a63SDavid du Colombier 	int look, rounds;
2148ccd4a63SDavid du Colombier 	Fsrpc *wb;
2158ccd4a63SDavid du Colombier 	int small_instead_of_fast = 1;
2168ccd4a63SDavid du Colombier 
2178ccd4a63SDavid du Colombier 	if(small_instead_of_fast)
2188ccd4a63SDavid du Colombier 		ap = 0;	/* so we always start looking at the beginning and reuse buffers */
2198ccd4a63SDavid du Colombier 
2208ccd4a63SDavid du Colombier 	for(rounds = 0; rounds < 10; rounds++) {
2218ccd4a63SDavid du Colombier 		for(look = 0; look < Nr_workbufs; look++) {
2228ccd4a63SDavid du Colombier 			if(++ap == Nr_workbufs)
2238ccd4a63SDavid du Colombier 				ap = 0;
2248ccd4a63SDavid du Colombier 			if(Workq[ap].busy == 0)
2258ccd4a63SDavid du Colombier 				break;
2268ccd4a63SDavid du Colombier 		}
2278ccd4a63SDavid du Colombier 
2288ccd4a63SDavid du Colombier 		if(look == Nr_workbufs){
2298ccd4a63SDavid du Colombier 			sleep(10 * rounds);
2308ccd4a63SDavid du Colombier 			continue;
2318ccd4a63SDavid du Colombier 		}
2328ccd4a63SDavid du Colombier 
2338ccd4a63SDavid du Colombier 		wb = &Workq[ap];
2348ccd4a63SDavid du Colombier 		wb->pid = 0;
2358ccd4a63SDavid du Colombier 		wb->canint = 0;
2368ccd4a63SDavid du Colombier 		wb->flushtag = NOTAG;
2378ccd4a63SDavid du Colombier 		wb->busy = 1;
2388ccd4a63SDavid du Colombier 		if(wb->buf == nil)	/* allocate buffers dynamically to keep size down */
2398ccd4a63SDavid du Colombier 			wb->buf = emallocz(messagesize);
2408ccd4a63SDavid du Colombier 		return wb;
2418ccd4a63SDavid du Colombier 	}
2428ccd4a63SDavid du Colombier 	fatal("No more work buffers");
2438ccd4a63SDavid du Colombier 	return nil;
2448ccd4a63SDavid du Colombier }
2458ccd4a63SDavid du Colombier 
2468ccd4a63SDavid du Colombier void
freefile(File * f)2478ccd4a63SDavid du Colombier freefile(File *f)
2488ccd4a63SDavid du Colombier {
2498ccd4a63SDavid du Colombier 	File *parent, *child;
2508ccd4a63SDavid du Colombier 
2518ccd4a63SDavid du Colombier Loop:
2528ccd4a63SDavid du Colombier 	f->ref--;
2538ccd4a63SDavid du Colombier 	if(f->ref > 0)
2548ccd4a63SDavid du Colombier 		return;
2558ccd4a63SDavid du Colombier 	freecnt++;
2568ccd4a63SDavid du Colombier 	if(f->ref < 0) abort();
2578ccd4a63SDavid du Colombier 	DEBUG(DFD, "free %s\n", f->name);
2588ccd4a63SDavid du Colombier 	/* delete from parent */
2598ccd4a63SDavid du Colombier 	parent = f->parent;
2608ccd4a63SDavid du Colombier 	if(parent->child == f)
2618ccd4a63SDavid du Colombier 		parent->child = f->childlist;
2628ccd4a63SDavid du Colombier 	else{
2638ccd4a63SDavid du Colombier 		for(child=parent->child; child->childlist!=f; child=child->childlist)
2648ccd4a63SDavid du Colombier 			if(child->childlist == nil)
2658ccd4a63SDavid du Colombier 				fatal("bad child list");
2668ccd4a63SDavid du Colombier 		child->childlist = f->childlist;
2678ccd4a63SDavid du Colombier 	}
2688ccd4a63SDavid du Colombier 	freeqid(f->qidt);
2698ccd4a63SDavid du Colombier 	free(f->name);
2708ccd4a63SDavid du Colombier 	f->name = nil;
2718ccd4a63SDavid du Colombier 	free(f);
2728ccd4a63SDavid du Colombier 	f = parent;
2738ccd4a63SDavid du Colombier 	if(f != nil)
2748ccd4a63SDavid du Colombier 		goto Loop;
2758ccd4a63SDavid du Colombier }
2768ccd4a63SDavid du Colombier 
2778ccd4a63SDavid du Colombier File *
file(File * parent,char * name)2788ccd4a63SDavid du Colombier file(File *parent, char *name)
2798ccd4a63SDavid du Colombier {
2808ccd4a63SDavid du Colombier 	Dir *dir;
2818ccd4a63SDavid du Colombier 	char *path;
2828ccd4a63SDavid du Colombier 	File *f;
2838ccd4a63SDavid du Colombier 
2848ccd4a63SDavid du Colombier 	DEBUG(DFD, "\tfile: 0x%p %s name %s\n", parent, parent->name, name);
2858ccd4a63SDavid du Colombier 
2868ccd4a63SDavid du Colombier 	path = makepath(parent, name);
2878ccd4a63SDavid du Colombier 	dir = dirstat(path);
2888ccd4a63SDavid du Colombier 	free(path);
2898ccd4a63SDavid du Colombier 	if(dir == nil)
2908ccd4a63SDavid du Colombier 		return nil;
2918ccd4a63SDavid du Colombier 
2928ccd4a63SDavid du Colombier 	for(f = parent->child; f; f = f->childlist)
2938ccd4a63SDavid du Colombier 		if(strcmp(name, f->name) == 0)
2948ccd4a63SDavid du Colombier 			break;
2958ccd4a63SDavid du Colombier 
2968ccd4a63SDavid du Colombier 	if(f == nil){
2978ccd4a63SDavid du Colombier 		f = emallocz(sizeof(File));
2988ccd4a63SDavid du Colombier 		f->name = estrdup(name);
2998ccd4a63SDavid du Colombier 
3008ccd4a63SDavid du Colombier 		f->parent = parent;
3018ccd4a63SDavid du Colombier 		f->childlist = parent->child;
3028ccd4a63SDavid du Colombier 		parent->child = f;
3038ccd4a63SDavid du Colombier 		parent->ref++;
3048ccd4a63SDavid du Colombier 		f->ref = 0;
3058ccd4a63SDavid du Colombier 		filecnt++;
3068ccd4a63SDavid du Colombier 	}
3078ccd4a63SDavid du Colombier 	f->ref++;
3088ccd4a63SDavid du Colombier 	f->qid.type = dir->qid.type;
3098ccd4a63SDavid du Colombier 	f->qid.vers = dir->qid.vers;
3108ccd4a63SDavid du Colombier 	f->qidt = uniqueqid(dir);
3118ccd4a63SDavid du Colombier 	f->qid.path = f->qidt->uniqpath;
3128ccd4a63SDavid du Colombier 
3138ccd4a63SDavid du Colombier 	f->inval = 0;
3148ccd4a63SDavid du Colombier 
3158ccd4a63SDavid du Colombier 	free(dir);
3168ccd4a63SDavid du Colombier 
3178ccd4a63SDavid du Colombier 	return f;
3188ccd4a63SDavid du Colombier }
3198ccd4a63SDavid du Colombier 
3208ccd4a63SDavid du Colombier void
initroot(void)3218ccd4a63SDavid du Colombier initroot(void)
3228ccd4a63SDavid du Colombier {
3238ccd4a63SDavid du Colombier 	Dir *dir;
3248ccd4a63SDavid du Colombier 
3258ccd4a63SDavid du Colombier 	root = emallocz(sizeof(File));
3268ccd4a63SDavid du Colombier 	root->name = estrdup(".");
3278ccd4a63SDavid du Colombier 
3288ccd4a63SDavid du Colombier 	dir = dirstat(root->name);
3298ccd4a63SDavid du Colombier 	if(dir == nil)
3308ccd4a63SDavid du Colombier 		fatal("root stat");
3318ccd4a63SDavid du Colombier 
3328ccd4a63SDavid du Colombier 	root->ref = 1;
3338ccd4a63SDavid du Colombier 	root->qid.vers = dir->qid.vers;
3348ccd4a63SDavid du Colombier 	root->qidt = uniqueqid(dir);
3358ccd4a63SDavid du Colombier 	root->qid.path = root->qidt->uniqpath;
3368ccd4a63SDavid du Colombier 	root->qid.type = QTDIR;
3378ccd4a63SDavid du Colombier 	free(dir);
3388ccd4a63SDavid du Colombier 
3398ccd4a63SDavid du Colombier 	psmpt = emallocz(sizeof(File));
3408ccd4a63SDavid du Colombier 	psmpt->name = estrdup("/");
3418ccd4a63SDavid du Colombier 
3428ccd4a63SDavid du Colombier 	dir = dirstat(psmpt->name);
3438ccd4a63SDavid du Colombier 	if(dir == nil)
3448ccd4a63SDavid du Colombier 		return;
3458ccd4a63SDavid du Colombier 
3468ccd4a63SDavid du Colombier 	psmpt->ref = 1;
3478ccd4a63SDavid du Colombier 	psmpt->qid.vers = dir->qid.vers;
3488ccd4a63SDavid du Colombier 	psmpt->qidt = uniqueqid(dir);
3498ccd4a63SDavid du Colombier 	psmpt->qid.path = psmpt->qidt->uniqpath;
3508ccd4a63SDavid du Colombier 	free(dir);
3518ccd4a63SDavid du Colombier 
3528ccd4a63SDavid du Colombier 	psmpt = file(psmpt, "mnt");
3538ccd4a63SDavid du Colombier 	if(psmpt == 0)
3548ccd4a63SDavid du Colombier 		return;
3558ccd4a63SDavid du Colombier 	psmpt = file(psmpt, "exportfs");
3568ccd4a63SDavid du Colombier }
3578ccd4a63SDavid du Colombier 
3588ccd4a63SDavid du Colombier char*
makepath(File * p,char * name)3598ccd4a63SDavid du Colombier makepath(File *p, char *name)
3608ccd4a63SDavid du Colombier {
3618ccd4a63SDavid du Colombier 	int i, n;
3628ccd4a63SDavid du Colombier 	char *c, *s, *path, *seg[256];
3638ccd4a63SDavid du Colombier 
3648ccd4a63SDavid du Colombier 	seg[0] = name;
3658ccd4a63SDavid du Colombier 	n = strlen(name)+2;
3668ccd4a63SDavid du Colombier 	for(i = 1; i < 256 && p; i++, p = p->parent){
3678ccd4a63SDavid du Colombier 		seg[i] = p->name;
3688ccd4a63SDavid du Colombier 		n += strlen(p->name)+1;
3698ccd4a63SDavid du Colombier 	}
3708ccd4a63SDavid du Colombier 	path = malloc(n);
3718ccd4a63SDavid du Colombier 	if(path == nil)
3728ccd4a63SDavid du Colombier 		fatal("out of memory");
3738ccd4a63SDavid du Colombier 	s = path;
3748ccd4a63SDavid du Colombier 
3758ccd4a63SDavid du Colombier 	while(i--) {
3768ccd4a63SDavid du Colombier 		for(c = seg[i]; *c; c++)
3778ccd4a63SDavid du Colombier 			*s++ = *c;
3788ccd4a63SDavid du Colombier 		*s++ = '/';
3798ccd4a63SDavid du Colombier 	}
3808ccd4a63SDavid du Colombier 	while(s[-1] == '/')
3818ccd4a63SDavid du Colombier 		s--;
3828ccd4a63SDavid du Colombier 	*s = '\0';
3838ccd4a63SDavid du Colombier 
3848ccd4a63SDavid du Colombier 	return path;
3858ccd4a63SDavid du Colombier }
3868ccd4a63SDavid du Colombier 
3878ccd4a63SDavid du Colombier int
qidhash(vlong path)3888ccd4a63SDavid du Colombier qidhash(vlong path)
3898ccd4a63SDavid du Colombier {
3908ccd4a63SDavid du Colombier 	int h, n;
3918ccd4a63SDavid du Colombier 
3928ccd4a63SDavid du Colombier 	h = 0;
3938ccd4a63SDavid du Colombier 	for(n=0; n<64; n+=Nqidbits){
3948ccd4a63SDavid du Colombier 		h ^= path;
3958ccd4a63SDavid du Colombier 		path >>= Nqidbits;
3968ccd4a63SDavid du Colombier 	}
3978ccd4a63SDavid du Colombier 	return h & (Nqidtab-1);
3988ccd4a63SDavid du Colombier }
3998ccd4a63SDavid du Colombier 
4008ccd4a63SDavid du Colombier void
freeqid(Qidtab * q)4018ccd4a63SDavid du Colombier freeqid(Qidtab *q)
4028ccd4a63SDavid du Colombier {
4038ccd4a63SDavid du Colombier 	ulong h;
4048ccd4a63SDavid du Colombier 	Qidtab *l;
4058ccd4a63SDavid du Colombier 
4068ccd4a63SDavid du Colombier 	q->ref--;
4078ccd4a63SDavid du Colombier 	if(q->ref > 0)
4088ccd4a63SDavid du Colombier 		return;
4098ccd4a63SDavid du Colombier 	qfreecnt++;
4108ccd4a63SDavid du Colombier 	h = qidhash(q->path);
4118ccd4a63SDavid du Colombier 	if(qidtab[h] == q)
4128ccd4a63SDavid du Colombier 		qidtab[h] = q->next;
4138ccd4a63SDavid du Colombier 	else{
4148ccd4a63SDavid du Colombier 		for(l=qidtab[h]; l->next!=q; l=l->next)
4158ccd4a63SDavid du Colombier 			if(l->next == nil)
4168ccd4a63SDavid du Colombier 				fatal("bad qid list");
4178ccd4a63SDavid du Colombier 		l->next = q->next;
4188ccd4a63SDavid du Colombier 	}
4198ccd4a63SDavid du Colombier 	free(q);
4208ccd4a63SDavid du Colombier }
4218ccd4a63SDavid du Colombier 
4228ccd4a63SDavid du Colombier Qidtab*
qidlookup(Dir * d)4238ccd4a63SDavid du Colombier qidlookup(Dir *d)
4248ccd4a63SDavid du Colombier {
4258ccd4a63SDavid du Colombier 	ulong h;
4268ccd4a63SDavid du Colombier 	Qidtab *q;
4278ccd4a63SDavid du Colombier 
4288ccd4a63SDavid du Colombier 	h = qidhash(d->qid.path);
4298ccd4a63SDavid du Colombier 	for(q=qidtab[h]; q!=nil; q=q->next)
4308ccd4a63SDavid du Colombier 		if(q->type==d->type && q->dev==d->dev && q->path==d->qid.path)
4318ccd4a63SDavid du Colombier 			return q;
4328ccd4a63SDavid du Colombier 	return nil;
4338ccd4a63SDavid du Colombier }
4348ccd4a63SDavid du Colombier 
4358ccd4a63SDavid du Colombier int
qidexists(vlong path)4368ccd4a63SDavid du Colombier qidexists(vlong path)
4378ccd4a63SDavid du Colombier {
4388ccd4a63SDavid du Colombier 	int h;
4398ccd4a63SDavid du Colombier 	Qidtab *q;
4408ccd4a63SDavid du Colombier 
4418ccd4a63SDavid du Colombier 	for(h=0; h<Nqidtab; h++)
4428ccd4a63SDavid du Colombier 		for(q=qidtab[h]; q!=nil; q=q->next)
4438ccd4a63SDavid du Colombier 			if(q->uniqpath == path)
4448ccd4a63SDavid du Colombier 				return 1;
4458ccd4a63SDavid du Colombier 	return 0;
4468ccd4a63SDavid du Colombier }
4478ccd4a63SDavid du Colombier 
4488ccd4a63SDavid du Colombier Qidtab*
uniqueqid(Dir * d)4498ccd4a63SDavid du Colombier uniqueqid(Dir *d)
4508ccd4a63SDavid du Colombier {
4518ccd4a63SDavid du Colombier 	ulong h;
4528ccd4a63SDavid du Colombier 	vlong path;
4538ccd4a63SDavid du Colombier 	Qidtab *q;
4548ccd4a63SDavid du Colombier 
4558ccd4a63SDavid du Colombier 	q = qidlookup(d);
4568ccd4a63SDavid du Colombier 	if(q != nil){
4578ccd4a63SDavid du Colombier 		q->ref++;
4588ccd4a63SDavid du Colombier 		return q;
4598ccd4a63SDavid du Colombier 	}
4608ccd4a63SDavid du Colombier 	path = d->qid.path;
4618ccd4a63SDavid du Colombier 	while(qidexists(path)){
4628ccd4a63SDavid du Colombier 		DEBUG(DFD, "collision on %s\n", d->name);
4638ccd4a63SDavid du Colombier 		/* collision: find a new one */
4648ccd4a63SDavid du Colombier 		ncollision++;
4658ccd4a63SDavid du Colombier 		path &= QIDPATH;
4668ccd4a63SDavid du Colombier 		++newqid;
4678ccd4a63SDavid du Colombier 		if(newqid >= (1<<16)){
4688ccd4a63SDavid du Colombier 			DEBUG(DFD, "collision wraparound\n");
4698ccd4a63SDavid du Colombier 			newqid = 1;
4708ccd4a63SDavid du Colombier 		}
4718ccd4a63SDavid du Colombier 		path |= newqid<<48;
4728ccd4a63SDavid du Colombier 		DEBUG(DFD, "assign qid %.16llux\n", path);
4738ccd4a63SDavid du Colombier 	}
4748ccd4a63SDavid du Colombier 	q = mallocz(sizeof(Qidtab), 1);
4758ccd4a63SDavid du Colombier 	if(q == nil)
4768ccd4a63SDavid du Colombier 		fatal("no memory for qid table");
4778ccd4a63SDavid du Colombier 	qidcnt++;
4788ccd4a63SDavid du Colombier 	q->ref = 1;
4798ccd4a63SDavid du Colombier 	q->type = d->type;
4808ccd4a63SDavid du Colombier 	q->dev = d->dev;
4818ccd4a63SDavid du Colombier 	q->path = d->qid.path;
4828ccd4a63SDavid du Colombier 	q->uniqpath = path;
4838ccd4a63SDavid du Colombier 	h = qidhash(d->qid.path);
4848ccd4a63SDavid du Colombier 	q->next = qidtab[h];
4858ccd4a63SDavid du Colombier 	qidtab[h] = q;
4868ccd4a63SDavid du Colombier 	return q;
4878ccd4a63SDavid du Colombier }
4888ccd4a63SDavid du Colombier 
4898ccd4a63SDavid du Colombier void
fatal(char * s,...)4908ccd4a63SDavid du Colombier fatal(char *s, ...)
4918ccd4a63SDavid du Colombier {
4928ccd4a63SDavid du Colombier 	char buf[ERRMAX];
4938ccd4a63SDavid du Colombier 	va_list arg;
4948ccd4a63SDavid du Colombier 
4958ccd4a63SDavid du Colombier 	if (s) {
4968ccd4a63SDavid du Colombier 		va_start(arg, s);
4978ccd4a63SDavid du Colombier 		vsnprint(buf, ERRMAX, s, arg);
4988ccd4a63SDavid du Colombier 		va_end(arg);
4998ccd4a63SDavid du Colombier 	}
5008ccd4a63SDavid du Colombier 
5018ccd4a63SDavid du Colombier 	/* Clear away the slave children */
5028ccd4a63SDavid du Colombier //	for(m = Proclist; m; m = m->next)
5038ccd4a63SDavid du Colombier //		postnote(PNPROC, m->pid, "kill");
5048ccd4a63SDavid du Colombier 
5058ccd4a63SDavid du Colombier 	DEBUG(DFD, "%s\n", buf);
5068ccd4a63SDavid du Colombier 	if (s)
5078ccd4a63SDavid du Colombier 		sysfatal(buf);
5088ccd4a63SDavid du Colombier 	else
5098ccd4a63SDavid du Colombier 		sysfatal("");
5108ccd4a63SDavid du Colombier }
5118ccd4a63SDavid du Colombier 
512