xref: /plan9/sys/src/cmd/iostats/statsrv.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 "statfs.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",
163e12c5d1SDavid du Colombier };
173e12c5d1SDavid du Colombier 
183e12c5d1SDavid du Colombier void
193e12c5d1SDavid du Colombier Xnop(Fsrpc *r)
203e12c5d1SDavid du Colombier {
213e12c5d1SDavid du Colombier 	Fcall thdr;
223e12c5d1SDavid du Colombier 
233e12c5d1SDavid du Colombier 	reply(&r->work, &thdr, 0);
243e12c5d1SDavid du Colombier 	r->busy = 0;
253e12c5d1SDavid du Colombier }
263e12c5d1SDavid du Colombier 
273e12c5d1SDavid du Colombier void
283e12c5d1SDavid du Colombier Xsession(Fsrpc *r)
293e12c5d1SDavid du Colombier {
303e12c5d1SDavid du Colombier 	Fcall thdr;
313e12c5d1SDavid du Colombier 
32*219b2ee8SDavid du Colombier 	memset(thdr.authid, 0, sizeof(thdr.authid));
33*219b2ee8SDavid du Colombier 	memset(thdr.authdom, 0, sizeof(thdr.authdom));
34*219b2ee8SDavid du Colombier 	memset(thdr.chal, 0, sizeof(thdr.chal));
353e12c5d1SDavid du Colombier 	reply(&r->work, &thdr, 0);
363e12c5d1SDavid du Colombier 	r->busy = 0;
373e12c5d1SDavid du Colombier }
383e12c5d1SDavid du Colombier 
393e12c5d1SDavid du Colombier void
403e12c5d1SDavid du Colombier Xflush(Fsrpc *r)
413e12c5d1SDavid du Colombier {
423e12c5d1SDavid du Colombier 	Fsrpc *t, *e;
433e12c5d1SDavid du Colombier 	Fcall thdr;
443e12c5d1SDavid du Colombier 
453e12c5d1SDavid du Colombier 	e = &Workq[Nr_workbufs];
463e12c5d1SDavid du Colombier 
473e12c5d1SDavid du Colombier 	for(t = Workq; t < e; t++) {
483e12c5d1SDavid du Colombier 		if(t->work.tag == r->work.oldtag) {
493e12c5d1SDavid du Colombier 			DEBUG(2, "\tQ busy %d pid %d can %d\n", t->busy, t->pid, t->canint);
503e12c5d1SDavid du Colombier 			if(t->busy && t->pid) {
513e12c5d1SDavid du Colombier 				t->flushtag = r->work.tag;
523e12c5d1SDavid du Colombier 				DEBUG(2, "\tset flushtag %d\n", r->work.tag);
533e12c5d1SDavid du Colombier 				if(t->canint)
54*219b2ee8SDavid du Colombier 					postnote(PNPROC, t->pid, "flush");
553e12c5d1SDavid du Colombier 				r->busy = 0;
563e12c5d1SDavid du Colombier 				return;
573e12c5d1SDavid du Colombier 			}
583e12c5d1SDavid du Colombier 		}
593e12c5d1SDavid du Colombier 	}
603e12c5d1SDavid du Colombier 
613e12c5d1SDavid du Colombier 	reply(&r->work, &thdr, 0);
623e12c5d1SDavid du Colombier 	DEBUG(2, "\tflush reply\n");
633e12c5d1SDavid du Colombier 	r->busy = 0;
643e12c5d1SDavid du Colombier }
653e12c5d1SDavid du Colombier 
663e12c5d1SDavid du Colombier void
673e12c5d1SDavid du Colombier Xattach(Fsrpc *r)
683e12c5d1SDavid du Colombier {
693e12c5d1SDavid du Colombier 	Fcall thdr;
703e12c5d1SDavid du Colombier 	Fid *f;
713e12c5d1SDavid du Colombier 	Rpc *rpc;
723e12c5d1SDavid du Colombier 	ulong t;
733e12c5d1SDavid du Colombier 
743e12c5d1SDavid du Colombier 	t = msec();
753e12c5d1SDavid du Colombier 
763e12c5d1SDavid du Colombier 	f = newfid(r->work.fid);
773e12c5d1SDavid du Colombier 	if(f == 0) {
783e12c5d1SDavid du Colombier 		reply(&r->work, &thdr, e[Ebadfid]);
793e12c5d1SDavid du Colombier 		r->busy = 0;
803e12c5d1SDavid du Colombier 		return;
813e12c5d1SDavid du Colombier 	}
823e12c5d1SDavid du Colombier 
833e12c5d1SDavid du Colombier 	f->f = root;
843e12c5d1SDavid du Colombier 	thdr.qid = f->f->qid;
853e12c5d1SDavid du Colombier 	reply(&r->work, &thdr, 0);
863e12c5d1SDavid du Colombier 	r->busy = 0;
873e12c5d1SDavid du Colombier 
883e12c5d1SDavid du Colombier 	t = msec()-t;
893e12c5d1SDavid du Colombier 	rpc = &stats->rpc[Tattach];
903e12c5d1SDavid du Colombier 	rpc->time += t;
913e12c5d1SDavid du Colombier 	if(t < rpc->loms)
923e12c5d1SDavid du Colombier 		rpc->loms = t;
933e12c5d1SDavid du Colombier 	if(t > rpc->hims)
943e12c5d1SDavid du Colombier 		rpc->hims = t;
953e12c5d1SDavid du Colombier }
963e12c5d1SDavid du Colombier 
973e12c5d1SDavid du Colombier void
983e12c5d1SDavid du Colombier Xclone(Fsrpc *r)
993e12c5d1SDavid du Colombier {
1003e12c5d1SDavid du Colombier 	Fcall thdr;
1013e12c5d1SDavid du Colombier 	Fid *f, *n;
1023e12c5d1SDavid du Colombier 	ulong t;
1033e12c5d1SDavid du Colombier 	Rpc *rpc;
1043e12c5d1SDavid du Colombier 
1053e12c5d1SDavid du Colombier 	t = msec();
1063e12c5d1SDavid du Colombier 
1073e12c5d1SDavid du Colombier 	f = getfid(r->work.fid);
1083e12c5d1SDavid du Colombier 	if(f == 0) {
1093e12c5d1SDavid du Colombier 		reply(&r->work, &thdr, e[Ebadfid]);
1103e12c5d1SDavid du Colombier 		r->busy = 0;
1113e12c5d1SDavid du Colombier 		return;
1123e12c5d1SDavid du Colombier 	}
1133e12c5d1SDavid du Colombier 	n = newfid(r->work.newfid);
1143e12c5d1SDavid du Colombier 	if(n == 0) {
1153e12c5d1SDavid du Colombier 		reply(&r->work, &thdr, e[Edupfid]);
1163e12c5d1SDavid du Colombier 		r->busy = 0;
1173e12c5d1SDavid du Colombier 		return;
1183e12c5d1SDavid du Colombier 	}
1193e12c5d1SDavid du Colombier 	n->f = f->f;
1203e12c5d1SDavid du Colombier 	reply(&r->work, &thdr, 0);
1213e12c5d1SDavid du Colombier 	r->busy = 0;
1223e12c5d1SDavid du Colombier 
1233e12c5d1SDavid du Colombier 	t = msec()-t;
1243e12c5d1SDavid du Colombier 	rpc = &stats->rpc[Tclone];
1253e12c5d1SDavid du Colombier 	rpc->time += t;
1263e12c5d1SDavid du Colombier 	if(t < rpc->loms)
1273e12c5d1SDavid du Colombier 		rpc->loms = t;
1283e12c5d1SDavid du Colombier 	if(t > rpc->hims)
1293e12c5d1SDavid du Colombier 		rpc->hims = t;
1303e12c5d1SDavid du Colombier }
1313e12c5d1SDavid du Colombier 
1323e12c5d1SDavid du Colombier void
1333e12c5d1SDavid du Colombier Xwalk(Fsrpc *r)
1343e12c5d1SDavid du Colombier {
1353e12c5d1SDavid du Colombier 	char err[ERRLEN];
1363e12c5d1SDavid du Colombier 	Fcall thdr;
1373e12c5d1SDavid du Colombier 	Fid *f;
1383e12c5d1SDavid du Colombier 	File *nf;
1393e12c5d1SDavid du Colombier 	Rpc *rpc;
1403e12c5d1SDavid du Colombier 	ulong t;
1413e12c5d1SDavid du Colombier 
1423e12c5d1SDavid du Colombier 	t = msec();
1433e12c5d1SDavid du Colombier 
1443e12c5d1SDavid du Colombier 	f = getfid(r->work.fid);
1453e12c5d1SDavid du Colombier 	if(f == 0) {
1463e12c5d1SDavid du Colombier 		reply(&r->work, &thdr, e[Ebadfid]);
1473e12c5d1SDavid du Colombier 		r->busy = 0;
1483e12c5d1SDavid du Colombier 		return;
1493e12c5d1SDavid du Colombier 	}
1503e12c5d1SDavid du Colombier 
1513e12c5d1SDavid du Colombier 	if(strcmp(r->work.name, "..") == 0) {
1523e12c5d1SDavid du Colombier 		if(f->f->parent == 0) {
1533e12c5d1SDavid du Colombier 			reply(&r->work, &thdr, e[Exmnt]);
1543e12c5d1SDavid du Colombier 			r->busy = 0;
1553e12c5d1SDavid du Colombier 			return;
1563e12c5d1SDavid du Colombier 		}
1573e12c5d1SDavid du Colombier 		f->f = f->f->parent;
1583e12c5d1SDavid du Colombier 		thdr.qid = f->f->qid;
1593e12c5d1SDavid du Colombier 		reply(&r->work, &thdr, 0);
1603e12c5d1SDavid du Colombier 		r->busy = 0;
1613e12c5d1SDavid du Colombier 		return;
1623e12c5d1SDavid du Colombier 	}
1633e12c5d1SDavid du Colombier 
1643e12c5d1SDavid du Colombier 	nf = file(f->f, r->work.name);
1653e12c5d1SDavid du Colombier 	if(nf == 0) {
1663e12c5d1SDavid du Colombier 		errstr(err);
1673e12c5d1SDavid du Colombier 		reply(&r->work, &thdr, err);
1683e12c5d1SDavid du Colombier 		r->busy = 0;
1693e12c5d1SDavid du Colombier 		return;
1703e12c5d1SDavid du Colombier 	}
1713e12c5d1SDavid du Colombier 
1723e12c5d1SDavid du Colombier 	f->f = nf;
1733e12c5d1SDavid du Colombier 	thdr.qid = nf->qid;
1743e12c5d1SDavid du Colombier 	reply(&r->work, &thdr, 0);
1753e12c5d1SDavid du Colombier 	r->busy = 0;
1763e12c5d1SDavid du Colombier 
1773e12c5d1SDavid du Colombier 	t = msec()-t;
1783e12c5d1SDavid du Colombier 	rpc = &stats->rpc[Twalk];
1793e12c5d1SDavid du Colombier 	rpc->time += t;
1803e12c5d1SDavid du Colombier 	if(t < rpc->loms)
1813e12c5d1SDavid du Colombier 		rpc->loms = t;
1823e12c5d1SDavid du Colombier 	if(t > rpc->hims)
1833e12c5d1SDavid du Colombier 		rpc->hims = t;
1843e12c5d1SDavid du Colombier }
1853e12c5d1SDavid du Colombier 
1863e12c5d1SDavid du Colombier void
1873e12c5d1SDavid du Colombier Xclunk(Fsrpc *r)
1883e12c5d1SDavid du Colombier {
1893e12c5d1SDavid du Colombier 	Fcall thdr;
1903e12c5d1SDavid du Colombier 	Fid *f;
1913e12c5d1SDavid du Colombier 	Rpc *rpc;
1923e12c5d1SDavid du Colombier 	ulong t;
1933e12c5d1SDavid du Colombier 	int fid;
1943e12c5d1SDavid du Colombier 
1953e12c5d1SDavid du Colombier 	t = msec();
1963e12c5d1SDavid du Colombier 
1973e12c5d1SDavid du Colombier 	f = getfid(r->work.fid);
1983e12c5d1SDavid du Colombier 	if(f == 0) {
1993e12c5d1SDavid du Colombier 		reply(&r->work, &thdr, e[Ebadfid]);
2003e12c5d1SDavid du Colombier 		r->busy = 0;
2013e12c5d1SDavid du Colombier 		return;
2023e12c5d1SDavid du Colombier 	}
2033e12c5d1SDavid du Colombier 
2043e12c5d1SDavid du Colombier 	if(f->fid >= 0)
2053e12c5d1SDavid du Colombier 		close(f->fid);
2063e12c5d1SDavid du Colombier 
2073e12c5d1SDavid du Colombier 	fid = r->work.fid;
2083e12c5d1SDavid du Colombier 	reply(&r->work, &thdr, 0);
2093e12c5d1SDavid du Colombier 	r->busy = 0;
2103e12c5d1SDavid du Colombier 
2113e12c5d1SDavid du Colombier 	t = msec()-t;
2123e12c5d1SDavid du Colombier 	rpc = &stats->rpc[Tclunk];
2133e12c5d1SDavid du Colombier 	rpc->time += t;
2143e12c5d1SDavid du Colombier 	if(t < rpc->loms)
2153e12c5d1SDavid du Colombier 		rpc->loms = t;
2163e12c5d1SDavid du Colombier 	if(t > rpc->hims)
2173e12c5d1SDavid du Colombier 		rpc->hims = t;
2183e12c5d1SDavid du Colombier 
2193e12c5d1SDavid du Colombier 	if(f->nread || f->nwrite)
2203e12c5d1SDavid du Colombier 		fidreport(f);
2213e12c5d1SDavid du Colombier 
2223e12c5d1SDavid du Colombier 	freefid(fid);
2233e12c5d1SDavid du Colombier }
2243e12c5d1SDavid du Colombier 
2253e12c5d1SDavid du Colombier void
2263e12c5d1SDavid du Colombier Xstat(Fsrpc *r)
2273e12c5d1SDavid du Colombier {
2283e12c5d1SDavid du Colombier 	char err[ERRLEN], path[128];
2293e12c5d1SDavid du Colombier 	Fcall thdr;
2303e12c5d1SDavid du Colombier 	Fid *f;
2313e12c5d1SDavid du Colombier 	int s;
2323e12c5d1SDavid du Colombier 	Rpc *rpc;
2333e12c5d1SDavid du Colombier 	ulong t;
2343e12c5d1SDavid du Colombier 
2353e12c5d1SDavid du Colombier 	t = msec();
2363e12c5d1SDavid du Colombier 
2373e12c5d1SDavid du Colombier 	f = getfid(r->work.fid);
2383e12c5d1SDavid du Colombier 	if(f == 0) {
2393e12c5d1SDavid du Colombier 		reply(&r->work, &thdr, e[Ebadfid]);
2403e12c5d1SDavid du Colombier 		r->busy = 0;
2413e12c5d1SDavid du Colombier 		return;
2423e12c5d1SDavid du Colombier 	}
2433e12c5d1SDavid du Colombier 	if(f->fid >= 0)
2443e12c5d1SDavid du Colombier 		s = fstat(f->fid, thdr.stat);
2453e12c5d1SDavid du Colombier 	else {
2463e12c5d1SDavid du Colombier 		makepath(path, f->f, "");
2473e12c5d1SDavid du Colombier 		s = stat(path, thdr.stat);
2483e12c5d1SDavid du Colombier 	}
2493e12c5d1SDavid du Colombier 
2503e12c5d1SDavid du Colombier 	if(s < 0) {
2513e12c5d1SDavid du Colombier 		errstr(err);
2523e12c5d1SDavid du Colombier 		reply(&r->work, &thdr, err);
2533e12c5d1SDavid du Colombier 		r->busy = 0;
2543e12c5d1SDavid du Colombier 		return;
2553e12c5d1SDavid du Colombier 	}
2563e12c5d1SDavid du Colombier 	reply(&r->work, &thdr, 0);
2573e12c5d1SDavid du Colombier 	r->busy = 0;
2583e12c5d1SDavid du Colombier 
2593e12c5d1SDavid du Colombier 	t = msec()-t;
2603e12c5d1SDavid du Colombier 	rpc = &stats->rpc[Tstat];
2613e12c5d1SDavid du Colombier 	rpc->time += t;
2623e12c5d1SDavid du Colombier 	if(t < rpc->loms)
2633e12c5d1SDavid du Colombier 		rpc->loms = t;
2643e12c5d1SDavid du Colombier 	if(t > rpc->hims)
2653e12c5d1SDavid du Colombier 		rpc->hims = t;
2663e12c5d1SDavid du Colombier }
2673e12c5d1SDavid du Colombier 
2683e12c5d1SDavid du Colombier void
2693e12c5d1SDavid du Colombier Xcreate(Fsrpc *r)
2703e12c5d1SDavid du Colombier {
2713e12c5d1SDavid du Colombier 	char err[ERRLEN], path[128];
2723e12c5d1SDavid du Colombier 	Fcall thdr;
2733e12c5d1SDavid du Colombier 	Fid *f;
2743e12c5d1SDavid du Colombier 	File *nf;
2753e12c5d1SDavid du Colombier 	Rpc *rpc;
2763e12c5d1SDavid du Colombier 	ulong t;
2773e12c5d1SDavid du Colombier 
2783e12c5d1SDavid du Colombier 	t = msec();
2793e12c5d1SDavid du Colombier 
2803e12c5d1SDavid du Colombier 	f = getfid(r->work.fid);
2813e12c5d1SDavid du Colombier 	if(f == 0) {
2823e12c5d1SDavid du Colombier 		reply(&r->work, &thdr, e[Ebadfid]);
2833e12c5d1SDavid du Colombier 		r->busy = 0;
2843e12c5d1SDavid du Colombier 		return;
2853e12c5d1SDavid du Colombier 	}
2863e12c5d1SDavid du Colombier 
2873e12c5d1SDavid du Colombier 
2883e12c5d1SDavid du Colombier 	makepath(path, f->f, r->work.name);
2893e12c5d1SDavid du Colombier 	f->fid = create(path, r->work.mode, r->work.perm);
2903e12c5d1SDavid du Colombier 	if(f->fid < 0) {
2913e12c5d1SDavid du Colombier 		errstr(err);
2923e12c5d1SDavid du Colombier 		reply(&r->work, &thdr, err);
2933e12c5d1SDavid du Colombier 		r->busy = 0;
2943e12c5d1SDavid du Colombier 		return;
2953e12c5d1SDavid du Colombier 	}
2963e12c5d1SDavid du Colombier 
2973e12c5d1SDavid du Colombier 	nf = file(f->f, r->work.name);
2983e12c5d1SDavid du Colombier 	if(nf == 0) {
2993e12c5d1SDavid du Colombier 		errstr(err);
3003e12c5d1SDavid du Colombier 		reply(&r->work, &thdr, err);
3013e12c5d1SDavid du Colombier 		r->busy = 0;
3023e12c5d1SDavid du Colombier 		return;
3033e12c5d1SDavid du Colombier 	}
3043e12c5d1SDavid du Colombier 
3053e12c5d1SDavid du Colombier 	f->mode = r->work.mode;
3063e12c5d1SDavid du Colombier 	f->f = nf;
3073e12c5d1SDavid du Colombier 	f->offset = 0;
3083e12c5d1SDavid du Colombier 	thdr.qid = f->f->qid;
3093e12c5d1SDavid du Colombier 	reply(&r->work, &thdr, 0);
3103e12c5d1SDavid du Colombier 	r->busy = 0;
3113e12c5d1SDavid du Colombier 
3123e12c5d1SDavid du Colombier 	t = msec()-t;
3133e12c5d1SDavid du Colombier 	rpc = &stats->rpc[Tcreate];
3143e12c5d1SDavid du Colombier 	rpc->time += t;
3153e12c5d1SDavid du Colombier 	if(t < rpc->loms)
3163e12c5d1SDavid du Colombier 		rpc->loms = t;
3173e12c5d1SDavid du Colombier 	if(t > rpc->hims)
3183e12c5d1SDavid du Colombier 		rpc->hims = t;
3193e12c5d1SDavid du Colombier }
3203e12c5d1SDavid du Colombier 
3213e12c5d1SDavid du Colombier 
3223e12c5d1SDavid du Colombier void
3233e12c5d1SDavid du Colombier Xremove(Fsrpc *r)
3243e12c5d1SDavid du Colombier {
3253e12c5d1SDavid du Colombier 	char err[ERRLEN], path[128];
3263e12c5d1SDavid du Colombier 	Fcall thdr;
3273e12c5d1SDavid du Colombier 	Fid *f;
3283e12c5d1SDavid du Colombier 	ulong t;
3293e12c5d1SDavid du Colombier 	Rpc *rpc;
3303e12c5d1SDavid du Colombier 
3313e12c5d1SDavid du Colombier 	t = msec();
3323e12c5d1SDavid du Colombier 
3333e12c5d1SDavid du Colombier 	f = getfid(r->work.fid);
3343e12c5d1SDavid du Colombier 	if(f == 0) {
3353e12c5d1SDavid du Colombier 		reply(&r->work, &thdr, e[Ebadfid]);
3363e12c5d1SDavid du Colombier 		r->busy = 0;
3373e12c5d1SDavid du Colombier 		return;
3383e12c5d1SDavid du Colombier 	}
3393e12c5d1SDavid du Colombier 
3403e12c5d1SDavid du Colombier 	makepath(path, f->f, "");
3413e12c5d1SDavid du Colombier 	DEBUG(2, "\tremove: %s\n", path);
3423e12c5d1SDavid du Colombier 	if(remove(path) < 0) {
3433e12c5d1SDavid du Colombier 		errstr(err);
3443e12c5d1SDavid du Colombier 		reply(&r->work, &thdr, err);
345*219b2ee8SDavid du Colombier 		freefid(r->work.fid);
3463e12c5d1SDavid du Colombier 		r->busy = 0;
3473e12c5d1SDavid du Colombier 		return;
3483e12c5d1SDavid du Colombier 	}
3493e12c5d1SDavid du Colombier 
3503e12c5d1SDavid du Colombier 	if(f->fid >= 0)
3513e12c5d1SDavid du Colombier 		close(f->fid);
3523e12c5d1SDavid du Colombier 	freefid(r->work.fid);
3533e12c5d1SDavid du Colombier 
3543e12c5d1SDavid du Colombier 	reply(&r->work, &thdr, 0);
3553e12c5d1SDavid du Colombier 	r->busy = 0;
3563e12c5d1SDavid du Colombier 
3573e12c5d1SDavid du Colombier 	t = msec()-t;
3583e12c5d1SDavid du Colombier 	rpc = &stats->rpc[Tremove];
3593e12c5d1SDavid du Colombier 	rpc->time += t;
3603e12c5d1SDavid du Colombier 	if(t < rpc->loms)
3613e12c5d1SDavid du Colombier 		rpc->loms = t;
3623e12c5d1SDavid du Colombier 	if(t > rpc->hims)
3633e12c5d1SDavid du Colombier 		rpc->hims = t;
3643e12c5d1SDavid du Colombier }
3653e12c5d1SDavid du Colombier 
3663e12c5d1SDavid du Colombier void
3673e12c5d1SDavid du Colombier Xwstat(Fsrpc *r)
3683e12c5d1SDavid du Colombier {
3693e12c5d1SDavid du Colombier 	char err[ERRLEN], path[128];
3703e12c5d1SDavid du Colombier 	Fcall thdr;
3713e12c5d1SDavid du Colombier 	Fid *f;
3723e12c5d1SDavid du Colombier 	int s;
3733e12c5d1SDavid du Colombier 	ulong t;
3743e12c5d1SDavid du Colombier 	Rpc *rpc;
3753e12c5d1SDavid du Colombier 
3763e12c5d1SDavid du Colombier 	t = msec();
3773e12c5d1SDavid du Colombier 
3783e12c5d1SDavid du Colombier 	f = getfid(r->work.fid);
3793e12c5d1SDavid du Colombier 	if(f == 0) {
3803e12c5d1SDavid du Colombier 		reply(&r->work, &thdr, e[Ebadfid]);
3813e12c5d1SDavid du Colombier 		r->busy = 0;
3823e12c5d1SDavid du Colombier 		return;
3833e12c5d1SDavid du Colombier 	}
3843e12c5d1SDavid du Colombier 	if(f->fid >= 0)
3853e12c5d1SDavid du Colombier 		s = fwstat(f->fid, r->work.stat);
3863e12c5d1SDavid du Colombier 	else {
3873e12c5d1SDavid du Colombier 		makepath(path, f->f, "");
3883e12c5d1SDavid du Colombier 		s = wstat(path, r->work.stat);
3893e12c5d1SDavid du Colombier 	}
3903e12c5d1SDavid du Colombier 	if(s < 0) {
3913e12c5d1SDavid du Colombier 		errstr(err);
3923e12c5d1SDavid du Colombier 		reply(&r->work, &thdr, err);
3933e12c5d1SDavid du Colombier 	}
3943e12c5d1SDavid du Colombier 	else
3953e12c5d1SDavid du Colombier 		reply(&r->work, &thdr, 0);
3963e12c5d1SDavid du Colombier 
3973e12c5d1SDavid du Colombier 	r->busy = 0;
3983e12c5d1SDavid du Colombier 	t = msec()-t;
3993e12c5d1SDavid du Colombier 	rpc = &stats->rpc[Twstat];
4003e12c5d1SDavid du Colombier 	rpc->time += t;
4013e12c5d1SDavid du Colombier 	if(t < rpc->loms)
4023e12c5d1SDavid du Colombier 		rpc->loms = t;
4033e12c5d1SDavid du Colombier 	if(t > rpc->hims)
4043e12c5d1SDavid du Colombier 		rpc->hims = t;
4053e12c5d1SDavid du Colombier }
4063e12c5d1SDavid du Colombier 
4073e12c5d1SDavid du Colombier void
4083e12c5d1SDavid du Colombier Xclwalk(Fsrpc *r)
4093e12c5d1SDavid du Colombier {
4103e12c5d1SDavid du Colombier 	Fcall thdr;
4113e12c5d1SDavid du Colombier 
4123e12c5d1SDavid du Colombier 	reply(&r->work, &thdr, "exportfs: no Tclwalk");
4133e12c5d1SDavid du Colombier 	r->busy = 0;
4143e12c5d1SDavid du Colombier }
4153e12c5d1SDavid du Colombier 
4163e12c5d1SDavid du Colombier void
4173e12c5d1SDavid du Colombier slave(Fsrpc *f)
4183e12c5d1SDavid du Colombier {
4193e12c5d1SDavid du Colombier 	Proc *p;
4203e12c5d1SDavid du Colombier 	int pid;
4213e12c5d1SDavid du Colombier 	static int nproc;
4223e12c5d1SDavid du Colombier 
4233e12c5d1SDavid du Colombier 	for(;;) {
4243e12c5d1SDavid du Colombier 		for(p = Proclist; p; p = p->next) {
4253e12c5d1SDavid du Colombier 			if(p->busy == 0) {
4263e12c5d1SDavid du Colombier 				f->pid = p->pid;
4273e12c5d1SDavid du Colombier 				p->busy = 1;
4283e12c5d1SDavid du Colombier 				pid = rendezvous(p->pid, (ulong)f);
4293e12c5d1SDavid du Colombier 				if(pid != p->pid)
4303e12c5d1SDavid du Colombier 					fatal("rendezvous sync fail");
4313e12c5d1SDavid du Colombier 				return;
4323e12c5d1SDavid du Colombier 			}
4333e12c5d1SDavid du Colombier 		}
4343e12c5d1SDavid du Colombier 
4353e12c5d1SDavid du Colombier 		if(++nproc > MAXPROC)
4363e12c5d1SDavid du Colombier 			fatal("too many procs");
4373e12c5d1SDavid du Colombier 
4383e12c5d1SDavid du Colombier 		pid = rfork(RFPROC|RFMEM);
4393e12c5d1SDavid du Colombier 		if(pid < 0)
4403e12c5d1SDavid du Colombier 			fatal("rfork");
4413e12c5d1SDavid du Colombier 
4423e12c5d1SDavid du Colombier 		if(pid == 0)
4433e12c5d1SDavid du Colombier 			blockingslave();
4443e12c5d1SDavid du Colombier 
4453e12c5d1SDavid du Colombier 		p = malloc(sizeof(Proc));
4463e12c5d1SDavid du Colombier 		if(p == 0)
4473e12c5d1SDavid du Colombier 			fatal("out of memory");
4483e12c5d1SDavid du Colombier 
4493e12c5d1SDavid du Colombier 		p->busy = 0;
4503e12c5d1SDavid du Colombier 		p->pid = pid;
4513e12c5d1SDavid du Colombier 		p->next = Proclist;
4523e12c5d1SDavid du Colombier 		Proclist = p;
4533e12c5d1SDavid du Colombier 
4543e12c5d1SDavid du Colombier 		rendezvous(pid, (ulong)p);
4553e12c5d1SDavid du Colombier 	}
4563e12c5d1SDavid du Colombier }
4573e12c5d1SDavid du Colombier 
4583e12c5d1SDavid du Colombier void
4593e12c5d1SDavid du Colombier blockingslave(void)
4603e12c5d1SDavid du Colombier {
4613e12c5d1SDavid du Colombier 	Proc *m;
4623e12c5d1SDavid du Colombier 	int pid;
4633e12c5d1SDavid du Colombier 	Fsrpc *p;
4643e12c5d1SDavid du Colombier 	Fcall thdr;
4653e12c5d1SDavid du Colombier 
4663e12c5d1SDavid du Colombier 	notify(flushaction);
4673e12c5d1SDavid du Colombier 
4683e12c5d1SDavid du Colombier 	pid = getpid();
4693e12c5d1SDavid du Colombier 
4703e12c5d1SDavid du Colombier 	m = (Proc*)rendezvous(pid, 0);
4713e12c5d1SDavid du Colombier 
4723e12c5d1SDavid du Colombier 	for(;;) {
4733e12c5d1SDavid du Colombier 		p = (Fsrpc*)rendezvous(pid, pid);
4743e12c5d1SDavid du Colombier 		if((int)p == ~0)			/* Interrupted */
4753e12c5d1SDavid du Colombier 			continue;
4763e12c5d1SDavid du Colombier 
4773e12c5d1SDavid du Colombier 		DEBUG(2, "\tslave: %d %F b %d p %d\n", pid, &p->work, p->busy, p->pid);
4783e12c5d1SDavid du Colombier 	if(p->flushtag != NOTAG)
4793e12c5d1SDavid du Colombier 		return;
4803e12c5d1SDavid du Colombier 
4813e12c5d1SDavid du Colombier 		switch(p->work.type) {
4823e12c5d1SDavid du Colombier 		case Tread:
4833e12c5d1SDavid du Colombier 			slaveread(p);
4843e12c5d1SDavid du Colombier 			break;
4853e12c5d1SDavid du Colombier 		case Twrite:
4863e12c5d1SDavid du Colombier 			slavewrite(p);
4873e12c5d1SDavid du Colombier 			break;
4883e12c5d1SDavid du Colombier 		case Topen:
4893e12c5d1SDavid du Colombier 			slaveopen(p);
4903e12c5d1SDavid du Colombier 			break;
4913e12c5d1SDavid du Colombier 		default:
4923e12c5d1SDavid du Colombier 			reply(&p->work, &thdr, "exportfs: slave type error");
4933e12c5d1SDavid du Colombier 		}
4943e12c5d1SDavid du Colombier 		if(p->flushtag != NOTAG) {
4953e12c5d1SDavid du Colombier 			p->work.type = Tflush;
4963e12c5d1SDavid du Colombier 			p->work.tag = p->flushtag;
4973e12c5d1SDavid du Colombier 			reply(&p->work, &thdr, 0);
4983e12c5d1SDavid du Colombier 		}
4993e12c5d1SDavid du Colombier 		p->busy = 0;
5003e12c5d1SDavid du Colombier 		m->busy = 0;
5013e12c5d1SDavid du Colombier 	}
5023e12c5d1SDavid du Colombier }
5033e12c5d1SDavid du Colombier 
5043e12c5d1SDavid du Colombier void
5053e12c5d1SDavid du Colombier slaveopen(Fsrpc *p)
5063e12c5d1SDavid du Colombier {
5073e12c5d1SDavid du Colombier 	char err[ERRLEN], path[128];
5083e12c5d1SDavid du Colombier 	Fcall *work, thdr;
5093e12c5d1SDavid du Colombier 	Fid *f;
5103e12c5d1SDavid du Colombier 	ulong t;
5113e12c5d1SDavid du Colombier 	Rpc *rpc;
5123e12c5d1SDavid du Colombier 
5133e12c5d1SDavid du Colombier 	work = &p->work;
5143e12c5d1SDavid du Colombier 
5153e12c5d1SDavid du Colombier 	t = msec();
5163e12c5d1SDavid du Colombier 
5173e12c5d1SDavid du Colombier 	f = getfid(work->fid);
5183e12c5d1SDavid du Colombier 	if(f == 0) {
5193e12c5d1SDavid du Colombier 		reply(work, &thdr, e[Ebadfid]);
5203e12c5d1SDavid du Colombier 		return;
5213e12c5d1SDavid du Colombier 	}
5223e12c5d1SDavid du Colombier 	if(f->fid >= 0) {
5233e12c5d1SDavid du Colombier 		close(f->fid);
5243e12c5d1SDavid du Colombier 		f->fid = -1;
5253e12c5d1SDavid du Colombier 	}
5263e12c5d1SDavid du Colombier 
5273e12c5d1SDavid du Colombier 	makepath(path, f->f, "");
5283e12c5d1SDavid du Colombier 	DEBUG(2, "\topen: %s %d\n", path, work->mode);
5293e12c5d1SDavid du Colombier 
5303e12c5d1SDavid du Colombier 	p->canint = 1;
5313e12c5d1SDavid du Colombier 	if(p->flushtag != NOTAG)
5323e12c5d1SDavid du Colombier 		return;
5333e12c5d1SDavid du Colombier 	/* There is a race here I ignore because there are no locks */
5343e12c5d1SDavid du Colombier 	f->fid = open(path, work->mode);
5353e12c5d1SDavid du Colombier 	p->canint = 0;
5363e12c5d1SDavid du Colombier 	if(f->fid < 0) {
5373e12c5d1SDavid du Colombier 		errstr(err);
5383e12c5d1SDavid du Colombier 		reply(work, &thdr, err);
5393e12c5d1SDavid du Colombier 		return;
5403e12c5d1SDavid du Colombier 	}
5413e12c5d1SDavid du Colombier 
5423e12c5d1SDavid du Colombier 	DEBUG(2, "\topen: fd %d\n", f->fid);
5433e12c5d1SDavid du Colombier 	f->mode = work->mode;
5443e12c5d1SDavid du Colombier 	f->offset = 0;
5453e12c5d1SDavid du Colombier 	thdr.qid = f->f->qid;
5463e12c5d1SDavid du Colombier 	reply(work, &thdr, 0);
5473e12c5d1SDavid du Colombier 
5483e12c5d1SDavid du Colombier 	t = msec()-t;
5493e12c5d1SDavid du Colombier 	rpc = &stats->rpc[Topen];
5503e12c5d1SDavid du Colombier 	rpc->time += t;
5513e12c5d1SDavid du Colombier 	if(t < rpc->loms)
5523e12c5d1SDavid du Colombier 		rpc->loms = t;
5533e12c5d1SDavid du Colombier 	if(t > rpc->hims)
5543e12c5d1SDavid du Colombier 		rpc->hims = t;
5553e12c5d1SDavid du Colombier }
5563e12c5d1SDavid du Colombier 
5573e12c5d1SDavid du Colombier void
5583e12c5d1SDavid du Colombier slaveread(Fsrpc *p)
5593e12c5d1SDavid du Colombier {
5603e12c5d1SDavid du Colombier 	char data[MAXFDATA], err[ERRLEN];
5613e12c5d1SDavid du Colombier 	Fcall *work, thdr;
5623e12c5d1SDavid du Colombier 	Fid *f;
5633e12c5d1SDavid du Colombier 	int n, r;
5643e12c5d1SDavid du Colombier 	ulong t;
5653e12c5d1SDavid du Colombier 	Rpc *rpc;
5663e12c5d1SDavid du Colombier 
5673e12c5d1SDavid du Colombier 	work = &p->work;
5683e12c5d1SDavid du Colombier 
5693e12c5d1SDavid du Colombier 	t = msec();
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 
5773e12c5d1SDavid du Colombier 	if(work->offset != f->offset)
5783e12c5d1SDavid du Colombier 		fileseek(f, work->offset);
5793e12c5d1SDavid du Colombier 
5803e12c5d1SDavid du Colombier 	n = (work->count > MAXFDATA) ? MAXFDATA : work->count;
5813e12c5d1SDavid du Colombier 	p->canint = 1;
5823e12c5d1SDavid du Colombier 	if(p->flushtag != NOTAG)
5833e12c5d1SDavid du Colombier 		return;
5843e12c5d1SDavid du Colombier 	r = read(f->fid, data, n);
5853e12c5d1SDavid du Colombier 	p->canint = 0;
5863e12c5d1SDavid du Colombier 	if(r < 0) {
5873e12c5d1SDavid du Colombier 		errstr(err);
5883e12c5d1SDavid du Colombier 		reply(work, &thdr, err);
5893e12c5d1SDavid du Colombier 		return;
5903e12c5d1SDavid du Colombier 	}
5913e12c5d1SDavid du Colombier 
5923e12c5d1SDavid du Colombier 	DEBUG(2, "\tread: fd=%d %d bytes\n", f->fid, r);
5933e12c5d1SDavid du Colombier 
5943e12c5d1SDavid du Colombier 	f->offset += r;
5953e12c5d1SDavid du Colombier 	thdr.data = data;
5963e12c5d1SDavid du Colombier 	thdr.count = r;
5973e12c5d1SDavid du Colombier 	stats->totread += r;
5983e12c5d1SDavid du Colombier 	f->nread++;
5993e12c5d1SDavid du Colombier 	f->bread += r;
6003e12c5d1SDavid du Colombier 	reply(work, &thdr, 0);
6013e12c5d1SDavid du Colombier 
6023e12c5d1SDavid du Colombier 	t = msec()-t;
6033e12c5d1SDavid du Colombier 	rpc = &stats->rpc[Tread];
6043e12c5d1SDavid du Colombier 	rpc->time += t;
6053e12c5d1SDavid du Colombier 	if(t < rpc->loms)
6063e12c5d1SDavid du Colombier 		rpc->loms = t;
6073e12c5d1SDavid du Colombier 	if(t > rpc->hims)
6083e12c5d1SDavid du Colombier 		rpc->hims = t;
6093e12c5d1SDavid du Colombier }
6103e12c5d1SDavid du Colombier 
6113e12c5d1SDavid du Colombier void
6123e12c5d1SDavid du Colombier slavewrite(Fsrpc *p)
6133e12c5d1SDavid du Colombier {
6143e12c5d1SDavid du Colombier 	char err[ERRLEN];
6153e12c5d1SDavid du Colombier 	Fcall *work, thdr;
6163e12c5d1SDavid du Colombier 	Fid *f;
6173e12c5d1SDavid du Colombier 	int n;
6183e12c5d1SDavid du Colombier 	ulong t;
6193e12c5d1SDavid du Colombier 	Rpc *rpc;
6203e12c5d1SDavid du Colombier 
6213e12c5d1SDavid du Colombier 	work = &p->work;
6223e12c5d1SDavid du Colombier 
6233e12c5d1SDavid du Colombier 	t = msec();
6243e12c5d1SDavid du Colombier 
6253e12c5d1SDavid du Colombier 	f = getfid(work->fid);
6263e12c5d1SDavid du Colombier 	if(f == 0) {
6273e12c5d1SDavid du Colombier 		reply(work, &thdr, e[Ebadfid]);
6283e12c5d1SDavid du Colombier 		return;
6293e12c5d1SDavid du Colombier 	}
6303e12c5d1SDavid du Colombier 
6313e12c5d1SDavid du Colombier 	if(work->offset != f->offset)
6323e12c5d1SDavid du Colombier 		fileseek(f, work->offset);
6333e12c5d1SDavid du Colombier 
6343e12c5d1SDavid du Colombier 	n = (work->count > MAXFDATA) ? MAXFDATA : work->count;
6353e12c5d1SDavid du Colombier 	p->canint = 1;
6363e12c5d1SDavid du Colombier 	if(p->flushtag != NOTAG)
6373e12c5d1SDavid du Colombier 		return;
6383e12c5d1SDavid du Colombier 	n = write(f->fid, work->data, n);
6393e12c5d1SDavid du Colombier 	p->canint = 0;
6403e12c5d1SDavid du Colombier 	if(n < 0) {
6413e12c5d1SDavid du Colombier 		errstr(err);
6423e12c5d1SDavid du Colombier 		reply(work, &thdr, err);
6433e12c5d1SDavid du Colombier 		return;
6443e12c5d1SDavid du Colombier 	}
6453e12c5d1SDavid du Colombier 
6463e12c5d1SDavid du Colombier 	DEBUG(2, "\twrite: %d bytes fd=%d\n", n, f->fid);
6473e12c5d1SDavid du Colombier 
6483e12c5d1SDavid du Colombier 	f->offset += n;
6493e12c5d1SDavid du Colombier 	thdr.count = n;
6503e12c5d1SDavid du Colombier 	f->nwrite++;
6513e12c5d1SDavid du Colombier 	f->bwrite += n;
6523e12c5d1SDavid du Colombier 	stats->totwrite += n;
6533e12c5d1SDavid du Colombier 	reply(work, &thdr, 0);
6543e12c5d1SDavid du Colombier 
6553e12c5d1SDavid du Colombier 	t = msec()-t;
6563e12c5d1SDavid du Colombier 	rpc = &stats->rpc[Twrite];
6573e12c5d1SDavid du Colombier 	rpc->time += t;
6583e12c5d1SDavid du Colombier 	if(t < rpc->loms)
6593e12c5d1SDavid du Colombier 		rpc->loms = t;
6603e12c5d1SDavid du Colombier 	if(t > rpc->hims)
6613e12c5d1SDavid du Colombier 		rpc->hims = t;
6623e12c5d1SDavid du Colombier }
6633e12c5d1SDavid du Colombier 
6643e12c5d1SDavid du Colombier void
6653e12c5d1SDavid du Colombier fileseek(Fid *f, ulong offset)
6663e12c5d1SDavid du Colombier {
6673e12c5d1SDavid du Colombier 	char chunk[DIRCHUNK];
6683e12c5d1SDavid du Colombier 	int n, nbytes, r;
6693e12c5d1SDavid du Colombier 	ulong to;
6703e12c5d1SDavid du Colombier 
6713e12c5d1SDavid du Colombier 	if(f->f->qid.path&CHDIR) {
6723e12c5d1SDavid du Colombier 		if(offset < f->offset)
6733e12c5d1SDavid du Colombier 			reopen(f);
6743e12c5d1SDavid du Colombier 
6753e12c5d1SDavid du Colombier 		for(nbytes = offset - f->offset; nbytes; nbytes -= r) {
6763e12c5d1SDavid du Colombier 			n = (nbytes > DIRCHUNK) ? DIRCHUNK : nbytes;
6773e12c5d1SDavid du Colombier 			r = read(f->fid, chunk, n);
6783e12c5d1SDavid du Colombier 			if(r <= 0) {
6793e12c5d1SDavid du Colombier 				DEBUG(2,"\tdir seek error\n");
6803e12c5d1SDavid du Colombier 				return;
6813e12c5d1SDavid du Colombier 			}
6823e12c5d1SDavid du Colombier 			f->offset += r;
6833e12c5d1SDavid du Colombier 		}
6843e12c5d1SDavid du Colombier 	}
6853e12c5d1SDavid du Colombier 	else
6863e12c5d1SDavid du Colombier 		f->offset = seek(f->fid, offset, 0);
6873e12c5d1SDavid du Colombier }
6883e12c5d1SDavid du Colombier 
6893e12c5d1SDavid du Colombier void
6903e12c5d1SDavid du Colombier reopen(Fid *f)
6913e12c5d1SDavid du Colombier {
6923e12c5d1SDavid du Colombier 	USED(f);
6933e12c5d1SDavid du Colombier 	fatal("reopen");
6943e12c5d1SDavid du Colombier }
6953e12c5d1SDavid du Colombier 
6963e12c5d1SDavid du Colombier void
6973e12c5d1SDavid du Colombier flushaction(void *a, char *cause)
6983e12c5d1SDavid du Colombier {
6993e12c5d1SDavid du Colombier 	USED(a);
7003e12c5d1SDavid du Colombier 	if(strncmp(cause, "kill", 4) == 0)
7013e12c5d1SDavid du Colombier 		noted(NDFLT);
7023e12c5d1SDavid du Colombier 
7033e12c5d1SDavid du Colombier 	noted(NCONT);
7043e12c5d1SDavid du Colombier }
705