13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
3219b2ee8SDavid 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
89a747e4fSDavid du Colombier char Ebadfid[] = "Bad fid";
99a747e4fSDavid du Colombier char Enotdir[] ="Not a directory";
109a747e4fSDavid du Colombier char Edupfid[] = "Fid already in use";
119a747e4fSDavid du Colombier char Eopen[] = "Fid already opened";
129a747e4fSDavid du Colombier char Exmnt[] = "Cannot .. past mount point";
139a747e4fSDavid du Colombier char Enoauth[] = "iostats: Authentication failed";
149a747e4fSDavid du Colombier char Ebadver[] = "Unrecognized 9P version";
153e12c5d1SDavid du Colombier
169a747e4fSDavid du Colombier int
okfile(char * s,int mode)179a747e4fSDavid du Colombier okfile(char *s, int mode)
183e12c5d1SDavid du Colombier {
199a747e4fSDavid du Colombier if(strncmp(s, "/fd/", 3) == 0){
209a747e4fSDavid du Colombier /* 0, 1, and 2 we handle ourselves */
219a747e4fSDavid du Colombier if(s[4]=='/' || atoi(s+4) > 2)
229a747e4fSDavid du Colombier return 0;
239a747e4fSDavid du Colombier return 1;
249a747e4fSDavid du Colombier }
259a747e4fSDavid du Colombier if(strncmp(s, "/net/ssl", 8) == 0)
269a747e4fSDavid du Colombier return 0;
279a747e4fSDavid du Colombier if(strncmp(s, "/net/tls", 8) == 0)
289a747e4fSDavid du Colombier return 0;
299a747e4fSDavid du Colombier if(strncmp(s, "/srv/", 5) == 0 && ((mode&3) == OWRITE || (mode&3) == ORDWR))
309a747e4fSDavid du Colombier return 0;
319a747e4fSDavid du Colombier return 1;
323e12c5d1SDavid du Colombier }
333e12c5d1SDavid du Colombier
343e12c5d1SDavid du Colombier void
update(Rpc * rpc,vlong t)35ab3dc52fSDavid du Colombier update(Rpc *rpc, vlong t)
36dc5a79c1SDavid du Colombier {
37ab3dc52fSDavid du Colombier vlong t2;
38dc5a79c1SDavid du Colombier
39ab3dc52fSDavid du Colombier t2 = nsec();
40ab3dc52fSDavid du Colombier t = t2 - t;
41ab3dc52fSDavid du Colombier if(t < 0)
42dc5a79c1SDavid du Colombier t = 0;
43dc5a79c1SDavid du Colombier
44dc5a79c1SDavid du Colombier rpc->time += t;
45ab3dc52fSDavid du Colombier if(t < rpc->lo)
46ab3dc52fSDavid du Colombier rpc->lo = t;
47ab3dc52fSDavid du Colombier if(t > rpc->hi)
48ab3dc52fSDavid du Colombier rpc->hi = t;
49dc5a79c1SDavid du Colombier }
50dc5a79c1SDavid du Colombier
51dc5a79c1SDavid du Colombier void
Xversion(Fsrpc * r)529a747e4fSDavid du Colombier Xversion(Fsrpc *r)
533e12c5d1SDavid du Colombier {
543e12c5d1SDavid du Colombier Fcall thdr;
55ab3dc52fSDavid du Colombier vlong t;
563e12c5d1SDavid du Colombier
57ab3dc52fSDavid du Colombier t = nsec();
589a747e4fSDavid du Colombier
599a747e4fSDavid du Colombier if(r->work.msize > IOHDRSZ+Maxfdata)
609a747e4fSDavid du Colombier thdr.msize = IOHDRSZ+Maxfdata;
619a747e4fSDavid du Colombier else
629a747e4fSDavid du Colombier thdr.msize = r->work.msize;
639a747e4fSDavid du Colombier myiounit = thdr.msize - IOHDRSZ;
649a747e4fSDavid du Colombier if(strncmp(r->work.version, "9P2000", 6) != 0){
659a747e4fSDavid du Colombier reply(&r->work, &thdr, Ebadver);
669a747e4fSDavid du Colombier r->busy = 0;
679a747e4fSDavid du Colombier return;
689a747e4fSDavid du Colombier }
699a747e4fSDavid du Colombier thdr.version = "9P2000";
709a747e4fSDavid du Colombier /* BUG: should clunk all fids */
713e12c5d1SDavid du Colombier reply(&r->work, &thdr, 0);
723e12c5d1SDavid du Colombier r->busy = 0;
739a747e4fSDavid du Colombier
74dc5a79c1SDavid du Colombier update(&stats->rpc[Tversion], t);
759a747e4fSDavid du Colombier }
769a747e4fSDavid du Colombier
779a747e4fSDavid du Colombier void
Xauth(Fsrpc * r)789a747e4fSDavid du Colombier Xauth(Fsrpc *r)
799a747e4fSDavid du Colombier {
809a747e4fSDavid du Colombier Fcall thdr;
81ab3dc52fSDavid du Colombier vlong t;
829a747e4fSDavid du Colombier
83ab3dc52fSDavid du Colombier t = nsec();
849a747e4fSDavid du Colombier
859a747e4fSDavid du Colombier reply(&r->work, &thdr, Enoauth);
869a747e4fSDavid du Colombier r->busy = 0;
879a747e4fSDavid du Colombier
88dc5a79c1SDavid du Colombier update(&stats->rpc[Tauth], t);
893e12c5d1SDavid du Colombier }
903e12c5d1SDavid du Colombier
913e12c5d1SDavid du Colombier void
Xflush(Fsrpc * r)923e12c5d1SDavid du Colombier Xflush(Fsrpc *r)
933e12c5d1SDavid du Colombier {
943e12c5d1SDavid du Colombier Fsrpc *t, *e;
953e12c5d1SDavid du Colombier Fcall thdr;
963e12c5d1SDavid du Colombier
973e12c5d1SDavid du Colombier e = &Workq[Nr_workbufs];
983e12c5d1SDavid du Colombier
993e12c5d1SDavid du Colombier for(t = Workq; t < e; t++) {
1003e12c5d1SDavid du Colombier if(t->work.tag == r->work.oldtag) {
10174f16c81SDavid du Colombier DEBUG(2, "\tQ busy %d pid %p can %d\n", t->busy, t->pid, t->canint);
1023e12c5d1SDavid du Colombier if(t->busy && t->pid) {
1033e12c5d1SDavid du Colombier t->flushtag = r->work.tag;
1043e12c5d1SDavid du Colombier DEBUG(2, "\tset flushtag %d\n", r->work.tag);
1053e12c5d1SDavid du Colombier if(t->canint)
106219b2ee8SDavid du Colombier postnote(PNPROC, t->pid, "flush");
1073e12c5d1SDavid du Colombier r->busy = 0;
1083e12c5d1SDavid du Colombier return;
1093e12c5d1SDavid du Colombier }
1103e12c5d1SDavid du Colombier }
1113e12c5d1SDavid du Colombier }
1123e12c5d1SDavid du Colombier
1133e12c5d1SDavid du Colombier reply(&r->work, &thdr, 0);
1143e12c5d1SDavid du Colombier DEBUG(2, "\tflush reply\n");
1153e12c5d1SDavid du Colombier r->busy = 0;
1163e12c5d1SDavid du Colombier }
1173e12c5d1SDavid du Colombier
1183e12c5d1SDavid du Colombier void
Xattach(Fsrpc * r)1193e12c5d1SDavid du Colombier Xattach(Fsrpc *r)
1203e12c5d1SDavid du Colombier {
1213e12c5d1SDavid du Colombier Fcall thdr;
1223e12c5d1SDavid du Colombier Fid *f;
123ab3dc52fSDavid du Colombier vlong t;
1243e12c5d1SDavid du Colombier
125ab3dc52fSDavid du Colombier t = nsec();
1263e12c5d1SDavid du Colombier
1273e12c5d1SDavid du Colombier f = newfid(r->work.fid);
1283e12c5d1SDavid du Colombier if(f == 0) {
1299a747e4fSDavid du Colombier reply(&r->work, &thdr, Ebadfid);
1303e12c5d1SDavid du Colombier r->busy = 0;
1313e12c5d1SDavid du Colombier return;
1323e12c5d1SDavid du Colombier }
1333e12c5d1SDavid du Colombier
1343e12c5d1SDavid du Colombier f->f = root;
1353e12c5d1SDavid du Colombier thdr.qid = f->f->qid;
1363e12c5d1SDavid du Colombier reply(&r->work, &thdr, 0);
1373e12c5d1SDavid du Colombier r->busy = 0;
1383e12c5d1SDavid du Colombier
139dc5a79c1SDavid du Colombier update(&stats->rpc[Tattach], t);
1403e12c5d1SDavid du Colombier }
1413e12c5d1SDavid du Colombier
1423e12c5d1SDavid du Colombier void
Xwalk(Fsrpc * r)1439a747e4fSDavid du Colombier Xwalk(Fsrpc *r)
1443e12c5d1SDavid du Colombier {
1459a747e4fSDavid du Colombier char errbuf[ERRMAX], *err;
1463e12c5d1SDavid du Colombier Fcall thdr;
1473e12c5d1SDavid du Colombier Fid *f, *n;
1489a747e4fSDavid du Colombier File *nf;
149ab3dc52fSDavid du Colombier vlong t;
1509a747e4fSDavid du Colombier int i;
1513e12c5d1SDavid du Colombier
152ab3dc52fSDavid du Colombier t = nsec();
1533e12c5d1SDavid du Colombier
1543e12c5d1SDavid du Colombier f = getfid(r->work.fid);
1553e12c5d1SDavid du Colombier if(f == 0) {
1569a747e4fSDavid du Colombier reply(&r->work, &thdr, Ebadfid);
1573e12c5d1SDavid du Colombier r->busy = 0;
1583e12c5d1SDavid du Colombier return;
1593e12c5d1SDavid du Colombier }
1609a747e4fSDavid du Colombier n = nil;
1619a747e4fSDavid du Colombier if(r->work.newfid != r->work.fid){
1623e12c5d1SDavid du Colombier n = newfid(r->work.newfid);
1633e12c5d1SDavid du Colombier if(n == 0) {
1649a747e4fSDavid du Colombier reply(&r->work, &thdr, Edupfid);
1653e12c5d1SDavid du Colombier r->busy = 0;
1663e12c5d1SDavid du Colombier return;
1673e12c5d1SDavid du Colombier }
1683e12c5d1SDavid du Colombier n->f = f->f;
1699a747e4fSDavid du Colombier f = n; /* walk new guy */
1703e12c5d1SDavid du Colombier }
1713e12c5d1SDavid du Colombier
1729a747e4fSDavid du Colombier thdr.nwqid = 0;
1739a747e4fSDavid du Colombier err = nil;
1749a747e4fSDavid du Colombier for(i=0; i<r->work.nwname; i++){
1759a747e4fSDavid du Colombier if(i >= MAXWELEM)
1769a747e4fSDavid du Colombier break;
1779a747e4fSDavid du Colombier if(strcmp(r->work.wname[i], "..") == 0) {
1783e12c5d1SDavid du Colombier if(f->f->parent == 0) {
1799a747e4fSDavid du Colombier err = Exmnt;
1809a747e4fSDavid du Colombier break;
1813e12c5d1SDavid du Colombier }
1823e12c5d1SDavid du Colombier f->f = f->f->parent;
1839a747e4fSDavid du Colombier thdr.wqid[thdr.nwqid++] = f->f->qid;
1849a747e4fSDavid du Colombier continue;
1853e12c5d1SDavid du Colombier }
1863e12c5d1SDavid du Colombier
1879a747e4fSDavid du Colombier nf = file(f->f, r->work.wname[i]);
1883e12c5d1SDavid du Colombier if(nf == 0) {
1899a747e4fSDavid du Colombier errstr(errbuf, sizeof errbuf);
1909a747e4fSDavid du Colombier err = errbuf;
1919a747e4fSDavid du Colombier break;
1923e12c5d1SDavid du Colombier }
1933e12c5d1SDavid du Colombier
1943e12c5d1SDavid du Colombier f->f = nf;
1959a747e4fSDavid du Colombier thdr.wqid[thdr.nwqid++] = nf->qid;
1969a747e4fSDavid du Colombier continue;
1979a747e4fSDavid du Colombier }
1989a747e4fSDavid du Colombier
1999a747e4fSDavid du Colombier if(err == nil && thdr.nwqid == 0 && r->work.nwname > 0)
2009a747e4fSDavid du Colombier err = "file does not exist";
2019a747e4fSDavid du Colombier
2029a747e4fSDavid du Colombier if(n != nil && (err != 0 || thdr.nwqid < r->work.nwname)){
2039a747e4fSDavid du Colombier /* clunk the new fid, which is the one we walked */
2049a747e4fSDavid du Colombier freefid(n->nr);
2059a747e4fSDavid du Colombier }
2069a747e4fSDavid du Colombier
2079a747e4fSDavid du Colombier if(thdr.nwqid > 0)
2089a747e4fSDavid du Colombier err = nil;
2099a747e4fSDavid du Colombier reply(&r->work, &thdr, err);
2103e12c5d1SDavid du Colombier r->busy = 0;
2113e12c5d1SDavid du Colombier
212dc5a79c1SDavid du Colombier update(&stats->rpc[Twalk], t);
2133e12c5d1SDavid du Colombier }
2143e12c5d1SDavid du Colombier
2153e12c5d1SDavid du Colombier void
Xclunk(Fsrpc * r)2163e12c5d1SDavid du Colombier Xclunk(Fsrpc *r)
2173e12c5d1SDavid du Colombier {
2183e12c5d1SDavid du Colombier Fcall thdr;
2193e12c5d1SDavid du Colombier Fid *f;
220ab3dc52fSDavid du Colombier vlong t;
2213e12c5d1SDavid du Colombier int fid;
2223e12c5d1SDavid du Colombier
223ab3dc52fSDavid du Colombier t = nsec();
2243e12c5d1SDavid du Colombier
2253e12c5d1SDavid du Colombier f = getfid(r->work.fid);
2263e12c5d1SDavid du Colombier if(f == 0) {
2279a747e4fSDavid du Colombier reply(&r->work, &thdr, Ebadfid);
2283e12c5d1SDavid du Colombier r->busy = 0;
2293e12c5d1SDavid du Colombier return;
2303e12c5d1SDavid du Colombier }
2313e12c5d1SDavid du Colombier
2323e12c5d1SDavid du Colombier if(f->fid >= 0)
2333e12c5d1SDavid du Colombier close(f->fid);
2343e12c5d1SDavid du Colombier
2353e12c5d1SDavid du Colombier fid = r->work.fid;
2363e12c5d1SDavid du Colombier reply(&r->work, &thdr, 0);
2373e12c5d1SDavid du Colombier r->busy = 0;
2383e12c5d1SDavid du Colombier
239dc5a79c1SDavid du Colombier update(&stats->rpc[Tclunk], t);
2403e12c5d1SDavid du Colombier
2413e12c5d1SDavid du Colombier if(f->nread || f->nwrite)
2423e12c5d1SDavid du Colombier fidreport(f);
2433e12c5d1SDavid du Colombier
2443e12c5d1SDavid du Colombier freefid(fid);
2453e12c5d1SDavid du Colombier }
2463e12c5d1SDavid du Colombier
2473e12c5d1SDavid du Colombier void
Xstat(Fsrpc * r)2483e12c5d1SDavid du Colombier Xstat(Fsrpc *r)
2493e12c5d1SDavid du Colombier {
2509a747e4fSDavid du Colombier char err[ERRMAX], path[128];
2519a747e4fSDavid du Colombier uchar statbuf[STATMAX];
2523e12c5d1SDavid du Colombier Fcall thdr;
2533e12c5d1SDavid du Colombier Fid *f;
2543e12c5d1SDavid du Colombier int s;
255ab3dc52fSDavid du Colombier vlong t;
2563e12c5d1SDavid du Colombier
257ab3dc52fSDavid du Colombier t = nsec();
2583e12c5d1SDavid du Colombier
2593e12c5d1SDavid du Colombier f = getfid(r->work.fid);
2603e12c5d1SDavid du Colombier if(f == 0) {
2619a747e4fSDavid du Colombier reply(&r->work, &thdr, Ebadfid);
2623e12c5d1SDavid du Colombier r->busy = 0;
2633e12c5d1SDavid du Colombier return;
2643e12c5d1SDavid du Colombier }
2653e12c5d1SDavid du Colombier makepath(path, f->f, "");
2669a747e4fSDavid du Colombier if(!okfile(path, -1)){
2679a747e4fSDavid du Colombier snprint(err, sizeof err, "iostats: can't simulate %s", path);
2683e12c5d1SDavid du Colombier reply(&r->work, &thdr, err);
2693e12c5d1SDavid du Colombier r->busy = 0;
2703e12c5d1SDavid du Colombier return;
2713e12c5d1SDavid du Colombier }
2729a747e4fSDavid du Colombier
2739a747e4fSDavid du Colombier if(f->fid >= 0)
2749a747e4fSDavid du Colombier s = fstat(f->fid, statbuf, sizeof statbuf);
2759a747e4fSDavid du Colombier else
2769a747e4fSDavid du Colombier s = stat(path, statbuf, sizeof statbuf);
2779a747e4fSDavid du Colombier
2789a747e4fSDavid du Colombier if(s < 0) {
2799a747e4fSDavid du Colombier errstr(err, sizeof err);
2809a747e4fSDavid du Colombier reply(&r->work, &thdr, err);
2819a747e4fSDavid du Colombier r->busy = 0;
2829a747e4fSDavid du Colombier return;
2839a747e4fSDavid du Colombier }
2849a747e4fSDavid du Colombier thdr.stat = statbuf;
2859a747e4fSDavid du Colombier thdr.nstat = s;
2863e12c5d1SDavid du Colombier reply(&r->work, &thdr, 0);
2873e12c5d1SDavid du Colombier r->busy = 0;
2883e12c5d1SDavid du Colombier
289dc5a79c1SDavid du Colombier update(&stats->rpc[Tstat], t);
2903e12c5d1SDavid du Colombier }
2913e12c5d1SDavid du Colombier
2923e12c5d1SDavid du Colombier void
Xcreate(Fsrpc * r)2933e12c5d1SDavid du Colombier Xcreate(Fsrpc *r)
2943e12c5d1SDavid du Colombier {
2959a747e4fSDavid du Colombier char err[ERRMAX], path[128];
2963e12c5d1SDavid du Colombier Fcall thdr;
2973e12c5d1SDavid du Colombier Fid *f;
2983e12c5d1SDavid du Colombier File *nf;
299ab3dc52fSDavid du Colombier vlong t;
3003e12c5d1SDavid du Colombier
301ab3dc52fSDavid du Colombier t = nsec();
3023e12c5d1SDavid du Colombier
3033e12c5d1SDavid du Colombier f = getfid(r->work.fid);
3043e12c5d1SDavid du Colombier if(f == 0) {
3059a747e4fSDavid du Colombier reply(&r->work, &thdr, Ebadfid);
3063e12c5d1SDavid du Colombier r->busy = 0;
3073e12c5d1SDavid du Colombier return;
3083e12c5d1SDavid du Colombier }
3093e12c5d1SDavid du Colombier
3103e12c5d1SDavid du Colombier
3113e12c5d1SDavid du Colombier makepath(path, f->f, r->work.name);
3123e12c5d1SDavid du Colombier f->fid = create(path, r->work.mode, r->work.perm);
3133e12c5d1SDavid du Colombier if(f->fid < 0) {
3149a747e4fSDavid du Colombier errstr(err, sizeof err);
3153e12c5d1SDavid du Colombier reply(&r->work, &thdr, err);
3163e12c5d1SDavid du Colombier r->busy = 0;
3173e12c5d1SDavid du Colombier return;
3183e12c5d1SDavid du Colombier }
3193e12c5d1SDavid du Colombier
3203e12c5d1SDavid du Colombier nf = file(f->f, r->work.name);
3213e12c5d1SDavid du Colombier if(nf == 0) {
3229a747e4fSDavid du Colombier errstr(err, sizeof err);
3233e12c5d1SDavid du Colombier reply(&r->work, &thdr, err);
3243e12c5d1SDavid du Colombier r->busy = 0;
3253e12c5d1SDavid du Colombier return;
3263e12c5d1SDavid du Colombier }
3273e12c5d1SDavid du Colombier
3283e12c5d1SDavid du Colombier f->mode = r->work.mode;
3293e12c5d1SDavid du Colombier f->f = nf;
3309a747e4fSDavid du Colombier thdr.iounit = myiounit;
3313e12c5d1SDavid du Colombier thdr.qid = f->f->qid;
3323e12c5d1SDavid du Colombier reply(&r->work, &thdr, 0);
3333e12c5d1SDavid du Colombier r->busy = 0;
3343e12c5d1SDavid du Colombier
335dc5a79c1SDavid du Colombier update(&stats->rpc[Tcreate], t);
3363e12c5d1SDavid du Colombier }
3373e12c5d1SDavid du Colombier
3383e12c5d1SDavid du Colombier
3393e12c5d1SDavid du Colombier void
Xremove(Fsrpc * r)3403e12c5d1SDavid du Colombier Xremove(Fsrpc *r)
3413e12c5d1SDavid du Colombier {
3429a747e4fSDavid du Colombier char err[ERRMAX], path[128];
3433e12c5d1SDavid du Colombier Fcall thdr;
3443e12c5d1SDavid du Colombier Fid *f;
345ab3dc52fSDavid du Colombier vlong t;
3463e12c5d1SDavid du Colombier
347ab3dc52fSDavid du Colombier t = nsec();
3483e12c5d1SDavid du Colombier
3493e12c5d1SDavid du Colombier f = getfid(r->work.fid);
3503e12c5d1SDavid du Colombier if(f == 0) {
3519a747e4fSDavid du Colombier reply(&r->work, &thdr, Ebadfid);
3523e12c5d1SDavid du Colombier r->busy = 0;
3533e12c5d1SDavid du Colombier return;
3543e12c5d1SDavid du Colombier }
3553e12c5d1SDavid du Colombier
3563e12c5d1SDavid du Colombier makepath(path, f->f, "");
3573e12c5d1SDavid du Colombier DEBUG(2, "\tremove: %s\n", path);
3583e12c5d1SDavid du Colombier if(remove(path) < 0) {
3599a747e4fSDavid du Colombier errstr(err, sizeof err);
3603e12c5d1SDavid du Colombier reply(&r->work, &thdr, err);
361219b2ee8SDavid du Colombier freefid(r->work.fid);
3623e12c5d1SDavid du Colombier r->busy = 0;
3633e12c5d1SDavid du Colombier return;
3643e12c5d1SDavid du Colombier }
3653e12c5d1SDavid du Colombier
3667dd7cddfSDavid du Colombier f->f->inval = 1;
3673e12c5d1SDavid du Colombier if(f->fid >= 0)
3683e12c5d1SDavid du Colombier close(f->fid);
3693e12c5d1SDavid du Colombier freefid(r->work.fid);
3703e12c5d1SDavid du Colombier
3713e12c5d1SDavid du Colombier reply(&r->work, &thdr, 0);
3723e12c5d1SDavid du Colombier r->busy = 0;
3733e12c5d1SDavid du Colombier
374dc5a79c1SDavid du Colombier update(&stats->rpc[Tremove], t);
3753e12c5d1SDavid du Colombier }
3763e12c5d1SDavid du Colombier
3773e12c5d1SDavid du Colombier void
Xwstat(Fsrpc * r)3783e12c5d1SDavid du Colombier Xwstat(Fsrpc *r)
3793e12c5d1SDavid du Colombier {
3809a747e4fSDavid du Colombier char err[ERRMAX], path[128];
3813e12c5d1SDavid du Colombier Fcall thdr;
3823e12c5d1SDavid du Colombier Fid *f;
3833e12c5d1SDavid du Colombier int s;
384ab3dc52fSDavid du Colombier vlong t;
3853e12c5d1SDavid du Colombier
386ab3dc52fSDavid du Colombier t = nsec();
3873e12c5d1SDavid du Colombier
3883e12c5d1SDavid du Colombier f = getfid(r->work.fid);
3893e12c5d1SDavid du Colombier if(f == 0) {
3909a747e4fSDavid du Colombier reply(&r->work, &thdr, Ebadfid);
3913e12c5d1SDavid du Colombier r->busy = 0;
3923e12c5d1SDavid du Colombier return;
3933e12c5d1SDavid du Colombier }
3943e12c5d1SDavid du Colombier if(f->fid >= 0)
3959a747e4fSDavid du Colombier s = fwstat(f->fid, r->work.stat, r->work.nstat);
3963e12c5d1SDavid du Colombier else {
3973e12c5d1SDavid du Colombier makepath(path, f->f, "");
3989a747e4fSDavid du Colombier s = wstat(path, r->work.stat, r->work.nstat);
3993e12c5d1SDavid du Colombier }
4003e12c5d1SDavid du Colombier if(s < 0) {
4019a747e4fSDavid du Colombier errstr(err, sizeof err);
4023e12c5d1SDavid du Colombier reply(&r->work, &thdr, err);
4033e12c5d1SDavid du Colombier }
4043e12c5d1SDavid du Colombier else
4053e12c5d1SDavid du Colombier reply(&r->work, &thdr, 0);
4063e12c5d1SDavid du Colombier
4073e12c5d1SDavid du Colombier r->busy = 0;
408dc5a79c1SDavid du Colombier update(&stats->rpc[Twstat], t);
4093e12c5d1SDavid du Colombier }
4103e12c5d1SDavid du Colombier
4113e12c5d1SDavid du Colombier void
slave(Fsrpc * f)4123e12c5d1SDavid du Colombier slave(Fsrpc *f)
4133e12c5d1SDavid du Colombier {
414*c93608ccSDavid du Colombier int r;
4153e12c5d1SDavid du Colombier Proc *p;
41674f16c81SDavid du Colombier uintptr pid;
4173e12c5d1SDavid du Colombier static int nproc;
4183e12c5d1SDavid du Colombier
4193e12c5d1SDavid du Colombier for(;;) {
4203e12c5d1SDavid du Colombier for(p = Proclist; p; p = p->next) {
4213e12c5d1SDavid du Colombier if(p->busy == 0) {
4223e12c5d1SDavid du Colombier f->pid = p->pid;
4233e12c5d1SDavid du Colombier p->busy = 1;
42474f16c81SDavid du Colombier pid = (uintptr)rendezvous((void*)p->pid, f);
4253e12c5d1SDavid du Colombier if(pid != p->pid)
4263e12c5d1SDavid du Colombier fatal("rendezvous sync fail");
4273e12c5d1SDavid du Colombier return;
4283e12c5d1SDavid du Colombier }
4293e12c5d1SDavid du Colombier }
4303e12c5d1SDavid du Colombier
4313e12c5d1SDavid du Colombier if(++nproc > MAXPROC)
4323e12c5d1SDavid du Colombier fatal("too many procs");
4333e12c5d1SDavid du Colombier
434*c93608ccSDavid du Colombier r = rfork(RFPROC|RFMEM);
435*c93608ccSDavid du Colombier if(r < 0)
4363e12c5d1SDavid du Colombier fatal("rfork");
4373e12c5d1SDavid du Colombier
438*c93608ccSDavid du Colombier if(r == 0)
4393e12c5d1SDavid du Colombier blockingslave();
4403e12c5d1SDavid du Colombier
4413e12c5d1SDavid du Colombier p = malloc(sizeof(Proc));
4423e12c5d1SDavid du Colombier if(p == 0)
4433e12c5d1SDavid du Colombier fatal("out of memory");
4443e12c5d1SDavid du Colombier
4453e12c5d1SDavid du Colombier p->busy = 0;
446*c93608ccSDavid du Colombier p->pid = r;
4473e12c5d1SDavid du Colombier p->next = Proclist;
4483e12c5d1SDavid du Colombier Proclist = p;
4493e12c5d1SDavid du Colombier
450*c93608ccSDavid du Colombier rendezvous((void*)p->pid, p);
4513e12c5d1SDavid du Colombier }
4523e12c5d1SDavid du Colombier }
4533e12c5d1SDavid du Colombier
4543e12c5d1SDavid du Colombier void
blockingslave(void)4553e12c5d1SDavid du Colombier blockingslave(void)
4563e12c5d1SDavid du Colombier {
4573e12c5d1SDavid du Colombier Proc *m;
45874f16c81SDavid du Colombier uintptr pid;
4593e12c5d1SDavid du Colombier Fsrpc *p;
4603e12c5d1SDavid du Colombier Fcall thdr;
4613e12c5d1SDavid du Colombier
4623e12c5d1SDavid du Colombier notify(flushaction);
4633e12c5d1SDavid du Colombier
4643e12c5d1SDavid du Colombier pid = getpid();
4653e12c5d1SDavid du Colombier
46674f16c81SDavid du Colombier m = rendezvous((void*)pid, 0);
4673e12c5d1SDavid du Colombier
4683e12c5d1SDavid du Colombier for(;;) {
46974f16c81SDavid du Colombier p = rendezvous((void*)pid, (void*)pid);
47074f16c81SDavid du Colombier if(p == (void*)~0) /* Interrupted */
4713e12c5d1SDavid du Colombier continue;
4723e12c5d1SDavid du Colombier
47374f16c81SDavid du Colombier DEBUG(2, "\tslave: %p %F b %d p %p\n", pid, &p->work, p->busy, p->pid);
4743e12c5d1SDavid du Colombier if(p->flushtag != NOTAG)
4753e12c5d1SDavid du Colombier return;
4763e12c5d1SDavid du Colombier
4773e12c5d1SDavid du Colombier switch(p->work.type) {
4783e12c5d1SDavid du Colombier case Tread:
4793e12c5d1SDavid du Colombier slaveread(p);
4803e12c5d1SDavid du Colombier break;
4813e12c5d1SDavid du Colombier case Twrite:
4823e12c5d1SDavid du Colombier slavewrite(p);
4833e12c5d1SDavid du Colombier break;
4843e12c5d1SDavid du Colombier case Topen:
4853e12c5d1SDavid du Colombier slaveopen(p);
4863e12c5d1SDavid du Colombier break;
4873e12c5d1SDavid du Colombier default:
4883e12c5d1SDavid du Colombier reply(&p->work, &thdr, "exportfs: slave type error");
4893e12c5d1SDavid du Colombier }
4903e12c5d1SDavid du Colombier if(p->flushtag != NOTAG) {
4913e12c5d1SDavid du Colombier p->work.type = Tflush;
4923e12c5d1SDavid du Colombier p->work.tag = p->flushtag;
4933e12c5d1SDavid du Colombier reply(&p->work, &thdr, 0);
4943e12c5d1SDavid du Colombier }
4953e12c5d1SDavid du Colombier p->busy = 0;
4963e12c5d1SDavid du Colombier m->busy = 0;
4973e12c5d1SDavid du Colombier }
4983e12c5d1SDavid du Colombier }
4993e12c5d1SDavid du Colombier
5003e12c5d1SDavid du Colombier void
slaveopen(Fsrpc * p)5013e12c5d1SDavid du Colombier slaveopen(Fsrpc *p)
5023e12c5d1SDavid du Colombier {
5039a747e4fSDavid du Colombier char err[ERRMAX], path[128];
5043e12c5d1SDavid du Colombier Fcall *work, thdr;
5053e12c5d1SDavid du Colombier Fid *f;
506ab3dc52fSDavid du Colombier vlong t;
5073e12c5d1SDavid du Colombier
5083e12c5d1SDavid du Colombier work = &p->work;
5093e12c5d1SDavid du Colombier
510ab3dc52fSDavid du Colombier t = nsec();
5113e12c5d1SDavid du Colombier
5123e12c5d1SDavid du Colombier f = getfid(work->fid);
5133e12c5d1SDavid du Colombier if(f == 0) {
5149a747e4fSDavid du Colombier reply(work, &thdr, Ebadfid);
5153e12c5d1SDavid du Colombier return;
5163e12c5d1SDavid du Colombier }
5173e12c5d1SDavid du Colombier if(f->fid >= 0) {
5183e12c5d1SDavid du Colombier close(f->fid);
5193e12c5d1SDavid du Colombier f->fid = -1;
5203e12c5d1SDavid du Colombier }
5213e12c5d1SDavid du Colombier
5223e12c5d1SDavid du Colombier makepath(path, f->f, "");
5233e12c5d1SDavid du Colombier DEBUG(2, "\topen: %s %d\n", path, work->mode);
5243e12c5d1SDavid du Colombier
5253e12c5d1SDavid du Colombier p->canint = 1;
5263e12c5d1SDavid du Colombier if(p->flushtag != NOTAG)
5273e12c5d1SDavid du Colombier return;
5289a747e4fSDavid du Colombier
5299a747e4fSDavid du Colombier if(!okfile(path, work->mode)){
5309a747e4fSDavid du Colombier snprint(err, sizeof err, "iostats can't simulate %s", path);
5319a747e4fSDavid du Colombier reply(work, &thdr, err);
5329a747e4fSDavid du Colombier return;
5339a747e4fSDavid du Colombier }
5349a747e4fSDavid du Colombier
5353e12c5d1SDavid du Colombier /* There is a race here I ignore because there are no locks */
5363e12c5d1SDavid du Colombier f->fid = open(path, work->mode);
5373e12c5d1SDavid du Colombier p->canint = 0;
5383e12c5d1SDavid du Colombier if(f->fid < 0) {
5399a747e4fSDavid du Colombier errstr(err, sizeof err);
5403e12c5d1SDavid du Colombier reply(work, &thdr, err);
5413e12c5d1SDavid du Colombier return;
5423e12c5d1SDavid du Colombier }
5433e12c5d1SDavid du Colombier
5443e12c5d1SDavid du Colombier DEBUG(2, "\topen: fd %d\n", f->fid);
5453e12c5d1SDavid du Colombier f->mode = work->mode;
5469a747e4fSDavid du Colombier thdr.iounit = myiounit;
5473e12c5d1SDavid du Colombier thdr.qid = f->f->qid;
5483e12c5d1SDavid du Colombier reply(work, &thdr, 0);
5493e12c5d1SDavid du Colombier
550dc5a79c1SDavid du Colombier update(&stats->rpc[Topen], t);
5513e12c5d1SDavid du Colombier }
5523e12c5d1SDavid du Colombier
5533e12c5d1SDavid du Colombier void
slaveread(Fsrpc * p)5543e12c5d1SDavid du Colombier slaveread(Fsrpc *p)
5553e12c5d1SDavid du Colombier {
5569a747e4fSDavid du Colombier char data[Maxfdata], err[ERRMAX];
5573e12c5d1SDavid du Colombier Fcall *work, thdr;
5583e12c5d1SDavid du Colombier Fid *f;
5593e12c5d1SDavid du Colombier int n, r;
560ab3dc52fSDavid du Colombier vlong t;
5613e12c5d1SDavid du Colombier
5623e12c5d1SDavid du Colombier work = &p->work;
5633e12c5d1SDavid du Colombier
564ab3dc52fSDavid du Colombier t = nsec();
5653e12c5d1SDavid du Colombier
5663e12c5d1SDavid du Colombier f = getfid(work->fid);
5673e12c5d1SDavid du Colombier if(f == 0) {
5689a747e4fSDavid du Colombier reply(work, &thdr, Ebadfid);
5693e12c5d1SDavid du Colombier return;
5703e12c5d1SDavid du Colombier }
5713e12c5d1SDavid du Colombier
5729a747e4fSDavid du Colombier n = (work->count > Maxfdata) ? Maxfdata : work->count;
5733e12c5d1SDavid du Colombier p->canint = 1;
5743e12c5d1SDavid du Colombier if(p->flushtag != NOTAG)
5753e12c5d1SDavid du Colombier return;
5769a747e4fSDavid du Colombier /* can't just call pread, since directories must update the offset */
5779a747e4fSDavid du Colombier if(f->f->qid.type&QTDIR){
5789a747e4fSDavid du Colombier if(work->offset != f->offset){
5799a747e4fSDavid du Colombier if(work->offset != 0){
5809a747e4fSDavid du Colombier snprint(err, sizeof err, "can't seek in directory from %lld to %lld", f->offset, work->offset);
5819a747e4fSDavid du Colombier reply(work, &thdr, err);
5829a747e4fSDavid du Colombier return;
5839a747e4fSDavid du Colombier }
5849a747e4fSDavid du Colombier if(seek(f->fid, 0, 0) != 0){
5859a747e4fSDavid du Colombier errstr(err, sizeof err);
5869a747e4fSDavid du Colombier reply(work, &thdr, err);
5879a747e4fSDavid du Colombier return;
5889a747e4fSDavid du Colombier }
5899a747e4fSDavid du Colombier f->offset = 0;
5909a747e4fSDavid du Colombier }
5913e12c5d1SDavid du Colombier r = read(f->fid, data, n);
5929a747e4fSDavid du Colombier if(r > 0)
5939a747e4fSDavid du Colombier f->offset += r;
5949a747e4fSDavid du Colombier }else
5959a747e4fSDavid du Colombier r = pread(f->fid, data, n, work->offset);
5963e12c5d1SDavid du Colombier p->canint = 0;
5973e12c5d1SDavid du Colombier if(r < 0) {
5989a747e4fSDavid du Colombier errstr(err, sizeof err);
5993e12c5d1SDavid du Colombier reply(work, &thdr, err);
6003e12c5d1SDavid du Colombier return;
6013e12c5d1SDavid du Colombier }
6023e12c5d1SDavid du Colombier
6033e12c5d1SDavid du Colombier DEBUG(2, "\tread: fd=%d %d bytes\n", f->fid, r);
6043e12c5d1SDavid du Colombier
6053e12c5d1SDavid du Colombier thdr.data = data;
6063e12c5d1SDavid du Colombier thdr.count = r;
6073e12c5d1SDavid du Colombier stats->totread += r;
6083e12c5d1SDavid du Colombier f->nread++;
6093e12c5d1SDavid du Colombier f->bread += r;
6103e12c5d1SDavid du Colombier reply(work, &thdr, 0);
6113e12c5d1SDavid du Colombier
612dc5a79c1SDavid du Colombier update(&stats->rpc[Tread], t);
6133e12c5d1SDavid du Colombier }
6143e12c5d1SDavid du Colombier
6153e12c5d1SDavid du Colombier void
slavewrite(Fsrpc * p)6163e12c5d1SDavid du Colombier slavewrite(Fsrpc *p)
6173e12c5d1SDavid du Colombier {
6189a747e4fSDavid du Colombier char err[ERRMAX];
6193e12c5d1SDavid du Colombier Fcall *work, thdr;
6203e12c5d1SDavid du Colombier Fid *f;
6213e12c5d1SDavid du Colombier int n;
622ab3dc52fSDavid du Colombier vlong t;
6233e12c5d1SDavid du Colombier
6243e12c5d1SDavid du Colombier work = &p->work;
6253e12c5d1SDavid du Colombier
626ab3dc52fSDavid du Colombier t = nsec();
6273e12c5d1SDavid du Colombier
6283e12c5d1SDavid du Colombier f = getfid(work->fid);
6293e12c5d1SDavid du Colombier if(f == 0) {
6309a747e4fSDavid du Colombier reply(work, &thdr, Ebadfid);
6313e12c5d1SDavid du Colombier return;
6323e12c5d1SDavid du Colombier }
6333e12c5d1SDavid du Colombier
6349a747e4fSDavid 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;
6389a747e4fSDavid du Colombier n = pwrite(f->fid, work->data, n, work->offset);
6393e12c5d1SDavid du Colombier p->canint = 0;
6403e12c5d1SDavid du Colombier if(n < 0) {
6419a747e4fSDavid du Colombier errstr(err, sizeof 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 thdr.count = n;
6493e12c5d1SDavid du Colombier f->nwrite++;
6503e12c5d1SDavid du Colombier f->bwrite += n;
6513e12c5d1SDavid du Colombier stats->totwrite += n;
6523e12c5d1SDavid du Colombier reply(work, &thdr, 0);
6533e12c5d1SDavid du Colombier
654dc5a79c1SDavid du Colombier update(&stats->rpc[Twrite], t);
6553e12c5d1SDavid du Colombier }
6563e12c5d1SDavid du Colombier
6573e12c5d1SDavid du Colombier void
reopen(Fid * f)6583e12c5d1SDavid du Colombier reopen(Fid *f)
6593e12c5d1SDavid du Colombier {
6603e12c5d1SDavid du Colombier USED(f);
6613e12c5d1SDavid du Colombier fatal("reopen");
6623e12c5d1SDavid du Colombier }
6633e12c5d1SDavid du Colombier
6643e12c5d1SDavid du Colombier void
flushaction(void * a,char * cause)6653e12c5d1SDavid du Colombier flushaction(void *a, char *cause)
6663e12c5d1SDavid du Colombier {
6673e12c5d1SDavid du Colombier USED(a);
6683e12c5d1SDavid du Colombier if(strncmp(cause, "kill", 4) == 0)
6693e12c5d1SDavid du Colombier noted(NDFLT);
6703e12c5d1SDavid du Colombier
6713e12c5d1SDavid du Colombier noted(NCONT);
6723e12c5d1SDavid du Colombier }
673