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