xref: /plan9/sys/src/cmd/exportfs/exportsrv.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
3*219b2ee8SDavid du Colombier #include <auth.h>
43e12c5d1SDavid du Colombier #include <fcall.h>
53e12c5d1SDavid du Colombier #define Extern	extern
63e12c5d1SDavid du Colombier #include "exportfs.h"
73e12c5d1SDavid du Colombier 
83e12c5d1SDavid du Colombier char *e[] =
93e12c5d1SDavid du Colombier {
103e12c5d1SDavid du Colombier 	[Ebadfid]	"Bad fid",
113e12c5d1SDavid du Colombier 	[Enotdir]	"Not a directory",
123e12c5d1SDavid du Colombier 	[Edupfid]	"Fid already in use",
133e12c5d1SDavid du Colombier 	[Eopen]		"Fid already opened",
143e12c5d1SDavid du Colombier 	[Exmnt]		"Cannot .. past mount point",
153e12c5d1SDavid du Colombier 	[Enoauth]	"Authentication failed",
16*219b2ee8SDavid du Colombier 	[Emip]		"Mount in progress",
17*219b2ee8SDavid du Colombier 	[Enopsmt]	"Out of pseudo mount points",
183e12c5d1SDavid du Colombier };
193e12c5d1SDavid du Colombier 
203e12c5d1SDavid du Colombier void
213e12c5d1SDavid du Colombier Xnop(Fsrpc *r)
223e12c5d1SDavid du Colombier {
233e12c5d1SDavid du Colombier 	Fcall thdr;
243e12c5d1SDavid du Colombier 
253e12c5d1SDavid du Colombier 	reply(&r->work, &thdr, 0);
263e12c5d1SDavid du Colombier 	r->busy = 0;
273e12c5d1SDavid du Colombier }
283e12c5d1SDavid du Colombier 
293e12c5d1SDavid du Colombier void
303e12c5d1SDavid du Colombier Xsession(Fsrpc *r)
313e12c5d1SDavid du Colombier {
323e12c5d1SDavid du Colombier 	Fcall thdr;
333e12c5d1SDavid du Colombier 
34*219b2ee8SDavid du Colombier 	memset(thdr.authid, 0, sizeof(thdr.authid));
35*219b2ee8SDavid du Colombier 	memset(thdr.authdom, 0, sizeof(thdr.authdom));
36*219b2ee8SDavid du Colombier 	memset(thdr.chal, 0, sizeof(thdr.chal));
373e12c5d1SDavid du Colombier 	reply(&r->work, &thdr, 0);
383e12c5d1SDavid du Colombier 	r->busy = 0;
393e12c5d1SDavid du Colombier }
403e12c5d1SDavid du Colombier 
413e12c5d1SDavid du Colombier void
423e12c5d1SDavid du Colombier Xflush(Fsrpc *r)
433e12c5d1SDavid du Colombier {
443e12c5d1SDavid du Colombier 	Fsrpc *t, *e;
453e12c5d1SDavid du Colombier 	Fcall thdr;
463e12c5d1SDavid du Colombier 
473e12c5d1SDavid du Colombier 	e = &Workq[Nr_workbufs];
483e12c5d1SDavid du Colombier 
493e12c5d1SDavid du Colombier 	for(t = Workq; t < e; t++) {
503e12c5d1SDavid du Colombier 		if(t->work.tag == r->work.oldtag) {
513e12c5d1SDavid du Colombier 			DEBUG(2, "\tQ busy %d pid %d can %d\n", t->busy, t->pid, t->canint);
523e12c5d1SDavid du Colombier 			if(t->busy && t->pid) {
533e12c5d1SDavid du Colombier 				t->flushtag = r->work.tag;
543e12c5d1SDavid du Colombier 				DEBUG(2, "\tset flushtag %d\n", r->work.tag);
553e12c5d1SDavid du Colombier 				if(t->canint)
56*219b2ee8SDavid du Colombier 					postnote(PNPROC, t->pid, "flush");
573e12c5d1SDavid du Colombier 				r->busy = 0;
583e12c5d1SDavid du Colombier 				return;
593e12c5d1SDavid du Colombier 			}
603e12c5d1SDavid du Colombier 		}
613e12c5d1SDavid du Colombier 	}
623e12c5d1SDavid du Colombier 
633e12c5d1SDavid du Colombier 	reply(&r->work, &thdr, 0);
643e12c5d1SDavid du Colombier 	DEBUG(2, "\tflush reply\n");
653e12c5d1SDavid du Colombier 	r->busy = 0;
663e12c5d1SDavid du Colombier }
673e12c5d1SDavid du Colombier 
683e12c5d1SDavid du Colombier void
693e12c5d1SDavid du Colombier Xattach(Fsrpc *r)
703e12c5d1SDavid du Colombier {
713e12c5d1SDavid du Colombier 	Fcall thdr;
723e12c5d1SDavid du Colombier 	Fid *f;
733e12c5d1SDavid du Colombier 
743e12c5d1SDavid du Colombier 	f = newfid(r->work.fid);
753e12c5d1SDavid du Colombier 	if(f == 0) {
763e12c5d1SDavid du Colombier 		reply(&r->work, &thdr, e[Ebadfid]);
773e12c5d1SDavid du Colombier 		r->busy = 0;
783e12c5d1SDavid du Colombier 		return;
793e12c5d1SDavid du Colombier 	}
803e12c5d1SDavid du Colombier 
813e12c5d1SDavid du Colombier 	f->f = root;
823e12c5d1SDavid du Colombier 	thdr.qid = f->f->qid;
833e12c5d1SDavid du Colombier 	reply(&r->work, &thdr, 0);
843e12c5d1SDavid du Colombier 	r->busy = 0;
853e12c5d1SDavid du Colombier }
863e12c5d1SDavid du Colombier 
873e12c5d1SDavid du Colombier void
883e12c5d1SDavid du Colombier Xclone(Fsrpc *r)
893e12c5d1SDavid du Colombier {
903e12c5d1SDavid du Colombier 	Fcall thdr;
913e12c5d1SDavid du Colombier 	Fid *f, *n;
923e12c5d1SDavid du Colombier 
933e12c5d1SDavid du Colombier 	f = getfid(r->work.fid);
943e12c5d1SDavid du Colombier 	if(f == 0) {
953e12c5d1SDavid du Colombier 		reply(&r->work, &thdr, e[Ebadfid]);
963e12c5d1SDavid du Colombier 		r->busy = 0;
973e12c5d1SDavid du Colombier 		return;
983e12c5d1SDavid du Colombier 	}
993e12c5d1SDavid du Colombier 	n = newfid(r->work.newfid);
1003e12c5d1SDavid du Colombier 	if(n == 0) {
101*219b2ee8SDavid du Colombier 		n = getfid(r->work.newfid);
102*219b2ee8SDavid du Colombier 		if(n == 0)
103*219b2ee8SDavid du Colombier 			fatal("inconsistent fids");
104*219b2ee8SDavid du Colombier 		if(n->fid >= 0)
105*219b2ee8SDavid du Colombier 			close(n->fid);
106*219b2ee8SDavid du Colombier 		freefid(r->work.newfid);
107*219b2ee8SDavid du Colombier 		n = newfid(r->work.newfid);
108*219b2ee8SDavid du Colombier 		if(n == 0)
109*219b2ee8SDavid du Colombier 			fatal("inconsistent fids2");
1103e12c5d1SDavid du Colombier 	}
1113e12c5d1SDavid du Colombier 	n->f = f->f;
1123e12c5d1SDavid du Colombier 	reply(&r->work, &thdr, 0);
1133e12c5d1SDavid du Colombier 	r->busy = 0;
1143e12c5d1SDavid du Colombier }
1153e12c5d1SDavid du Colombier 
1163e12c5d1SDavid du Colombier void
1173e12c5d1SDavid du Colombier Xwalk(Fsrpc *r)
1183e12c5d1SDavid du Colombier {
1193e12c5d1SDavid du Colombier 	char err[ERRLEN];
1203e12c5d1SDavid du Colombier 	Fcall thdr;
1213e12c5d1SDavid du Colombier 	Fid *f;
1223e12c5d1SDavid du Colombier 	File *nf;
1233e12c5d1SDavid du Colombier 
1243e12c5d1SDavid du Colombier 	f = getfid(r->work.fid);
1253e12c5d1SDavid du Colombier 	if(f == 0) {
1263e12c5d1SDavid du Colombier 		reply(&r->work, &thdr, e[Ebadfid]);
1273e12c5d1SDavid du Colombier 		r->busy = 0;
1283e12c5d1SDavid du Colombier 		return;
1293e12c5d1SDavid du Colombier 	}
1303e12c5d1SDavid du Colombier 
1313e12c5d1SDavid du Colombier 	if(strcmp(r->work.name, "..") == 0) {
1323e12c5d1SDavid du Colombier 		if(f->f->parent == 0) {
1333e12c5d1SDavid du Colombier 			reply(&r->work, &thdr, e[Exmnt]);
1343e12c5d1SDavid du Colombier 			r->busy = 0;
1353e12c5d1SDavid du Colombier 			return;
1363e12c5d1SDavid du Colombier 		}
1373e12c5d1SDavid du Colombier 		f->f = f->f->parent;
1383e12c5d1SDavid du Colombier 		thdr.qid = f->f->qid;
1393e12c5d1SDavid du Colombier 		reply(&r->work, &thdr, 0);
1403e12c5d1SDavid du Colombier 		r->busy = 0;
1413e12c5d1SDavid du Colombier 		return;
1423e12c5d1SDavid du Colombier 	}
1433e12c5d1SDavid du Colombier 
1443e12c5d1SDavid du Colombier 	nf = file(f->f, r->work.name);
1453e12c5d1SDavid du Colombier 	if(nf == 0) {
1463e12c5d1SDavid du Colombier 		errstr(err);
1473e12c5d1SDavid du Colombier 		reply(&r->work, &thdr, err);
1483e12c5d1SDavid du Colombier 		r->busy = 0;
1493e12c5d1SDavid du Colombier 		return;
1503e12c5d1SDavid du Colombier 	}
1513e12c5d1SDavid du Colombier 
1523e12c5d1SDavid du Colombier 	f->f = nf;
1533e12c5d1SDavid du Colombier 	thdr.qid = nf->qid;
1543e12c5d1SDavid du Colombier 	reply(&r->work, &thdr, 0);
1553e12c5d1SDavid du Colombier 	r->busy = 0;
1563e12c5d1SDavid du Colombier }
1573e12c5d1SDavid du Colombier 
1583e12c5d1SDavid du Colombier void
1593e12c5d1SDavid du Colombier Xclunk(Fsrpc *r)
1603e12c5d1SDavid du Colombier {
1613e12c5d1SDavid du Colombier 	Fcall thdr;
1623e12c5d1SDavid du Colombier 	Fid *f;
1633e12c5d1SDavid du Colombier 
1643e12c5d1SDavid du Colombier 	f = getfid(r->work.fid);
1653e12c5d1SDavid du Colombier 	if(f == 0) {
1663e12c5d1SDavid du Colombier 		reply(&r->work, &thdr, e[Ebadfid]);
1673e12c5d1SDavid du Colombier 		r->busy = 0;
1683e12c5d1SDavid du Colombier 		return;
1693e12c5d1SDavid du Colombier 	}
1703e12c5d1SDavid du Colombier 
1713e12c5d1SDavid du Colombier 	if(f->fid >= 0)
1723e12c5d1SDavid du Colombier 		close(f->fid);
1733e12c5d1SDavid du Colombier 
1743e12c5d1SDavid du Colombier 	freefid(r->work.fid);
1753e12c5d1SDavid du Colombier 	reply(&r->work, &thdr, 0);
1763e12c5d1SDavid du Colombier 	r->busy = 0;
1773e12c5d1SDavid du Colombier }
1783e12c5d1SDavid du Colombier 
1793e12c5d1SDavid du Colombier void
1803e12c5d1SDavid du Colombier Xstat(Fsrpc *r)
1813e12c5d1SDavid du Colombier {
1823e12c5d1SDavid du Colombier 	char err[ERRLEN], path[128];
1833e12c5d1SDavid du Colombier 	Fcall thdr;
1843e12c5d1SDavid du Colombier 	Fid *f;
1853e12c5d1SDavid du Colombier 	int s;
1863e12c5d1SDavid du Colombier 
1873e12c5d1SDavid du Colombier 	f = getfid(r->work.fid);
1883e12c5d1SDavid du Colombier 	if(f == 0) {
1893e12c5d1SDavid du Colombier 		reply(&r->work, &thdr, e[Ebadfid]);
1903e12c5d1SDavid du Colombier 		r->busy = 0;
1913e12c5d1SDavid du Colombier 		return;
1923e12c5d1SDavid du Colombier 	}
1933e12c5d1SDavid du Colombier 	if(f->fid >= 0)
1943e12c5d1SDavid du Colombier 		s = fstat(f->fid, thdr.stat);
1953e12c5d1SDavid du Colombier 	else {
1963e12c5d1SDavid du Colombier 		makepath(path, f->f, "");
1973e12c5d1SDavid du Colombier 		s = stat(path, thdr.stat);
1983e12c5d1SDavid du Colombier 	}
1993e12c5d1SDavid du Colombier 
2003e12c5d1SDavid du Colombier 	if(s < 0) {
2013e12c5d1SDavid du Colombier 		errstr(err);
2023e12c5d1SDavid du Colombier 		reply(&r->work, &thdr, err);
2033e12c5d1SDavid du Colombier 		r->busy = 0;
2043e12c5d1SDavid du Colombier 		return;
2053e12c5d1SDavid du Colombier 	}
2063e12c5d1SDavid du Colombier 	reply(&r->work, &thdr, 0);
2073e12c5d1SDavid du Colombier 	r->busy = 0;
2083e12c5d1SDavid du Colombier }
2093e12c5d1SDavid du Colombier 
2103e12c5d1SDavid du Colombier void
2113e12c5d1SDavid du Colombier Xcreate(Fsrpc *r)
2123e12c5d1SDavid du Colombier {
2133e12c5d1SDavid du Colombier 	char err[ERRLEN], path[128];
2143e12c5d1SDavid du Colombier 	Fcall thdr;
2153e12c5d1SDavid du Colombier 	Fid *f;
2163e12c5d1SDavid du Colombier 	File *nf;
2173e12c5d1SDavid du Colombier 
2183e12c5d1SDavid du Colombier 	f = getfid(r->work.fid);
2193e12c5d1SDavid du Colombier 	if(f == 0) {
2203e12c5d1SDavid du Colombier 		reply(&r->work, &thdr, e[Ebadfid]);
2213e12c5d1SDavid du Colombier 		r->busy = 0;
2223e12c5d1SDavid du Colombier 		return;
2233e12c5d1SDavid du Colombier 	}
2243e12c5d1SDavid du Colombier 
2253e12c5d1SDavid du Colombier 
2263e12c5d1SDavid du Colombier 	makepath(path, f->f, r->work.name);
2273e12c5d1SDavid du Colombier 	f->fid = create(path, r->work.mode, r->work.perm);
2283e12c5d1SDavid du Colombier 	if(f->fid < 0) {
2293e12c5d1SDavid du Colombier 		errstr(err);
2303e12c5d1SDavid du Colombier 		reply(&r->work, &thdr, err);
2313e12c5d1SDavid du Colombier 		r->busy = 0;
2323e12c5d1SDavid du Colombier 		return;
2333e12c5d1SDavid du Colombier 	}
2343e12c5d1SDavid du Colombier 
2353e12c5d1SDavid du Colombier 	nf = file(f->f, r->work.name);
2363e12c5d1SDavid du Colombier 	if(nf == 0) {
2373e12c5d1SDavid du Colombier 		errstr(err);
2383e12c5d1SDavid du Colombier 		reply(&r->work, &thdr, err);
2393e12c5d1SDavid du Colombier 		r->busy = 0;
2403e12c5d1SDavid du Colombier 		return;
2413e12c5d1SDavid du Colombier 	}
2423e12c5d1SDavid du Colombier 
2433e12c5d1SDavid du Colombier 	f->mode = r->work.mode;
2443e12c5d1SDavid du Colombier 	f->f = nf;
2453e12c5d1SDavid du Colombier 	f->offset = 0;
2463e12c5d1SDavid du Colombier 	thdr.qid = f->f->qid;
2473e12c5d1SDavid du Colombier 	reply(&r->work, &thdr, 0);
2483e12c5d1SDavid du Colombier 	r->busy = 0;
2493e12c5d1SDavid du Colombier }
2503e12c5d1SDavid du Colombier 
2513e12c5d1SDavid du Colombier 
2523e12c5d1SDavid du Colombier void
2533e12c5d1SDavid du Colombier Xremove(Fsrpc *r)
2543e12c5d1SDavid du Colombier {
2553e12c5d1SDavid du Colombier 	char err[ERRLEN], path[128];
2563e12c5d1SDavid du Colombier 	Fcall thdr;
2573e12c5d1SDavid du Colombier 	Fid *f;
2583e12c5d1SDavid du Colombier 
2593e12c5d1SDavid du Colombier 	f = getfid(r->work.fid);
2603e12c5d1SDavid du Colombier 	if(f == 0) {
2613e12c5d1SDavid du Colombier 		reply(&r->work, &thdr, e[Ebadfid]);
2623e12c5d1SDavid du Colombier 		r->busy = 0;
2633e12c5d1SDavid du Colombier 		return;
2643e12c5d1SDavid du Colombier 	}
2653e12c5d1SDavid du Colombier 
2663e12c5d1SDavid du Colombier 	makepath(path, f->f, "");
2673e12c5d1SDavid du Colombier 	DEBUG(2, "\tremove: %s\n", path);
2683e12c5d1SDavid du Colombier 	if(remove(path) < 0) {
2693e12c5d1SDavid du Colombier 		errstr(err);
2703e12c5d1SDavid du Colombier 		reply(&r->work, &thdr, err);
2713e12c5d1SDavid du Colombier 		r->busy = 0;
2723e12c5d1SDavid du Colombier 		return;
2733e12c5d1SDavid du Colombier 	}
2743e12c5d1SDavid du Colombier 
2753e12c5d1SDavid du Colombier 	if(f->fid >= 0)
2763e12c5d1SDavid du Colombier 		close(f->fid);
2773e12c5d1SDavid du Colombier 	freefid(r->work.fid);
2783e12c5d1SDavid du Colombier 
2793e12c5d1SDavid du Colombier 	reply(&r->work, &thdr, 0);
2803e12c5d1SDavid du Colombier 	r->busy = 0;
2813e12c5d1SDavid du Colombier }
2823e12c5d1SDavid du Colombier 
2833e12c5d1SDavid du Colombier void
2843e12c5d1SDavid du Colombier Xwstat(Fsrpc *r)
2853e12c5d1SDavid du Colombier {
2863e12c5d1SDavid du Colombier 	char err[ERRLEN], path[128];
2873e12c5d1SDavid du Colombier 	Fcall thdr;
2883e12c5d1SDavid du Colombier 	Fid *f;
2893e12c5d1SDavid du Colombier 	int s;
2903e12c5d1SDavid du Colombier 
2913e12c5d1SDavid du Colombier 	f = getfid(r->work.fid);
2923e12c5d1SDavid du Colombier 	if(f == 0) {
2933e12c5d1SDavid du Colombier 		reply(&r->work, &thdr, e[Ebadfid]);
2943e12c5d1SDavid du Colombier 		r->busy = 0;
2953e12c5d1SDavid du Colombier 		return;
2963e12c5d1SDavid du Colombier 	}
2973e12c5d1SDavid du Colombier 	if(f->fid >= 0)
2983e12c5d1SDavid du Colombier 		s = fwstat(f->fid, r->work.stat);
2993e12c5d1SDavid du Colombier 	else {
3003e12c5d1SDavid du Colombier 		makepath(path, f->f, "");
3013e12c5d1SDavid du Colombier 		s = wstat(path, r->work.stat);
3023e12c5d1SDavid du Colombier 	}
3033e12c5d1SDavid du Colombier 	if(s < 0) {
3043e12c5d1SDavid du Colombier 		errstr(err);
3053e12c5d1SDavid du Colombier 		reply(&r->work, &thdr, err);
3063e12c5d1SDavid du Colombier 	}
307*219b2ee8SDavid du Colombier 	else {
308*219b2ee8SDavid du Colombier 		/* wstat may really be rename */
309*219b2ee8SDavid du Colombier 		strncpy(f->f->name, r->work.stat, NAMELEN);
3103e12c5d1SDavid du Colombier 		reply(&r->work, &thdr, 0);
311*219b2ee8SDavid du Colombier 	}
3123e12c5d1SDavid du Colombier 
3133e12c5d1SDavid du Colombier 	r->busy = 0;
3143e12c5d1SDavid du Colombier }
3153e12c5d1SDavid du Colombier 
3163e12c5d1SDavid du Colombier void
3173e12c5d1SDavid du Colombier Xclwalk(Fsrpc *r)
3183e12c5d1SDavid du Colombier {
3193e12c5d1SDavid du Colombier 	Fcall thdr;
320*219b2ee8SDavid du Colombier 	Fid *f, *n;
3213e12c5d1SDavid du Colombier 
322*219b2ee8SDavid du Colombier 	f = getfid(r->work.fid);
323*219b2ee8SDavid du Colombier 	if(f == 0) {
324*219b2ee8SDavid du Colombier 		reply(&r->work, &thdr, e[Ebadfid]);
3253e12c5d1SDavid du Colombier 		r->busy = 0;
326*219b2ee8SDavid du Colombier 		return;
327*219b2ee8SDavid du Colombier 	}
328*219b2ee8SDavid du Colombier 	n = newfid(r->work.newfid);
329*219b2ee8SDavid du Colombier 	if(n == 0) {
330*219b2ee8SDavid du Colombier 		reply(&r->work, &thdr, e[Edupfid]);
331*219b2ee8SDavid du Colombier 		r->busy = 0;
332*219b2ee8SDavid du Colombier 		return;
333*219b2ee8SDavid du Colombier 	}
334*219b2ee8SDavid du Colombier 	n->f = f->f;
335*219b2ee8SDavid du Colombier 	r->work.fid = r->work.newfid;
336*219b2ee8SDavid du Colombier 	Xwalk(r);
337*219b2ee8SDavid du Colombier }
338*219b2ee8SDavid du Colombier 
339*219b2ee8SDavid du Colombier int
340*219b2ee8SDavid du Colombier wrmount(Fsrpc *p)
341*219b2ee8SDavid du Colombier {
342*219b2ee8SDavid du Colombier 	Dir d;
343*219b2ee8SDavid du Colombier 	Fid *f;
344*219b2ee8SDavid du Colombier 	Fcall thdr, *work;
345*219b2ee8SDavid du Colombier 
346*219b2ee8SDavid du Colombier 	work = &p->work;
347*219b2ee8SDavid du Colombier 
348*219b2ee8SDavid du Colombier 	f = getfid(work->fid);
349*219b2ee8SDavid du Colombier 	if(f == 0)
350*219b2ee8SDavid du Colombier 		return 0;
351*219b2ee8SDavid du Colombier 	if(f->fid < 0)
352*219b2ee8SDavid du Colombier 		return 0;
353*219b2ee8SDavid du Colombier 	if(dirfstat(f->fid, &d) < 0)
354*219b2ee8SDavid du Colombier 		return 0;
355*219b2ee8SDavid du Colombier 	if((d.mode&CHMOUNT) == 0)
356*219b2ee8SDavid du Colombier 		return 0;
357*219b2ee8SDavid du Colombier 
358*219b2ee8SDavid du Colombier 	/* This may need to be a list matched by tag */
359*219b2ee8SDavid du Colombier 	if(f->mpend) {
360*219b2ee8SDavid du Colombier 		reply(work, &thdr, e[Emip]);
361*219b2ee8SDavid du Colombier 		p->busy = 0;
362*219b2ee8SDavid du Colombier 		return 1;
363*219b2ee8SDavid du Colombier 	}
364*219b2ee8SDavid du Colombier 
365*219b2ee8SDavid du Colombier 	f->mpend = p;
366*219b2ee8SDavid du Colombier 
367*219b2ee8SDavid du Colombier 	thdr.count = work->count;
368*219b2ee8SDavid du Colombier 	reply(work, &thdr, 0);
369*219b2ee8SDavid du Colombier 	return 1;
3703e12c5d1SDavid du Colombier }
3713e12c5d1SDavid du Colombier 
3723e12c5d1SDavid du Colombier void
3733e12c5d1SDavid du Colombier slave(Fsrpc *f)
3743e12c5d1SDavid du Colombier {
3753e12c5d1SDavid du Colombier 	Proc *p;
376*219b2ee8SDavid du Colombier 	int pid, n;
377*219b2ee8SDavid du Colombier 	Fcall mcall;
3783e12c5d1SDavid du Colombier 	static int nproc;
3793e12c5d1SDavid du Colombier 
380*219b2ee8SDavid du Colombier 	/*
381*219b2ee8SDavid du Colombier 	 * Look for a write to a message channel from the mount
382*219b2ee8SDavid du Colombier 	 * driver and attempt to multiplex to a local mount
383*219b2ee8SDavid du Colombier 	 */
384*219b2ee8SDavid du Colombier 	if(f->work.type == Twrite && f->work.data[0] == Tattach) {
385*219b2ee8SDavid du Colombier 		n = convM2S(f->work.data, &mcall, f->work.count);
386*219b2ee8SDavid du Colombier 		if(n != 0 && wrmount(f))
387*219b2ee8SDavid du Colombier 			return;
388*219b2ee8SDavid du Colombier 	}
389*219b2ee8SDavid du Colombier 
3903e12c5d1SDavid du Colombier 	for(;;) {
3913e12c5d1SDavid du Colombier 		for(p = Proclist; p; p = p->next) {
3923e12c5d1SDavid du Colombier 			if(p->busy == 0) {
3933e12c5d1SDavid du Colombier 				f->pid = p->pid;
3943e12c5d1SDavid du Colombier 				p->busy = 1;
3953e12c5d1SDavid du Colombier 				pid = rendezvous(p->pid, (ulong)f);
3963e12c5d1SDavid du Colombier 				if(pid != p->pid)
3973e12c5d1SDavid du Colombier 					fatal("rendezvous sync fail");
3983e12c5d1SDavid du Colombier 				return;
3993e12c5d1SDavid du Colombier 			}
4003e12c5d1SDavid du Colombier 		}
4013e12c5d1SDavid du Colombier 
4023e12c5d1SDavid du Colombier 		if(++nproc > MAXPROC)
4033e12c5d1SDavid du Colombier 			fatal("too many procs");
4043e12c5d1SDavid du Colombier 
4053e12c5d1SDavid du Colombier 		pid = rfork(RFPROC|RFMEM);
4063e12c5d1SDavid du Colombier 		switch(pid) {
4073e12c5d1SDavid du Colombier 		case -1:
4083e12c5d1SDavid du Colombier 			fatal("rfork");
4093e12c5d1SDavid du Colombier 
4103e12c5d1SDavid du Colombier 		case 0:
4113e12c5d1SDavid du Colombier 			blockingslave();
4123e12c5d1SDavid du Colombier 			fatal("slave");
4133e12c5d1SDavid du Colombier 
4143e12c5d1SDavid du Colombier 		default:
4153e12c5d1SDavid du Colombier 			p = malloc(sizeof(Proc));
4163e12c5d1SDavid du Colombier 			if(p == 0)
4173e12c5d1SDavid du Colombier 				fatal("out of memory");
4183e12c5d1SDavid du Colombier 
4193e12c5d1SDavid du Colombier 			p->busy = 0;
4203e12c5d1SDavid du Colombier 			p->pid = pid;
4213e12c5d1SDavid du Colombier 			p->next = Proclist;
4223e12c5d1SDavid du Colombier 			Proclist = p;
4233e12c5d1SDavid du Colombier 
4243e12c5d1SDavid du Colombier 			rendezvous(pid, (ulong)p);
4253e12c5d1SDavid du Colombier 		}
4263e12c5d1SDavid du Colombier 	}
4273e12c5d1SDavid du Colombier }
4283e12c5d1SDavid du Colombier 
4293e12c5d1SDavid du Colombier void
4303e12c5d1SDavid du Colombier blockingslave(void)
4313e12c5d1SDavid du Colombier {
4323e12c5d1SDavid du Colombier 	Fsrpc *p;
4333e12c5d1SDavid du Colombier 	Fcall thdr;
4343e12c5d1SDavid du Colombier 	Proc *m;
4353e12c5d1SDavid du Colombier 	int pid;
4363e12c5d1SDavid du Colombier 
4373e12c5d1SDavid du Colombier 	notify(flushaction);
4383e12c5d1SDavid du Colombier 
4393e12c5d1SDavid du Colombier 	pid = getpid();
4403e12c5d1SDavid du Colombier 
4413e12c5d1SDavid du Colombier 	m = (Proc*)rendezvous(pid, 0);
4423e12c5d1SDavid du Colombier 
4433e12c5d1SDavid du Colombier 	for(;;) {
4443e12c5d1SDavid du Colombier 		p = (Fsrpc*)rendezvous(pid, pid);
4453e12c5d1SDavid du Colombier 		if((int)p == ~0)			/* Interrupted */
4463e12c5d1SDavid du Colombier 			continue;
4473e12c5d1SDavid du Colombier 
4483e12c5d1SDavid du Colombier 		DEBUG(2, "\tslave: %d %F b %d p %d\n", pid, &p->work, p->busy, p->pid);
4493e12c5d1SDavid du Colombier 		if(p->flushtag != NOTAG)
4503e12c5d1SDavid du Colombier 			goto flushme;
4513e12c5d1SDavid du Colombier 
4523e12c5d1SDavid du Colombier 		switch(p->work.type) {
4533e12c5d1SDavid du Colombier 		case Tread:
4543e12c5d1SDavid du Colombier 			slaveread(p);
4553e12c5d1SDavid du Colombier 			break;
4563e12c5d1SDavid du Colombier 
4573e12c5d1SDavid du Colombier 		case Twrite:
4583e12c5d1SDavid du Colombier 			slavewrite(p);
4593e12c5d1SDavid du Colombier 			break;
4603e12c5d1SDavid du Colombier 
4613e12c5d1SDavid du Colombier 		case Topen:
4623e12c5d1SDavid du Colombier 			slaveopen(p);
4633e12c5d1SDavid du Colombier 			break;
4643e12c5d1SDavid du Colombier 
4653e12c5d1SDavid du Colombier 		default:
4663e12c5d1SDavid du Colombier 			reply(&p->work, &thdr, "exportfs: slave type error");
4673e12c5d1SDavid du Colombier 		}
4683e12c5d1SDavid du Colombier 		if(p->flushtag != NOTAG) {
4693e12c5d1SDavid du Colombier flushme:
4703e12c5d1SDavid du Colombier 			p->work.type = Tflush;
4713e12c5d1SDavid du Colombier 			p->work.tag = p->flushtag;
4723e12c5d1SDavid du Colombier 			reply(&p->work, &thdr, 0);
4733e12c5d1SDavid du Colombier 		}
4743e12c5d1SDavid du Colombier 		p->busy = 0;
4753e12c5d1SDavid du Colombier 		m->busy = 0;
4763e12c5d1SDavid du Colombier 	}
4773e12c5d1SDavid du Colombier }
4783e12c5d1SDavid du Colombier 
479*219b2ee8SDavid du Colombier File*
480*219b2ee8SDavid du Colombier mkmpt(char *buf, Fid *f)
481*219b2ee8SDavid du Colombier {
482*219b2ee8SDavid du Colombier 	int i;
483*219b2ee8SDavid du Colombier 	File *fl;
484*219b2ee8SDavid du Colombier 	char nr[10];
485*219b2ee8SDavid du Colombier 
486*219b2ee8SDavid du Colombier 	if(psmpt == 0)
487*219b2ee8SDavid du Colombier 		return 0;
488*219b2ee8SDavid du Colombier 
489*219b2ee8SDavid du Colombier 	for(i = 1; i < Npsmpt; i++)
490*219b2ee8SDavid du Colombier 		if(psmap[i] == 0)
491*219b2ee8SDavid du Colombier 			break;
492*219b2ee8SDavid du Colombier 
493*219b2ee8SDavid du Colombier 	if(i >= Npsmpt-1)
494*219b2ee8SDavid du Colombier 		return 0;
495*219b2ee8SDavid du Colombier 
496*219b2ee8SDavid du Colombier 	sprint(nr, "%d", i);
497*219b2ee8SDavid du Colombier 	fl = file(psmpt, nr);
498*219b2ee8SDavid du Colombier 	if(fl == 0)
499*219b2ee8SDavid du Colombier 		return 0;
500*219b2ee8SDavid du Colombier 
501*219b2ee8SDavid du Colombier 	sprint(buf, "/mnt/exportfs/%d", i);
502*219b2ee8SDavid du Colombier 	psmap[i] = 1;
503*219b2ee8SDavid du Colombier 	f->mid = i;
504*219b2ee8SDavid du Colombier 
505*219b2ee8SDavid du Colombier 	return fl;
506*219b2ee8SDavid du Colombier }
507*219b2ee8SDavid du Colombier 
508*219b2ee8SDavid du Colombier void
509*219b2ee8SDavid du Colombier rdmount(Fid *f, Fsrpc *p)
510*219b2ee8SDavid du Colombier {
511*219b2ee8SDavid du Colombier 	File *nf;
512*219b2ee8SDavid du Colombier 	int n, fd;
513*219b2ee8SDavid du Colombier 	Fid *mfid;
514*219b2ee8SDavid du Colombier 	Fsrpc *mp;
515*219b2ee8SDavid du Colombier 	char mpath[256];
516*219b2ee8SDavid du Colombier 	Fcall thdr, *work, mcall;
517*219b2ee8SDavid du Colombier 
518*219b2ee8SDavid du Colombier 	work = &p->work;
519*219b2ee8SDavid du Colombier 
520*219b2ee8SDavid du Colombier 	mp = f->mpend;
521*219b2ee8SDavid du Colombier 	convM2S(mp->work.data, &mcall, mp->work.count);
522*219b2ee8SDavid du Colombier 
523*219b2ee8SDavid du Colombier 	mfid = newfid(mcall.fid);
524*219b2ee8SDavid du Colombier 	if(mfid == 0) {
525*219b2ee8SDavid du Colombier 		mcall.type = Rerror;
526*219b2ee8SDavid du Colombier 		strcpy(mcall.ename, e[Ebadfid]);
527*219b2ee8SDavid du Colombier 		goto repl;
528*219b2ee8SDavid du Colombier 	}
529*219b2ee8SDavid du Colombier 
530*219b2ee8SDavid du Colombier 	nf = mkmpt(mpath, mfid);
531*219b2ee8SDavid du Colombier 	if(nf == 0) {
532*219b2ee8SDavid du Colombier 		mcall.type = Rerror;
533*219b2ee8SDavid du Colombier 		strcpy(mcall.ename, e[Enopsmt]);
534*219b2ee8SDavid du Colombier 		goto repl;
535*219b2ee8SDavid du Colombier 	}
536*219b2ee8SDavid du Colombier 
537*219b2ee8SDavid du Colombier 	fd = dup(f->fid, -1);
538*219b2ee8SDavid du Colombier 	p->canint = 1;
539*219b2ee8SDavid du Colombier 	n = amount(fd, mpath, MREPL, mcall.aname);
540*219b2ee8SDavid du Colombier 	p->canint = 0;
541*219b2ee8SDavid du Colombier 	if(n < 0) {
542*219b2ee8SDavid du Colombier 		close(fd);
543*219b2ee8SDavid du Colombier 		freefid(mcall.fid);
544*219b2ee8SDavid du Colombier 		mcall.type = Rerror;
545*219b2ee8SDavid du Colombier 		mcall.ename[0] = 0;
546*219b2ee8SDavid du Colombier 		errstr(mcall.ename);
547*219b2ee8SDavid du Colombier 	}
548*219b2ee8SDavid du Colombier 	else {
549*219b2ee8SDavid du Colombier 		mfid->f = nf;
550*219b2ee8SDavid du Colombier 		mcall.type = Rattach;
551*219b2ee8SDavid du Colombier 		mcall.qid = nf->qid;
552*219b2ee8SDavid du Colombier 		mcall.qid.path &= ~CHDIR;
553*219b2ee8SDavid du Colombier 	}
554*219b2ee8SDavid du Colombier repl:
555*219b2ee8SDavid du Colombier 	thdr.count = convS2M(&mcall, mp->buf);
556*219b2ee8SDavid du Colombier 	thdr.data = mp->buf;
557*219b2ee8SDavid du Colombier 	reply(work, &thdr, 0);
558*219b2ee8SDavid du Colombier 	mp->busy = 0;
559*219b2ee8SDavid du Colombier 	f->mpend = 0;
560*219b2ee8SDavid du Colombier }
561*219b2ee8SDavid du Colombier 
5623e12c5d1SDavid du Colombier void
5633e12c5d1SDavid du Colombier slaveopen(Fsrpc *p)
5643e12c5d1SDavid du Colombier {
5653e12c5d1SDavid du Colombier 	char err[ERRLEN], path[128];
5663e12c5d1SDavid du Colombier 	Fcall *work, thdr;
5673e12c5d1SDavid du Colombier 	Fid *f;
5683e12c5d1SDavid du Colombier 
5693e12c5d1SDavid du Colombier 	work = &p->work;
5703e12c5d1SDavid du Colombier 
5713e12c5d1SDavid du Colombier 	f = getfid(work->fid);
5723e12c5d1SDavid du Colombier 	if(f == 0) {
5733e12c5d1SDavid du Colombier 		reply(work, &thdr, e[Ebadfid]);
5743e12c5d1SDavid du Colombier 		return;
5753e12c5d1SDavid du Colombier 	}
5763e12c5d1SDavid du Colombier 	if(f->fid >= 0) {
5773e12c5d1SDavid du Colombier 		close(f->fid);
5783e12c5d1SDavid du Colombier 		f->fid = -1;
5793e12c5d1SDavid du Colombier 	}
5803e12c5d1SDavid du Colombier 
5813e12c5d1SDavid du Colombier 	makepath(path, f->f, "");
5823e12c5d1SDavid du Colombier 	DEBUG(2, "\topen: %s %d\n", path, work->mode);
5833e12c5d1SDavid du Colombier 
5843e12c5d1SDavid du Colombier 	p->canint = 1;
5853e12c5d1SDavid du Colombier 	if(p->flushtag != NOTAG)
5863e12c5d1SDavid du Colombier 		return;
5873e12c5d1SDavid du Colombier 	/* There is a race here I ignore because there are no locks */
5883e12c5d1SDavid du Colombier 	f->fid = open(path, work->mode);
5893e12c5d1SDavid du Colombier 	p->canint = 0;
5903e12c5d1SDavid du Colombier 	if(f->fid < 0) {
5913e12c5d1SDavid du Colombier 		errstr(err);
5923e12c5d1SDavid du Colombier 		reply(work, &thdr, err);
5933e12c5d1SDavid du Colombier 		return;
5943e12c5d1SDavid du Colombier 	}
5953e12c5d1SDavid du Colombier 
5963e12c5d1SDavid du Colombier 	DEBUG(2, "\topen: fd %d\n", f->fid);
5973e12c5d1SDavid du Colombier 	f->mode = work->mode;
5983e12c5d1SDavid du Colombier 	f->offset = 0;
5993e12c5d1SDavid du Colombier 	thdr.qid = f->f->qid;
6003e12c5d1SDavid du Colombier 	reply(work, &thdr, 0);
6013e12c5d1SDavid du Colombier }
6023e12c5d1SDavid du Colombier 
6033e12c5d1SDavid du Colombier void
6043e12c5d1SDavid du Colombier slaveread(Fsrpc *p)
6053e12c5d1SDavid du Colombier {
6063e12c5d1SDavid du Colombier 	Fid *f;
6073e12c5d1SDavid du Colombier 	int n, r;
608*219b2ee8SDavid du Colombier 	Fcall *work, thdr;
609*219b2ee8SDavid du Colombier 	char data[MAXFDATA], err[ERRLEN];
6103e12c5d1SDavid du Colombier 
6113e12c5d1SDavid du Colombier 	work = &p->work;
6123e12c5d1SDavid du Colombier 
6133e12c5d1SDavid du Colombier 	f = getfid(work->fid);
6143e12c5d1SDavid du Colombier 	if(f == 0) {
6153e12c5d1SDavid du Colombier 		reply(work, &thdr, e[Ebadfid]);
6163e12c5d1SDavid du Colombier 		return;
6173e12c5d1SDavid du Colombier 	}
6183e12c5d1SDavid du Colombier 
619*219b2ee8SDavid du Colombier 	/* Do the work half of a split transaction mount */
620*219b2ee8SDavid du Colombier 	if(f->mpend) {
621*219b2ee8SDavid du Colombier 		rdmount(f, p);
622*219b2ee8SDavid du Colombier 		return;
623*219b2ee8SDavid du Colombier 	}
624*219b2ee8SDavid du Colombier 
6253e12c5d1SDavid du Colombier 	if(work->offset != f->offset)
6263e12c5d1SDavid du Colombier 		fileseek(f, work->offset);
6273e12c5d1SDavid du Colombier 
6283e12c5d1SDavid du Colombier 	n = (work->count > MAXFDATA) ? MAXFDATA : work->count;
6293e12c5d1SDavid du Colombier 	p->canint = 1;
6303e12c5d1SDavid du Colombier 	if(p->flushtag != NOTAG)
6313e12c5d1SDavid du Colombier 		return;
6323e12c5d1SDavid du Colombier 	r = read(f->fid, data, n);
6333e12c5d1SDavid du Colombier 	p->canint = 0;
6343e12c5d1SDavid du Colombier 	if(r < 0) {
6353e12c5d1SDavid du Colombier 		errstr(err);
6363e12c5d1SDavid du Colombier 		reply(work, &thdr, err);
6373e12c5d1SDavid du Colombier 		return;
6383e12c5d1SDavid du Colombier 	}
6393e12c5d1SDavid du Colombier 
6403e12c5d1SDavid du Colombier 	DEBUG(2, "\tread: fd=%d %d bytes\n", f->fid, r);
6413e12c5d1SDavid du Colombier 
6423e12c5d1SDavid du Colombier 	f->offset += r;
6433e12c5d1SDavid du Colombier 	thdr.data = data;
6443e12c5d1SDavid du Colombier 	thdr.count = r;
6453e12c5d1SDavid du Colombier 	reply(work, &thdr, 0);
6463e12c5d1SDavid du Colombier }
6473e12c5d1SDavid du Colombier 
6483e12c5d1SDavid du Colombier void
6493e12c5d1SDavid du Colombier slavewrite(Fsrpc *p)
6503e12c5d1SDavid du Colombier {
6513e12c5d1SDavid du Colombier 	char err[ERRLEN];
6523e12c5d1SDavid du Colombier 	Fcall *work, thdr;
6533e12c5d1SDavid du Colombier 	Fid *f;
6543e12c5d1SDavid du Colombier 	int n;
6553e12c5d1SDavid du Colombier 
6563e12c5d1SDavid du Colombier 	work = &p->work;
6573e12c5d1SDavid du Colombier 
6583e12c5d1SDavid du Colombier 	f = getfid(work->fid);
6593e12c5d1SDavid du Colombier 	if(f == 0) {
6603e12c5d1SDavid du Colombier 		reply(work, &thdr, e[Ebadfid]);
6613e12c5d1SDavid du Colombier 		return;
6623e12c5d1SDavid du Colombier 	}
6633e12c5d1SDavid du Colombier 
6643e12c5d1SDavid du Colombier 	if(work->offset != f->offset)
6653e12c5d1SDavid du Colombier 		fileseek(f, work->offset);
6663e12c5d1SDavid du Colombier 
6673e12c5d1SDavid du Colombier 	n = (work->count > MAXFDATA) ? MAXFDATA : work->count;
6683e12c5d1SDavid du Colombier 	p->canint = 1;
6693e12c5d1SDavid du Colombier 	if(p->flushtag != NOTAG)
6703e12c5d1SDavid du Colombier 		return;
6713e12c5d1SDavid du Colombier 	n = write(f->fid, work->data, n);
6723e12c5d1SDavid du Colombier 	p->canint = 0;
6733e12c5d1SDavid du Colombier 	if(n < 0) {
6743e12c5d1SDavid du Colombier 		errstr(err);
6753e12c5d1SDavid du Colombier 		reply(work, &thdr, err);
6763e12c5d1SDavid du Colombier 		return;
6773e12c5d1SDavid du Colombier 	}
6783e12c5d1SDavid du Colombier 
6793e12c5d1SDavid du Colombier 	DEBUG(2, "\twrite: %d bytes fd=%d\n", n, f->fid);
6803e12c5d1SDavid du Colombier 
6813e12c5d1SDavid du Colombier 	f->offset += n;
6823e12c5d1SDavid du Colombier 	thdr.count = n;
6833e12c5d1SDavid du Colombier 	reply(work, &thdr, 0);
6843e12c5d1SDavid du Colombier }
6853e12c5d1SDavid du Colombier 
6863e12c5d1SDavid du Colombier void
6873e12c5d1SDavid du Colombier fileseek(Fid *f, ulong offset)
6883e12c5d1SDavid du Colombier {
6893e12c5d1SDavid du Colombier 	char chunk[DIRCHUNK];
6903e12c5d1SDavid du Colombier 	int n, nbytes, r;
6913e12c5d1SDavid du Colombier 
6923e12c5d1SDavid du Colombier 	if(f->f->qid.path&CHDIR) {
6933e12c5d1SDavid du Colombier 		if(offset < f->offset)
6943e12c5d1SDavid du Colombier 			reopen(f);
6953e12c5d1SDavid du Colombier 
6963e12c5d1SDavid du Colombier 		for(nbytes = offset - f->offset; nbytes; nbytes -= r) {
6973e12c5d1SDavid du Colombier 			n = (nbytes > DIRCHUNK) ? DIRCHUNK : nbytes;
6983e12c5d1SDavid du Colombier 			r = read(f->fid, chunk, n);
6993e12c5d1SDavid du Colombier 			if(r <= 0) {
7003e12c5d1SDavid du Colombier 				DEBUG(2,"\tdir seek error\n");
7013e12c5d1SDavid du Colombier 				return;
7023e12c5d1SDavid du Colombier 			}
7033e12c5d1SDavid du Colombier 			f->offset += r;
7043e12c5d1SDavid du Colombier 		}
7053e12c5d1SDavid du Colombier 	}
7063e12c5d1SDavid du Colombier 	else
7073e12c5d1SDavid du Colombier 		f->offset = seek(f->fid, offset, 0);
7083e12c5d1SDavid du Colombier }
7093e12c5d1SDavid du Colombier 
7103e12c5d1SDavid du Colombier void
7113e12c5d1SDavid du Colombier reopen(Fid *f)
7123e12c5d1SDavid du Colombier {
7133e12c5d1SDavid du Colombier 	USED(f);
7143e12c5d1SDavid du Colombier 	fatal("reopen");
7153e12c5d1SDavid du Colombier }
7163e12c5d1SDavid du Colombier 
7173e12c5d1SDavid du Colombier void
7183e12c5d1SDavid du Colombier flushaction(void *a, char *cause)
7193e12c5d1SDavid du Colombier {
7203e12c5d1SDavid du Colombier 	USED(a);
7213e12c5d1SDavid du Colombier 	if(strncmp(cause, "sys:", 4) == 0 && !strstr(cause, "pipe")) {
7223e12c5d1SDavid du Colombier 		fprint(2, "exportsrv: note: %s\n", cause);
7233e12c5d1SDavid du Colombier 		exits("noted");
7243e12c5d1SDavid du Colombier 	}
7253e12c5d1SDavid du Colombier 	if(strncmp(cause, "kill", 4) == 0)
7263e12c5d1SDavid du Colombier 		noted(NDFLT);
7273e12c5d1SDavid du Colombier 
7283e12c5d1SDavid du Colombier 	noted(NCONT);
7293e12c5d1SDavid du Colombier }
730