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