1*7dd7cddfSDavid du Colombier 23e12c5d1SDavid du Colombier /* 33e12c5d1SDavid du Colombier * exportfs - Export a plan 9 name space across a network 43e12c5d1SDavid du Colombier */ 53e12c5d1SDavid du Colombier #include <u.h> 63e12c5d1SDavid du Colombier #include <libc.h> 73e12c5d1SDavid du Colombier #include <auth.h> 8219b2ee8SDavid du Colombier #include <fcall.h> 93e12c5d1SDavid du Colombier #define Extern 103e12c5d1SDavid du Colombier #include "exportfs.h" 113e12c5d1SDavid du Colombier 12*7dd7cddfSDavid du Colombier #define QIDMODE (CHDIR|CHAPPEND|CHEXCL|CHMOUNT) 13*7dd7cddfSDavid du Colombier ulong newqid = ~QIDMODE; 14*7dd7cddfSDavid du Colombier 153e12c5d1SDavid du Colombier void (*fcalls[])(Fsrpc*) = 163e12c5d1SDavid du Colombier { 173e12c5d1SDavid du Colombier [Tnop] Xnop, 183e12c5d1SDavid du Colombier [Tsession] Xsession, 193e12c5d1SDavid du Colombier [Tflush] Xflush, 203e12c5d1SDavid du Colombier [Tattach] Xattach, 213e12c5d1SDavid du Colombier [Tclone] Xclone, 223e12c5d1SDavid du Colombier [Twalk] Xwalk, 233e12c5d1SDavid du Colombier [Topen] slave, 243e12c5d1SDavid du Colombier [Tcreate] Xcreate, 253e12c5d1SDavid du Colombier [Tclunk] Xclunk, 263e12c5d1SDavid du Colombier [Tread] slave, 273e12c5d1SDavid du Colombier [Twrite] slave, 283e12c5d1SDavid du Colombier [Tremove] Xremove, 293e12c5d1SDavid du Colombier [Tstat] Xstat, 303e12c5d1SDavid du Colombier [Twstat] Xwstat, 313e12c5d1SDavid du Colombier [Tclwalk] Xclwalk, 323e12c5d1SDavid du Colombier }; 333e12c5d1SDavid du Colombier 34*7dd7cddfSDavid du Colombier /* accounting and debugging counters */ 35*7dd7cddfSDavid du Colombier int filecnt; 36*7dd7cddfSDavid du Colombier int freecnt; 37*7dd7cddfSDavid du Colombier int qidcnt; 38*7dd7cddfSDavid du Colombier int qfreecnt; 39*7dd7cddfSDavid du Colombier int ncollision; 40*7dd7cddfSDavid du Colombier 41*7dd7cddfSDavid du Colombier int fflag; 42*7dd7cddfSDavid du Colombier int netfd; 43*7dd7cddfSDavid du Colombier int filter(int); 44219b2ee8SDavid du Colombier 45219b2ee8SDavid du Colombier void 46219b2ee8SDavid du Colombier usage(void) 47219b2ee8SDavid du Colombier { 48219b2ee8SDavid du Colombier fprint(2, "usage: %s [-as] [-c ctlfile]\n", argv0); 49219b2ee8SDavid du Colombier fatal("usage"); 50219b2ee8SDavid du Colombier } 51219b2ee8SDavid du Colombier 523e12c5d1SDavid du Colombier void 533e12c5d1SDavid du Colombier main(int argc, char **argv) 543e12c5d1SDavid du Colombier { 553e12c5d1SDavid du Colombier char buf[128]; 563e12c5d1SDavid du Colombier Fsrpc *r; 57bd389b36SDavid du Colombier int n, srv; 583e12c5d1SDavid du Colombier char *dbfile; 59219b2ee8SDavid du Colombier char user[NAMELEN]; 603e12c5d1SDavid du Colombier 613e12c5d1SDavid du Colombier dbfile = "/tmp/exportdb"; 62bd389b36SDavid du Colombier srv = 0; 633e12c5d1SDavid du Colombier 643e12c5d1SDavid du Colombier ARGBEGIN{ 653e12c5d1SDavid du Colombier case 'a': 66*7dd7cddfSDavid du Colombier // fprint(2, "srvauth\n"); 67219b2ee8SDavid du Colombier if(srvauth(0, user) < 0) 68219b2ee8SDavid du Colombier fatal("srvauth"); 69*7dd7cddfSDavid du Colombier // fprint(2, "newns\n"); 70219b2ee8SDavid du Colombier if(newns(user, 0) < 0) 71219b2ee8SDavid du Colombier fatal("newns"); 723e12c5d1SDavid du Colombier putenv("service", "exportfs"); 733e12c5d1SDavid du Colombier break; 743e12c5d1SDavid du Colombier 753e12c5d1SDavid du Colombier case 'd': 763e12c5d1SDavid du Colombier dbg++; 773e12c5d1SDavid du Colombier break; 783e12c5d1SDavid du Colombier 793e12c5d1SDavid du Colombier case 'f': 803e12c5d1SDavid du Colombier dbfile = ARGF(); 813e12c5d1SDavid du Colombier break; 823e12c5d1SDavid du Colombier 83*7dd7cddfSDavid du Colombier case 'F': 84*7dd7cddfSDavid du Colombier fflag++; 85*7dd7cddfSDavid du Colombier break; 86*7dd7cddfSDavid du Colombier 87bd389b36SDavid du Colombier case 's': 88bd389b36SDavid du Colombier srv++; 89bd389b36SDavid du Colombier break; 90219b2ee8SDavid du Colombier 91219b2ee8SDavid du Colombier default: 92219b2ee8SDavid du Colombier usage(); 933e12c5d1SDavid du Colombier }ARGEND 943e12c5d1SDavid du Colombier USED(argc, argv); 953e12c5d1SDavid du Colombier 963e12c5d1SDavid du Colombier if(dbg) { 973e12c5d1SDavid du Colombier n = create(dbfile, OWRITE|OTRUNC, 0666); 98*7dd7cddfSDavid du Colombier dup(n, DFD); 993e12c5d1SDavid du Colombier close(n); 1003e12c5d1SDavid du Colombier } 1013e12c5d1SDavid du Colombier 102*7dd7cddfSDavid du Colombier DEBUG(DFD, "exportfs: started\n"); 103219b2ee8SDavid du Colombier 1043e12c5d1SDavid du Colombier rfork(RFNOTEG); 1053e12c5d1SDavid du Colombier 106*7dd7cddfSDavid du Colombier Workq = mallocz(sizeof(Fsrpc)*Nr_workbufs, 1); 107*7dd7cddfSDavid du Colombier fhash = mallocz(sizeof(Fid*)*FHASHSIZE, 1); 1083e12c5d1SDavid du Colombier 1093e12c5d1SDavid du Colombier if(Workq == 0 || fhash == 0) 1103e12c5d1SDavid du Colombier fatal("no initial memory"); 1113e12c5d1SDavid du Colombier 1123e12c5d1SDavid du Colombier 1133e12c5d1SDavid du Colombier fmtinstall('F', fcallconv); 1143e12c5d1SDavid du Colombier 1153e12c5d1SDavid du Colombier /* 116219b2ee8SDavid du Colombier * Get tree to serve from network connection, 117219b2ee8SDavid du Colombier * check we can get there and ack the connection 1183e12c5d1SDavid du Colombier */ 119219b2ee8SDavid du Colombier if(srv) { 120bd389b36SDavid du Colombier chdir("/"); 121*7dd7cddfSDavid du Colombier DEBUG(DFD, "invoked as server for /"); 122219b2ee8SDavid du Colombier } 123bd389b36SDavid du Colombier else { 124bd389b36SDavid du Colombier buf[0] = 0; 1253e12c5d1SDavid du Colombier n = read(0, buf, sizeof(buf)); 126bd389b36SDavid du Colombier if(n < 0) { 1273e12c5d1SDavid du Colombier errstr(buf); 128bd389b36SDavid du Colombier fprint(0, "read(0): %s", buf); 129*7dd7cddfSDavid du Colombier DEBUG(DFD, "read(0): %s", buf); 1303e12c5d1SDavid du Colombier exits(buf); 1313e12c5d1SDavid du Colombier } 132219b2ee8SDavid du Colombier buf[n] = 0; 133bd389b36SDavid du Colombier if(chdir(buf) < 0) { 134bd389b36SDavid du Colombier char ebuf[128]; 135bd389b36SDavid du Colombier errstr(ebuf); 136bd389b36SDavid du Colombier fprint(0, "chdir(%d:\"%s\"): %s", n, buf, ebuf); 137*7dd7cddfSDavid du Colombier DEBUG(DFD, "chdir(%d:\"%s\"): %s", n, buf, ebuf); 138bd389b36SDavid du Colombier exits(ebuf); 139bd389b36SDavid du Colombier } 140bd389b36SDavid du Colombier } 1413e12c5d1SDavid du Colombier 142*7dd7cddfSDavid du Colombier DEBUG(DFD, "initing root\n"); 1433e12c5d1SDavid du Colombier initroot(); 1443e12c5d1SDavid du Colombier 145*7dd7cddfSDavid du Colombier DEBUG(DFD, "exportfs: %s\n", buf); 1463e12c5d1SDavid du Colombier 147bd389b36SDavid du Colombier if(srv == 0 && write(0, "OK", 2) != 2) 1483e12c5d1SDavid du Colombier fatal("open ack write"); 1493e12c5d1SDavid du Colombier 1503e12c5d1SDavid du Colombier /* 151*7dd7cddfSDavid du Colombier * push the fcall line discipline 152*7dd7cddfSDavid du Colombier */ 153*7dd7cddfSDavid du Colombier netfd = 0; 154*7dd7cddfSDavid du Colombier if(fflag) 155*7dd7cddfSDavid du Colombier netfd = filter(netfd); 156*7dd7cddfSDavid du Colombier 157*7dd7cddfSDavid du Colombier /* 1583e12c5d1SDavid du Colombier * Start serving file requests from the network 1593e12c5d1SDavid du Colombier */ 1603e12c5d1SDavid du Colombier for(;;) { 1613e12c5d1SDavid du Colombier r = getsbuf(); 1623e12c5d1SDavid du Colombier if(r == 0) 1633e12c5d1SDavid du Colombier fatal("Out of service buffers"); 1643e12c5d1SDavid du Colombier 1653e12c5d1SDavid du Colombier do 166*7dd7cddfSDavid du Colombier n = read9p(netfd, r->buf, sizeof(r->buf)); 1673e12c5d1SDavid du Colombier while(n == 0); 1683e12c5d1SDavid du Colombier 1693e12c5d1SDavid du Colombier if(n < 0) 1703e12c5d1SDavid du Colombier fatal("server read"); 1713e12c5d1SDavid du Colombier 1723e12c5d1SDavid du Colombier 1733e12c5d1SDavid du Colombier if(convM2S(r->buf, &r->work, n) == 0) 1743e12c5d1SDavid du Colombier fatal("format error"); 1753e12c5d1SDavid du Colombier 176*7dd7cddfSDavid du Colombier DEBUG(DFD, "%F\n", &r->work); 1773e12c5d1SDavid du Colombier (fcalls[r->work.type])(r); 1783e12c5d1SDavid du Colombier } 1793e12c5d1SDavid du Colombier } 1803e12c5d1SDavid du Colombier 1813e12c5d1SDavid du Colombier void 1823e12c5d1SDavid du Colombier reply(Fcall *r, Fcall *t, char *err) 1833e12c5d1SDavid du Colombier { 1843e12c5d1SDavid du Colombier char data[MAXFDATA+MAXMSG]; 1853e12c5d1SDavid du Colombier int n; 1863e12c5d1SDavid du Colombier 1873e12c5d1SDavid du Colombier t->tag = r->tag; 1883e12c5d1SDavid du Colombier t->fid = r->fid; 1893e12c5d1SDavid du Colombier if(err) { 1903e12c5d1SDavid du Colombier t->type = Rerror; 1913e12c5d1SDavid du Colombier strncpy(t->ename, err, ERRLEN); 1923e12c5d1SDavid du Colombier } 1933e12c5d1SDavid du Colombier else 1943e12c5d1SDavid du Colombier t->type = r->type + 1; 1953e12c5d1SDavid du Colombier 196*7dd7cddfSDavid du Colombier DEBUG(DFD, "\t%F\n", t); 1973e12c5d1SDavid du Colombier 1983e12c5d1SDavid du Colombier n = convS2M(t, data); 199*7dd7cddfSDavid du Colombier if(write9p(netfd, data, n)!=n) 2003e12c5d1SDavid du Colombier fatal("mount write"); 2013e12c5d1SDavid du Colombier } 2023e12c5d1SDavid du Colombier 2033e12c5d1SDavid du Colombier Fid * 2043e12c5d1SDavid du Colombier getfid(int nr) 2053e12c5d1SDavid du Colombier { 2063e12c5d1SDavid du Colombier Fid *f; 2073e12c5d1SDavid du Colombier 2083e12c5d1SDavid du Colombier for(f = fidhash(nr); f; f = f->next) 2093e12c5d1SDavid du Colombier if(f->nr == nr) 2103e12c5d1SDavid du Colombier return f; 2113e12c5d1SDavid du Colombier 2123e12c5d1SDavid du Colombier return 0; 2133e12c5d1SDavid du Colombier } 2143e12c5d1SDavid du Colombier 2153e12c5d1SDavid du Colombier int 2163e12c5d1SDavid du Colombier freefid(int nr) 2173e12c5d1SDavid du Colombier { 2183e12c5d1SDavid du Colombier Fid *f, **l; 219219b2ee8SDavid du Colombier char buf[128]; 2203e12c5d1SDavid du Colombier 2213e12c5d1SDavid du Colombier l = &fidhash(nr); 2223e12c5d1SDavid du Colombier for(f = *l; f; f = f->next) { 2233e12c5d1SDavid du Colombier if(f->nr == nr) { 224219b2ee8SDavid du Colombier if(f->mpend) 225219b2ee8SDavid du Colombier f->mpend->busy = 0; 226219b2ee8SDavid du Colombier if(f->mid) { 227219b2ee8SDavid du Colombier sprint(buf, "/mnt/exportfs/%d", f->mid); 228219b2ee8SDavid du Colombier unmount(0, buf); 229219b2ee8SDavid du Colombier psmap[f->mid] = 0; 230219b2ee8SDavid du Colombier } 231*7dd7cddfSDavid du Colombier freefile(f->f); 232*7dd7cddfSDavid du Colombier f->f = nil; 2333e12c5d1SDavid du Colombier *l = f->next; 2343e12c5d1SDavid du Colombier f->next = fidfree; 2353e12c5d1SDavid du Colombier fidfree = f; 2363e12c5d1SDavid du Colombier return 1; 2373e12c5d1SDavid du Colombier } 2383e12c5d1SDavid du Colombier l = &f->next; 2393e12c5d1SDavid du Colombier } 2403e12c5d1SDavid du Colombier 2413e12c5d1SDavid du Colombier return 0; 2423e12c5d1SDavid du Colombier } 2433e12c5d1SDavid du Colombier 2443e12c5d1SDavid du Colombier Fid * 2453e12c5d1SDavid du Colombier newfid(int nr) 2463e12c5d1SDavid du Colombier { 2473e12c5d1SDavid du Colombier Fid *new, **l; 2483e12c5d1SDavid du Colombier int i; 2493e12c5d1SDavid du Colombier 2503e12c5d1SDavid du Colombier l = &fidhash(nr); 2513e12c5d1SDavid du Colombier for(new = *l; new; new = new->next) 2523e12c5d1SDavid du Colombier if(new->nr == nr) 2533e12c5d1SDavid du Colombier return 0; 2543e12c5d1SDavid du Colombier 2553e12c5d1SDavid du Colombier if(fidfree == 0) { 256*7dd7cddfSDavid du Colombier fidfree = mallocz(sizeof(Fid) * Fidchunk, 1); 2573e12c5d1SDavid du Colombier if(fidfree == 0) 2583e12c5d1SDavid du Colombier fatal("out of memory"); 2593e12c5d1SDavid du Colombier 2603e12c5d1SDavid du Colombier for(i = 0; i < Fidchunk-1; i++) 2613e12c5d1SDavid du Colombier fidfree[i].next = &fidfree[i+1]; 2623e12c5d1SDavid du Colombier 2633e12c5d1SDavid du Colombier fidfree[Fidchunk-1].next = 0; 2643e12c5d1SDavid du Colombier } 2653e12c5d1SDavid du Colombier 2663e12c5d1SDavid du Colombier new = fidfree; 2673e12c5d1SDavid du Colombier fidfree = new->next; 2683e12c5d1SDavid du Colombier 2693e12c5d1SDavid du Colombier memset(new, 0, sizeof(Fid)); 2703e12c5d1SDavid du Colombier new->next = *l; 2713e12c5d1SDavid du Colombier *l = new; 2723e12c5d1SDavid du Colombier new->nr = nr; 2733e12c5d1SDavid du Colombier new->fid = -1; 274219b2ee8SDavid du Colombier new->mpend = 0; 275219b2ee8SDavid du Colombier new->mid = 0; 2763e12c5d1SDavid du Colombier 2773e12c5d1SDavid du Colombier return new; 2783e12c5d1SDavid du Colombier } 2793e12c5d1SDavid du Colombier 2803e12c5d1SDavid du Colombier Fsrpc * 2813e12c5d1SDavid du Colombier getsbuf(void) 2823e12c5d1SDavid du Colombier { 2833e12c5d1SDavid du Colombier static int ap; 284*7dd7cddfSDavid du Colombier int look, rounds; 2853e12c5d1SDavid du Colombier Fsrpc *wb; 2863e12c5d1SDavid du Colombier 287*7dd7cddfSDavid du Colombier for(rounds = 0; rounds < 10; rounds++) { 2883e12c5d1SDavid du Colombier for(look = 0; look < Nr_workbufs; look++) { 2893e12c5d1SDavid du Colombier if(++ap == Nr_workbufs) 2903e12c5d1SDavid du Colombier ap = 0; 2913e12c5d1SDavid du Colombier if(Workq[ap].busy == 0) 2923e12c5d1SDavid du Colombier break; 2933e12c5d1SDavid du Colombier } 2943e12c5d1SDavid du Colombier 295*7dd7cddfSDavid du Colombier if(look == Nr_workbufs){ 296*7dd7cddfSDavid du Colombier sleep(10 * rounds); 297*7dd7cddfSDavid du Colombier continue; 298*7dd7cddfSDavid du Colombier } 2993e12c5d1SDavid du Colombier 3003e12c5d1SDavid du Colombier wb = &Workq[ap]; 3013e12c5d1SDavid du Colombier wb->pid = 0; 3023e12c5d1SDavid du Colombier wb->canint = 0; 3033e12c5d1SDavid du Colombier wb->flushtag = NOTAG; 3043e12c5d1SDavid du Colombier wb->busy = 1; 3053e12c5d1SDavid du Colombier 3063e12c5d1SDavid du Colombier return wb; 3073e12c5d1SDavid du Colombier } 308*7dd7cddfSDavid du Colombier fatal("No more work buffers"); 309*7dd7cddfSDavid du Colombier return nil; 310*7dd7cddfSDavid du Colombier } 3113e12c5d1SDavid du Colombier 312*7dd7cddfSDavid du Colombier void 313*7dd7cddfSDavid du Colombier freefile(File *f) 3143e12c5d1SDavid du Colombier { 315*7dd7cddfSDavid du Colombier File *parent, *child; 3163e12c5d1SDavid du Colombier 317*7dd7cddfSDavid du Colombier Loop: 318*7dd7cddfSDavid du Colombier f->ref--; 319*7dd7cddfSDavid du Colombier if(f->ref > 0) 320*7dd7cddfSDavid du Colombier return; 321*7dd7cddfSDavid du Colombier freecnt++; 322*7dd7cddfSDavid du Colombier if(f->ref < 0) abort(); 323*7dd7cddfSDavid du Colombier DEBUG(DFD, "free %s\n", f->name); 324*7dd7cddfSDavid du Colombier /* delete from parent */ 325*7dd7cddfSDavid du Colombier parent = f->parent; 326*7dd7cddfSDavid du Colombier if(parent->child == f) 327*7dd7cddfSDavid du Colombier parent->child = f->childlist; 328*7dd7cddfSDavid du Colombier else{ 329*7dd7cddfSDavid du Colombier for(child=parent->child; child->childlist!=f; child=child->childlist) 330*7dd7cddfSDavid du Colombier if(child->childlist == nil) 331*7dd7cddfSDavid du Colombier fatal("bad child list"); 332*7dd7cddfSDavid du Colombier child->childlist = f->childlist; 333*7dd7cddfSDavid du Colombier } 334*7dd7cddfSDavid du Colombier freeqid(f->qidt); 335*7dd7cddfSDavid du Colombier free(f); 336*7dd7cddfSDavid du Colombier f = parent; 337*7dd7cddfSDavid du Colombier if(f != nil) 338*7dd7cddfSDavid du Colombier goto Loop; 3393e12c5d1SDavid du Colombier } 3403e12c5d1SDavid du Colombier 3413e12c5d1SDavid du Colombier File * 3423e12c5d1SDavid du Colombier file(File *parent, char *name) 3433e12c5d1SDavid du Colombier { 344219b2ee8SDavid du Colombier Dir dir; 3453e12c5d1SDavid du Colombier char buf[128]; 346*7dd7cddfSDavid du Colombier File *f; 3473e12c5d1SDavid du Colombier 348*7dd7cddfSDavid du Colombier DEBUG(DFD, "\tfile: 0x%p %s name %s\n", parent, parent->name, name); 3493e12c5d1SDavid du Colombier 3503e12c5d1SDavid du Colombier makepath(buf, parent, name); 3513e12c5d1SDavid du Colombier if(dirstat(buf, &dir) < 0) 352*7dd7cddfSDavid du Colombier return nil; 3533e12c5d1SDavid du Colombier 354*7dd7cddfSDavid du Colombier for(f = parent->child; f; f = f->childlist) 355*7dd7cddfSDavid du Colombier if(strcmp(name, f->name) == 0) 356*7dd7cddfSDavid du Colombier break; 357*7dd7cddfSDavid du Colombier 358*7dd7cddfSDavid du Colombier if(f == nil){ 359*7dd7cddfSDavid du Colombier f = mallocz(sizeof(File), 1); 360*7dd7cddfSDavid du Colombier if(f == 0) 3613e12c5d1SDavid du Colombier fatal("no memory"); 362*7dd7cddfSDavid du Colombier strcpy(f->name, name); 3633e12c5d1SDavid du Colombier 364*7dd7cddfSDavid du Colombier f->parent = parent; 365*7dd7cddfSDavid du Colombier f->childlist = parent->child; 366*7dd7cddfSDavid du Colombier parent->child = f; 367*7dd7cddfSDavid du Colombier parent->ref++; 368*7dd7cddfSDavid du Colombier f->ref = 0; 369*7dd7cddfSDavid du Colombier filecnt++; 370*7dd7cddfSDavid du Colombier } 371*7dd7cddfSDavid du Colombier f->ref++; 372*7dd7cddfSDavid du Colombier f->qid.vers = dir.qid.vers; 373*7dd7cddfSDavid du Colombier f->qidt = uniqueqid(&dir); 374*7dd7cddfSDavid du Colombier f->qid.path = f->qidt->uniqpath; 3753e12c5d1SDavid du Colombier 376*7dd7cddfSDavid du Colombier f->inval = 0; 3773e12c5d1SDavid du Colombier 378*7dd7cddfSDavid du Colombier 379*7dd7cddfSDavid du Colombier return f; 3803e12c5d1SDavid du Colombier } 3813e12c5d1SDavid du Colombier 3823e12c5d1SDavid du Colombier void 3833e12c5d1SDavid du Colombier initroot(void) 3843e12c5d1SDavid du Colombier { 3853e12c5d1SDavid du Colombier Dir dir; 3863e12c5d1SDavid du Colombier 387*7dd7cddfSDavid du Colombier root = mallocz(sizeof(File), 1); 3883e12c5d1SDavid du Colombier if(root == 0) 3893e12c5d1SDavid du Colombier fatal("no memory"); 3903e12c5d1SDavid du Colombier 3913e12c5d1SDavid du Colombier strcpy(root->name, "."); 3923e12c5d1SDavid du Colombier if(dirstat(root->name, &dir) < 0) 3933e12c5d1SDavid du Colombier fatal("root stat"); 3943e12c5d1SDavid du Colombier 395*7dd7cddfSDavid du Colombier root->ref = 1; 3963e12c5d1SDavid du Colombier root->qid.vers = dir.qid.vers; 397*7dd7cddfSDavid du Colombier root->qidt = uniqueqid(&dir); 398*7dd7cddfSDavid du Colombier root->qid.path = root->qidt->uniqpath; 399219b2ee8SDavid du Colombier 400*7dd7cddfSDavid du Colombier psmpt = mallocz(sizeof(File), 1); 401219b2ee8SDavid du Colombier if(psmpt == 0) 402219b2ee8SDavid du Colombier fatal("no memory"); 403219b2ee8SDavid du Colombier 404219b2ee8SDavid du Colombier strcpy(psmpt->name, "/"); 405219b2ee8SDavid du Colombier if(dirstat(psmpt->name, &dir) < 0) 406219b2ee8SDavid du Colombier return; 407219b2ee8SDavid du Colombier 408*7dd7cddfSDavid du Colombier psmpt->ref = 1; 409219b2ee8SDavid du Colombier psmpt->qid.vers = dir.qid.vers; 410*7dd7cddfSDavid du Colombier psmpt->qidt = uniqueqid(&dir); 411*7dd7cddfSDavid du Colombier psmpt->qid.path = psmpt->qidt->uniqpath; 412219b2ee8SDavid du Colombier 413219b2ee8SDavid du Colombier psmpt = file(psmpt, "mnt"); 414219b2ee8SDavid du Colombier if(psmpt == 0) 415219b2ee8SDavid du Colombier return; 416219b2ee8SDavid du Colombier psmpt = file(psmpt, "exportfs"); 4173e12c5d1SDavid du Colombier } 4183e12c5d1SDavid du Colombier 4193e12c5d1SDavid du Colombier void 4203e12c5d1SDavid du Colombier makepath(char *s, File *p, char *name) 4213e12c5d1SDavid du Colombier { 4223e12c5d1SDavid du Colombier int i; 423219b2ee8SDavid du Colombier char *c, *seg[256]; 4243e12c5d1SDavid du Colombier 4253e12c5d1SDavid du Colombier seg[0] = name; 4263e12c5d1SDavid du Colombier for(i = 1; i < 100 && p; i++, p = p->parent) 4273e12c5d1SDavid du Colombier seg[i] = p->name; 4283e12c5d1SDavid du Colombier 4293e12c5d1SDavid du Colombier while(i--) { 4303e12c5d1SDavid du Colombier for(c = seg[i]; *c; c++) 4313e12c5d1SDavid du Colombier *s++ = *c; 4323e12c5d1SDavid du Colombier *s++ = '/'; 4333e12c5d1SDavid du Colombier } 4343e12c5d1SDavid du Colombier while(s[-1] == '/') 4353e12c5d1SDavid du Colombier s--; 4363e12c5d1SDavid du Colombier *s = '\0'; 4373e12c5d1SDavid du Colombier } 4383e12c5d1SDavid du Colombier 439*7dd7cddfSDavid du Colombier int 440*7dd7cddfSDavid du Colombier qidhash(ulong path) 441*7dd7cddfSDavid du Colombier { 442*7dd7cddfSDavid du Colombier int h, n; 443*7dd7cddfSDavid du Colombier 444*7dd7cddfSDavid du Colombier h = 0; 445*7dd7cddfSDavid du Colombier for(n=0; n<32; n+=Nqidbits){ 446*7dd7cddfSDavid du Colombier h ^= path; 447*7dd7cddfSDavid du Colombier path >>= Nqidbits; 448*7dd7cddfSDavid du Colombier } 449*7dd7cddfSDavid du Colombier return h & (Nqidtab-1); 450*7dd7cddfSDavid du Colombier } 451*7dd7cddfSDavid du Colombier 452*7dd7cddfSDavid du Colombier void 453*7dd7cddfSDavid du Colombier freeqid(Qidtab *q) 454*7dd7cddfSDavid du Colombier { 455*7dd7cddfSDavid du Colombier ulong h; 456*7dd7cddfSDavid du Colombier Qidtab *l; 457*7dd7cddfSDavid du Colombier 458*7dd7cddfSDavid du Colombier q->ref--; 459*7dd7cddfSDavid du Colombier if(q->ref > 0) 460*7dd7cddfSDavid du Colombier return; 461*7dd7cddfSDavid du Colombier qfreecnt++; 462*7dd7cddfSDavid du Colombier h = qidhash(q->path); 463*7dd7cddfSDavid du Colombier if(qidtab[h] == q) 464*7dd7cddfSDavid du Colombier qidtab[h] = q->next; 465*7dd7cddfSDavid du Colombier else{ 466*7dd7cddfSDavid du Colombier for(l=qidtab[h]; l->next!=q; l=l->next) 467*7dd7cddfSDavid du Colombier if(l->next == nil) 468*7dd7cddfSDavid du Colombier fatal("bad qid list"); 469*7dd7cddfSDavid du Colombier l->next = q->next; 470*7dd7cddfSDavid du Colombier } 471*7dd7cddfSDavid du Colombier free(q); 472*7dd7cddfSDavid du Colombier } 473*7dd7cddfSDavid du Colombier 474*7dd7cddfSDavid du Colombier Qidtab* 475*7dd7cddfSDavid du Colombier qidlookup(Dir *d) 476*7dd7cddfSDavid du Colombier { 477*7dd7cddfSDavid du Colombier ulong h; 478*7dd7cddfSDavid du Colombier Qidtab *q; 479*7dd7cddfSDavid du Colombier 480*7dd7cddfSDavid du Colombier h = qidhash(d->qid.path); 481*7dd7cddfSDavid du Colombier for(q=qidtab[h]; q!=nil; q=q->next) 482*7dd7cddfSDavid du Colombier if(q->type==d->type && q->dev==d->dev && q->path==d->qid.path) 483*7dd7cddfSDavid du Colombier return q; 484*7dd7cddfSDavid du Colombier return nil; 485*7dd7cddfSDavid du Colombier } 486*7dd7cddfSDavid du Colombier 487*7dd7cddfSDavid du Colombier int 488*7dd7cddfSDavid du Colombier qidexists(ulong path) 489*7dd7cddfSDavid du Colombier { 490*7dd7cddfSDavid du Colombier int h; 491*7dd7cddfSDavid du Colombier Qidtab *q; 492*7dd7cddfSDavid du Colombier 493*7dd7cddfSDavid du Colombier for(h=0; h<Nqidtab; h++) 494*7dd7cddfSDavid du Colombier for(q=qidtab[h]; q!=nil; q=q->next) 495*7dd7cddfSDavid du Colombier if(q->uniqpath == path) 496*7dd7cddfSDavid du Colombier return 1; 497*7dd7cddfSDavid du Colombier return 0; 498*7dd7cddfSDavid du Colombier } 499*7dd7cddfSDavid du Colombier 500*7dd7cddfSDavid du Colombier Qidtab* 501*7dd7cddfSDavid du Colombier uniqueqid(Dir *d) 502*7dd7cddfSDavid du Colombier { 503*7dd7cddfSDavid du Colombier ulong h, path; 504*7dd7cddfSDavid du Colombier Qidtab *q; 505*7dd7cddfSDavid du Colombier 506*7dd7cddfSDavid du Colombier q = qidlookup(d); 507*7dd7cddfSDavid du Colombier if(q != nil){ 508*7dd7cddfSDavid du Colombier q->ref++; 509*7dd7cddfSDavid du Colombier return q; 510*7dd7cddfSDavid du Colombier } 511*7dd7cddfSDavid du Colombier path = d->qid.path; 512*7dd7cddfSDavid du Colombier while(qidexists(path)){ 513*7dd7cddfSDavid du Colombier /* collision: find a new one */ 514*7dd7cddfSDavid du Colombier ncollision++; 515*7dd7cddfSDavid du Colombier DEBUG(DFD, "collision on %s\n", d->name); 516*7dd7cddfSDavid du Colombier path = newqid--; 517*7dd7cddfSDavid du Colombier if(newqid == 0) 518*7dd7cddfSDavid du Colombier newqid = ~QIDMODE; 519*7dd7cddfSDavid du Colombier path |= d->qid.path & (CHDIR|CHAPPEND|CHEXCL|CHMOUNT); 520*7dd7cddfSDavid du Colombier } 521*7dd7cddfSDavid du Colombier q = mallocz(sizeof(Qidtab), 1); 522*7dd7cddfSDavid du Colombier if(q == nil) 523*7dd7cddfSDavid du Colombier fatal("no memory for qid table"); 524*7dd7cddfSDavid du Colombier qidcnt++; 525*7dd7cddfSDavid du Colombier q->ref = 1; 526*7dd7cddfSDavid du Colombier q->type = d->type; 527*7dd7cddfSDavid du Colombier q->dev = d->dev; 528*7dd7cddfSDavid du Colombier q->path = d->qid.path; 529*7dd7cddfSDavid du Colombier q->uniqpath = path; 530*7dd7cddfSDavid du Colombier h = qidhash(d->qid.path); 531*7dd7cddfSDavid du Colombier q->next = qidtab[h]; 532*7dd7cddfSDavid du Colombier qidtab[h] = q; 533*7dd7cddfSDavid du Colombier return q; 534*7dd7cddfSDavid du Colombier } 535*7dd7cddfSDavid du Colombier 5363e12c5d1SDavid du Colombier void 5373e12c5d1SDavid du Colombier fatal(char *s) 5383e12c5d1SDavid du Colombier { 5393e12c5d1SDavid du Colombier char buf[128]; 5403e12c5d1SDavid du Colombier Proc *m; 5413e12c5d1SDavid du Colombier 5423e12c5d1SDavid du Colombier sprint(buf, "exportfs: %r: %s", s); 5433e12c5d1SDavid du Colombier 5443e12c5d1SDavid du Colombier /* Clear away the slave children */ 5453e12c5d1SDavid du Colombier for(m = Proclist; m; m = m->next) 546219b2ee8SDavid du Colombier postnote(PNPROC, m->pid, "kill"); 5473e12c5d1SDavid du Colombier 548*7dd7cddfSDavid du Colombier DEBUG(DFD, "%s\n", buf); 5493e12c5d1SDavid du Colombier exits(buf); 5503e12c5d1SDavid du Colombier } 5513e12c5d1SDavid du Colombier 552*7dd7cddfSDavid du Colombier /* Network on fd1, mount driver on fd0 */ 553*7dd7cddfSDavid du Colombier int 554*7dd7cddfSDavid du Colombier filter(int fd) 5553e12c5d1SDavid du Colombier { 556*7dd7cddfSDavid du Colombier int p[2]; 5573e12c5d1SDavid du Colombier 558*7dd7cddfSDavid du Colombier if(pipe(p) < 0) 559*7dd7cddfSDavid du Colombier fatal("pipe"); 560*7dd7cddfSDavid du Colombier 561*7dd7cddfSDavid du Colombier switch(rfork(RFNOWAIT|RFPROC|RFFDG)) { 562*7dd7cddfSDavid du Colombier case -1: 563*7dd7cddfSDavid du Colombier fatal("rfork record module"); 564*7dd7cddfSDavid du Colombier case 0: 565*7dd7cddfSDavid du Colombier dup(fd, 1); 566*7dd7cddfSDavid du Colombier close(fd); 567*7dd7cddfSDavid du Colombier dup(p[0], 0); 568*7dd7cddfSDavid du Colombier close(p[0]); 569*7dd7cddfSDavid du Colombier close(p[1]); 570*7dd7cddfSDavid du Colombier execl("/bin/aux/fcall", "fcall", 0); 571*7dd7cddfSDavid du Colombier fatal("exec record module"); 572*7dd7cddfSDavid du Colombier default: 573*7dd7cddfSDavid du Colombier close(fd); 574*7dd7cddfSDavid du Colombier close(p[0]); 5753e12c5d1SDavid du Colombier } 576*7dd7cddfSDavid du Colombier return p[1]; 5773e12c5d1SDavid du Colombier } 578