diff -Nru /n/sources/plan9/sys/src/cmd/exportfs/exportfs.c /sys/src/cmd/exportfs/exportfs.c --- /n/sources/plan9/sys/src/cmd/exportfs/exportfs.c Mon Feb 11 23:12:41 2013 +++ /sys/src/cmd/exportfs/exportfs.c Sun Feb 28 00:00:00 2016 @@ -42,7 +42,6 @@ int qfreecnt; int ncollision; -int netfd; /* initially stdin */ int srvfd = -1; int nonone = 1; char *filterp; @@ -51,13 +50,13 @@ int encproto = Encnone; int readonly; -static void mksecret(char *, uchar *); -static int localread9pmsg(int, void *, uint, ulong *); +static void mksecret(char *, uchar *); +static int localread9pmsg(int, void *, uint, void *); static char *anstring = "tcp!*!0"; char *netdir = "", *local = "", *remote = ""; -int filter(int, char *); +void filter(int, char *, char *); void usage(void) @@ -74,23 +73,22 @@ NetConnInfo *nci; nci = getnetconninfo(nil, fd); - if (nci == nil) + if(nci == nil) return; - netdir = strdup(nci->dir); - local = strdup(nci->lsys); - remote = strdup(nci->rsys); + netdir = estrdup(nci->dir); + local = estrdup(nci->lsys); + remote = estrdup(nci->rsys); freenetconninfo(nci); } void main(int argc, char **argv) { - char buf[ERRMAX], ebuf[ERRMAX], *srvfdfile; - Fsrpc *r; - int doauth, n, fd; + char buf[ERRMAX], ebuf[ERRMAX], initial[4], *ini, *srvfdfile; char *dbfile, *srv, *na, *nsfile, *keyspec; + int doauth, n, fd; AuthInfo *ai; - ulong initial; + Fsrpc *r; dbfile = "/tmp/exportdb"; srv = nil; @@ -166,7 +164,7 @@ break; case 'S': - if(srvfdfile) + if(srvfdfile != nil) usage(); srvfdfile = EARGF(usage()); break; @@ -176,7 +174,7 @@ }ARGEND USED(argc, argv); - if(doauth){ + if(na == nil && doauth){ /* * We use p9any so we don't have to visit this code again, with the * cost that this code is incompatible with the old world, which @@ -193,23 +191,23 @@ putenv("service", "exportfs"); } - if(srvfdfile){ + if(srvfdfile != nil){ if((srvfd = open(srvfdfile, ORDWR)) < 0) - sysfatal("open '%s': %r", srvfdfile); + fatal("open %s: %r", srvfdfile); } - if(na){ + if(na != nil){ if(srv == nil) - sysfatal("-B requires -s"); + fatal("-B requires -s"); local = "me"; remote = na; if((fd = dial(netmkaddr(na, 0, "importfs"), 0, 0, 0)) < 0) - sysfatal("can't dial %s: %r", na); + fatal("can't dial %s: %r", na); ai = auth_proxy(fd, auth_getkey, "proto=p9any role=client %s", keyspec); if(ai == nil) - sysfatal("%r: %s", na); + fatal("%r: %s", na); dup(fd, 0); dup(fd, 1); @@ -224,24 +222,20 @@ close(n); } - if(srvfd >= 0 && srv){ + if(srvfd >= 0 && srv != nil){ fprint(2, "exportfs: -S cannot be used with -r or -s\n"); usage(); } DEBUG(DFD, "exportfs: started\n"); - rfork(RFNOTEG); + rfork(RFNOTEG|RFREND); if(messagesize == 0){ - messagesize = iounit(netfd); + messagesize = iounit(0); if(messagesize == 0) messagesize = 8192+IOHDRSZ; } - - Workq = emallocz(sizeof(Fsrpc)*Nr_workbufs); -// for(i=0; i= buf + sizeof(buf)) + fatal("import parameters too long"); } - if (tokenize(buf, args, nelem(args)) != 2) - fatal("impo arguments invalid: impo%s...\n", buf); + if(tokenize(buf, args, nelem(args)) != 2) + fatal("impo arguments invalid: impo%s...", buf); - if (strcmp(args[0], "aan") == 0) + if(strcmp(args[0], "aan") == 0) filterp = aanfilter; - else if (strcmp(args[0], "nofilter") != 0) - fatal("import filter argument unsupported: %s\n", args[0]); + else if(strcmp(args[0], "nofilter") != 0) + fatal("import filter argument unsupported: %s", args[0]); - if (strcmp(args[1], "ssl") == 0) + if(strcmp(args[1], "ssl") == 0) encproto = Encssl; - else if (strcmp(args[1], "tls") == 0) + else if(strcmp(args[1], "tls") == 0) encproto = Enctls; - else if (strcmp(args[1], "clear") != 0) - fatal("import encryption proto unsupported: %s\n", args[1]); + else if(strcmp(args[1], "clear") != 0) + fatal("import encryption proto unsupported: %s", args[1]); - if (encproto == Enctls) - sysfatal("%s: tls has not yet been implemented", argv[0]); + if(encproto == Enctls) + fatal("%s: tls has not yet been implemented", argv[0]); } - if (encproto != Encnone && ealgs && ai) { - uchar key[16]; - uchar digest[SHA1dlen]; + if(encproto != Encnone && ealgs != nil && ai != nil) { + uchar key[16], digest[SHA1dlen]; char fromclientsecret[21]; char fromserversecret[21]; int i; - memmove(key+4, ai->secret, ai->nsecret); + if(ai->nsecret < 8) + fatal("secret too small for ssl"); + memmove(key+4, ai->secret, 8); /* exchange random numbers */ srand(truerand()); for(i = 0; i < 4; i++) key[i+12] = rand(); - if (initial) - fatal("Protocol botch: old import\n"); - if(readn(netfd, key, 4) != 4) - fatal("can't read key part; %r\n"); + if(ini != nil) + fatal("Protocol botch: old import"); + if(readn(0, key, 4) != 4) + fatal("can't read key part; %r"); - if(write(netfd, key+12, 4) != 4) - fatal("can't write key part; %r\n"); + if(write(0, key+12, 4) != 4) + fatal("can't write key part; %r"); /* scramble into two secrets */ sha1(key, sizeof(key), digest, nil); mksecret(fromclientsecret, digest); mksecret(fromserversecret, digest+10); - if (filterp) - netfd = filter(netfd, filterp); + if(filterp != nil) + filter(0, filterp, na); - switch (encproto) { + switch(encproto) { case Encssl: - netfd = pushssl(netfd, ealgs, fromserversecret, - fromclientsecret, nil); + fd = pushssl(0, ealgs, fromserversecret, fromclientsecret, nil); + if(fd < 0) + fatal("can't establish ssl connection: %r"); + if(fd != 0){ + dup(fd, 0); + close(fd); + } break; case Enctls: default: - fatal("Unsupported encryption protocol\n"); + fatal("Unsupported encryption protocol"); } - - if(netfd < 0) - fatal("can't establish ssl connection: %r"); } - else if (filterp) { - if (initial) - fatal("Protocol botch: don't know how to deal with this\n"); - netfd = filter(netfd, filterp); + else if(filterp != nil) { + if(ini != nil) + fatal("Protocol botch: don't know how to deal with this"); + filter(0, filterp, na); } + dup(0, 1); + + if(ai != nil) + auth_freeAI(ai); /* * Start serving file requests from the network */ for(;;) { r = getsbuf(); - if(r == 0) - fatal("Out of service buffers"); - - n = localread9pmsg(netfd, r->buf, messagesize, &initial); - if(n <= 0) + while((n = localread9pmsg(0, r->buf, messagesize, ini)) == 0) + ; + if(n < 0) fatal(nil); - if(convM2S(r->buf, n, &r->work) == 0) fatal("convM2S format error"); DEBUG(DFD, "%F\n", &r->work); (fcalls[r->work.type])(r); + ini = nil; } } @@ -407,7 +408,7 @@ * cpu relies on this (which needs to be fixed!) -- pb. */ static int -localread9pmsg(int fd, void *abuf, uint n, ulong *initial) +localread9pmsg(int fd, void *abuf, uint n, void *ini) { int m, len; uchar *buf; @@ -415,11 +416,8 @@ buf = abuf; /* read count */ - assert(BIT32SZ == sizeof(ulong)); - if (*initial) { - memcpy(buf, initial, BIT32SZ); - *initial = 0; - } + if(ini != nil) + memcpy(buf, ini, BIT32SZ); else { m = readn(fd, buf, BIT32SZ); if(m != BIT32SZ){ @@ -448,7 +446,7 @@ t->tag = r->tag; t->fid = r->fid; - if(err) { + if(err != nil) { t->type = Rerror; t->ename = err; } @@ -461,10 +459,10 @@ if(data == nil) fatal(Enomem); n = convS2M(t, data, messagesize); - if(write(netfd, data, n)!=n) -{syslog(0, "exportfs", "short write: %r"); - fatal("mount write"); -} + if(write(0, data, n) != n){ + /* not fatal, might have got a note due to flush */ + fprint(2, "exportfs: short write in reply: %r\n"); + } free(data); } @@ -473,11 +471,11 @@ { Fid *f; - for(f = fidhash(nr); f; f = f->next) + for(f = fidhash(nr); f != nil; f = f->next) if(f->nr == nr) return f; - return 0; + return nil; } int @@ -487,18 +485,18 @@ char buf[128]; l = &fidhash(nr); - for(f = *l; f; f = f->next) { + for(f = *l; f != nil; f = f->next) { if(f->nr == nr) { if(f->mid) { - sprint(buf, "/mnt/exportfs/%d", f->mid); + snprint(buf, sizeof(buf), "/mnt/exportfs/%d", f->mid); unmount(0, buf); psmap[f->mid] = 0; } - if(f->f) { + if(f->f != nil) { freefile(f->f); f->f = nil; } - if(f->dir){ + if(f->dir != nil){ free(f->dir); f->dir = nil; } @@ -520,17 +518,17 @@ int i; l = &fidhash(nr); - for(new = *l; new; new = new->next) + for(new = *l; new != nil; new = new->next) if(new->nr == nr) - return 0; + return nil; - if(fidfree == 0) { + if(fidfree == nil) { fidfree = emallocz(sizeof(Fid) * Fidchunk); for(i = 0; i < Fidchunk-1; i++) fidfree[i].next = &fidfree[i+1]; - fidfree[Fidchunk-1].next = 0; + fidfree[Fidchunk-1].next = nil; } new = fidfree; @@ -546,41 +544,45 @@ return new; } +static struct { + Lock; + Fsrpc *free; + + /* statistics */ + int nalloc; + int nfree; +} sbufalloc; + Fsrpc * getsbuf(void) { - static int ap; - int look, rounds; - Fsrpc *wb; - int small_instead_of_fast = 1; - - if(small_instead_of_fast) - ap = 0; /* so we always start looking at the beginning and reuse buffers */ - - for(rounds = 0; rounds < 10; rounds++) { - for(look = 0; look < Nr_workbufs; look++) { - if(++ap == Nr_workbufs) - ap = 0; - if(Workq[ap].busy == 0) - break; - } + Fsrpc *w; - if(look == Nr_workbufs){ - sleep(10 * rounds); - continue; - } - - wb = &Workq[ap]; - wb->pid = 0; - wb->canint = 0; - wb->flushtag = NOTAG; - wb->busy = 1; - if(wb->buf == nil) /* allocate buffers dynamically to keep size down */ - wb->buf = emallocz(messagesize); - return wb; + lock(&sbufalloc); + w = sbufalloc.free; + if(w != nil){ + sbufalloc.free = w->next; + w->next = nil; + sbufalloc.nfree--; + unlock(&sbufalloc); + } else { + sbufalloc.nalloc++; + unlock(&sbufalloc); + w = emallocz(sizeof(*w) + messagesize); } - fatal("No more work buffers"); - return nil; + w->flushtag = NOTAG; + return w; +} + +void +putsbuf(Fsrpc *w) +{ + w->flushtag = NOTAG; + lock(&sbufalloc); + w->next = sbufalloc.free; + sbufalloc.free = w; + sbufalloc.nfree++; + unlock(&sbufalloc); } void @@ -588,30 +590,25 @@ { File *parent, *child; -Loop: - f->ref--; - if(f->ref > 0) - return; - freecnt++; - if(f->ref < 0) abort(); - DEBUG(DFD, "free %s\n", f->name); - /* delete from parent */ - parent = f->parent; - if(parent->child == f) - parent->child = f->childlist; - else{ - for(child=parent->child; child->childlist!=f; child=child->childlist) - if(child->childlist == nil) - fatal("bad child list"); - child->childlist = f->childlist; - } - freeqid(f->qidt); - free(f->name); - f->name = nil; - free(f); - f = parent; - if(f != nil) - goto Loop; + while(--f->ref == 0){ + freecnt++; + DEBUG(DFD, "free %s\n", f->name); + /* delete from parent */ + parent = f->parent; + if(parent->child == f) + parent->child = f->childlist; + else{ + for(child = parent->child; child->childlist != f; child = child->childlist) { + if(child->childlist == nil) + fatal("bad child list"); + } + child->childlist = f->childlist; + } + freeqid(f->qidt); + free(f->name); + free(f); + f = parent; + } } File * @@ -633,7 +630,7 @@ if(dir == nil) return nil; - for(f = parent->child; f; f = f->childlist) + for(f = parent->child; f != nil; f = f->childlist) if(strcmp(name, f->name) == 0) break; @@ -694,7 +691,7 @@ free(dir); psmpt = file(psmpt, "mnt"); - if(psmpt == 0) + if(psmpt == nil) return; psmpt = file(psmpt, "exportfs"); } @@ -711,9 +708,7 @@ seg[i] = p->name; n += strlen(p->name)+1; } - path = malloc(n); - if(path == nil) - fatal("out of memory"); + path = emallocz(n); s = path; while(i--) { @@ -747,8 +742,7 @@ ulong h; Qidtab *l; - q->ref--; - if(q->ref > 0) + if(--q->ref) return; qfreecnt++; h = qidhash(q->path); @@ -815,10 +809,8 @@ path |= newqid<<48; DEBUG(DFD, "assign qid %.16llux\n", path); } - q = mallocz(sizeof(Qidtab), 1); - if(q == nil) - fatal("no memory for qid table"); qidcnt++; + q = emallocz(sizeof(Qidtab)); q->ref = 1; q->type = d->type; q->dev = d->dev; @@ -837,20 +829,20 @@ va_list arg; Proc *m; - if (s) { + if(s != nil) { va_start(arg, s); vsnprint(buf, ERRMAX, s, arg); va_end(arg); } /* Clear away the slave children */ - for(m = Proclist; m; m = m->next) + for(m = Proclist; m != nil; m = m->next) postnote(PNPROC, m->pid, "kill"); - DEBUG(DFD, "%s\n", buf); - if (s) + if(s != nil) { + DEBUG(DFD, "%s\n", buf); sysfatal("%s", buf); /* caution: buf could contain '%' */ - else + } else exits(nil); } @@ -862,6 +854,7 @@ p = mallocz(n, 1); if(p == nil) fatal(Enomem); + setmalloctag(p, getcallerpc(&n)); return p; } @@ -873,65 +866,81 @@ t = strdup(s); if(t == nil) fatal(Enomem); + setmalloctag(t, getcallerpc(&s)); return t; } -/* Network on fd1, mount driver on fd0 */ -int -filter(int fd, char *cmd) +void +filter(int fd, char *cmd, char *host) { - int p[2], lfd, len, nb, argc; - char newport[128], buf[128], devdir[40], *s, *file, *argv[16]; + char addr[128], buf[256], *s, *file, *argv[16]; + int lfd, p[2], len, argc; + + if(host == nil){ + /* Get a free port and post it to the client. */ + if (announce(anstring, addr) < 0) + fatal("filter: Cannot announce %s: %r", anstring); + + snprint(buf, sizeof(buf), "%s/local", addr); + if ((lfd = open(buf, OREAD)) < 0) + fatal("filter: Cannot open %s: %r", buf); + if ((len = read(lfd, buf, sizeof buf - 1)) < 0) + fatal("filter: Cannot read %s: %r", buf); + close(lfd); + buf[len] = '\0'; + if ((s = strchr(buf, '\n')) != nil) + len = s - buf; + if (write(fd, buf, len) != len) + fatal("filter: cannot write port; %r"); + } else { + /* Read address string from connection */ + if ((len = read(fd, buf, sizeof buf - 1)) < 0) + sysfatal("filter: cannot write port; %r"); + buf[len] = '\0'; + + if ((s = strrchr(buf, '!')) == nil) + sysfatal("filter: illegally formatted port %s", buf); + strecpy(addr, addr+sizeof(addr), netmkaddr(host, "tcp", s+1)); + strecpy(strrchr(addr, '!'), addr+sizeof(addr), s); + } - /* Get a free port and post it to the client. */ - if (announce(anstring, devdir) < 0) - sysfatal("filter: Cannot announce %s: %r", anstring); - - snprint(buf, sizeof(buf), "%s/local", devdir); - buf[sizeof buf - 1] = '\0'; - if ((lfd = open(buf, OREAD)) < 0) - sysfatal("filter: Cannot open %s: %r", buf); - if ((len = read(lfd, newport, sizeof newport - 1)) < 0) - sysfatal("filter: Cannot read %s: %r", buf); - close(lfd); - newport[len] = '\0'; - - if ((s = strchr(newport, '\n')) != nil) - *s = '\0'; - - if ((nb = write(fd, newport, len)) < 0) - sysfatal("getport; cannot write port; %r"); - assert(nb == len); + DEBUG(DFD, "filter: %s\n", addr); - argc = tokenize(cmd, argv, nelem(argv)-2); + snprint(buf, sizeof(buf), "%s", cmd); + argc = tokenize(buf, argv, nelem(argv)-3); if (argc == 0) sysfatal("filter: empty command"); - argv[argc++] = buf; + + if(host != nil) + argv[argc++] = "-c"; + argv[argc++] = addr; argv[argc] = nil; + file = argv[0]; - if (s = strrchr(argv[0], '/')) + if((s = strrchr(argv[0], '/')) != nil) argv[0] = s+1; if(pipe(p) < 0) - fatal("pipe"); + sysfatal("pipe: %r"); - switch(rfork(RFNOWAIT|RFPROC|RFFDG)) { + switch(rfork(RFNOWAIT|RFPROC|RFMEM|RFFDG|RFREND)) { case -1: - fatal("rfork record module"); + fatal("filter: rfork; %r\n"); case 0: + close(fd); if (dup(p[0], 1) < 0) - fatal("filter: Cannot dup to 1; %r\n"); + fatal("filter: Cannot dup to 1; %r"); if (dup(p[0], 0) < 0) - fatal("filter: Cannot dup to 0; %r\n"); + fatal("filter: Cannot dup to 0; %r"); close(p[0]); close(p[1]); exec(file, argv); - fatal("exec record module"); + fatal("filter: exec; %r"); default: - close(fd); + dup(p[1], fd); close(p[0]); + close(p[1]); } - return p[1]; } static void diff -Nru /n/sources/plan9/sys/src/cmd/exportfs/exportfs.h /sys/src/cmd/exportfs/exportfs.h --- /n/sources/plan9/sys/src/cmd/exportfs/exportfs.h Sun Dec 25 05:19:31 2005 +++ /sys/src/cmd/exportfs/exportfs.h Sun Feb 28 00:00:00 2016 @@ -14,12 +14,10 @@ struct Fsrpc { - int busy; /* Work buffer has pending rpc to service */ - uintptr pid; /* Pid of slave process executing the rpc */ - int canint; /* Interrupt gate */ + Fsrpc *next; /* freelist */ int flushtag; /* Tag on which to reply to flush */ Fcall work; /* Plan 9 incoming Fcall */ - uchar *buf; /* Data buffer */ + uchar buf[]; /* Data buffer */ }; struct Fid @@ -53,9 +51,10 @@ struct Proc { - uintptr pid; - int busy; + Lock; + Fsrpc *busy; Proc *next; + int pid; }; struct Qidtab @@ -70,9 +69,7 @@ enum { - MAXPROC = 50, FHASHSIZE = 64, - Nr_workbufs = 50, Fidchunk = 1000, Npsmpt = 32, Nqidbits = 5, @@ -83,12 +80,10 @@ char Enotdir[]; char Edupfid[]; char Eopen[]; -char Exmnt[]; char Enomem[]; char Emip[]; char Enopsmt[]; -Extern Fsrpc *Workq; Extern int dbg; Extern File *root; Extern File *psmpt; @@ -121,6 +116,7 @@ int freefid(int); Fid *newfid(int); Fsrpc *getsbuf(void); +void putsbuf(Fsrpc*); void initroot(void); void fatal(char*, ...); char* makepath(File*, char*); @@ -129,7 +125,7 @@ void slaveopen(Fsrpc*); void slaveread(Fsrpc*); void slavewrite(Fsrpc*); -void blockingslave(void); +void blockingslave(Proc*); void reopen(Fid *f); void noteproc(int, char*); void flushaction(void*, char*); diff -Nru /n/sources/plan9/sys/src/cmd/exportfs/exportsrv.c /sys/src/cmd/exportfs/exportsrv.c --- /n/sources/plan9/sys/src/cmd/exportfs/exportsrv.c Wed Jul 8 19:22:28 2009 +++ /sys/src/cmd/exportfs/exportsrv.c Sun Feb 28 00:00:00 2016 @@ -7,16 +7,16 @@ extern char *netdir, *local, *remote; -char Ebadfid[] = "Bad fid"; -char Enotdir[] = "Not a directory"; -char Edupfid[] = "Fid already in use"; -char Eopen[] = "Fid already opened"; -char Exmnt[] = "Cannot .. past mount point"; -char Emip[] = "Mount in progress"; -char Enopsmt[] = "Out of pseudo mount points"; -char Enomem[] = "No memory"; -char Eversion[] = "Bad 9P2000 version"; -char Ereadonly[] = "File system read only"; +char Ebadfid[] = "bad fid"; +char Enotdir[] = "not a directory"; +char Edupfid[] = "fid already in use"; +char Eopen[] = "fid already opened"; +char Emip[] = "mount in progress"; +char Enopsmt[] = "out of pseudo mount points"; +char Enomem[] = "no memory"; +char Eversion[] = "bad 9P2000 version"; +char Ereadonly[] = "file system read only"; +char Enoprocs[] = "out of processes"; ulong messagesize; int readonly; @@ -26,17 +26,23 @@ { Fcall rhdr; + if(t->work.msize < 256){ + reply(&t->work, &rhdr, "version: message size too small"); + putsbuf(t); + return; + } if(t->work.msize > messagesize) t->work.msize = messagesize; messagesize = t->work.msize; if(strncmp(t->work.version, "9P2000", 6) != 0){ reply(&t->work, &rhdr, Eversion); + putsbuf(t); return; } rhdr.version = "9P2000"; rhdr.msize = t->work.msize; reply(&t->work, &rhdr, 0); - t->busy = 0; + putsbuf(t); } void @@ -45,34 +51,37 @@ Fcall rhdr; reply(&t->work, &rhdr, "exportfs: authentication not required"); - t->busy = 0; + putsbuf(t); } void Xflush(Fsrpc *t) { - Fsrpc *w, *e; Fcall rhdr; + Fsrpc *w; + Proc *m; - e = &Workq[Nr_workbufs]; + for(m = Proclist; m != nil; m = m->next){ + w = m->busy; + if(w == nil || w->work.tag != t->work.oldtag) + continue; - for(w = Workq; w < e; w++) { - if(w->work.tag == t->work.oldtag) { - DEBUG(DFD, "\tQ busy %d pid %p can %d\n", w->busy, w->pid, w->canint); - if(w->busy && w->pid) { - w->flushtag = t->work.tag; - DEBUG(DFD, "\tset flushtag %d\n", t->work.tag); - if(w->canint) - postnote(PNPROC, w->pid, "flush"); - t->busy = 0; - return; - } + lock(m); + w = m->busy; + if(w != nil && w->work.tag == t->work.oldtag) { + w->flushtag = t->work.tag; + DEBUG(DFD, "\tset flushtag %d\n", t->work.tag); + postnote(PNPROC, m->pid, "flush"); + unlock(m); + putsbuf(t); + return; } + unlock(m); } reply(&t->work, &rhdr, 0); DEBUG(DFD, "\tflush reply\n"); - t->busy = 0; + putsbuf(t); } void @@ -84,36 +93,31 @@ char buf[128]; f = newfid(t->work.fid); - if(f == 0) { + if(f == nil) { reply(&t->work, &rhdr, Ebadfid); - t->busy = 0; + putsbuf(t); return; } if(srvfd >= 0){ - if(psmpt == 0){ - Nomount: - reply(&t->work, &rhdr, Enopsmt); - t->busy = 0; - freefid(t->work.fid); - return; - } + if(psmpt == nil) + goto Nomount; for(i=0; i= Npsmpt) goto Nomount; - sprint(buf, "%d", i); + snprint(buf, sizeof(buf), "%d", i); f->f = file(psmpt, buf); if(f->f == nil) goto Nomount; - sprint(buf, "/mnt/exportfs/%d", i); + snprint(buf, sizeof(buf), "/mnt/exportfs/%d", i); nfd = dup(srvfd, -1); if(amount(nfd, buf, MREPL|MCREATE, t->work.aname) < 0){ errstr(buf, sizeof buf); reply(&t->work, &rhdr, buf); - t->busy = 0; freefid(t->work.fid); + putsbuf(t); close(nfd); return; } @@ -126,7 +130,13 @@ rhdr.qid = f->f->qid; reply(&t->work, &rhdr, 0); - t->busy = 0; + putsbuf(t); + return; + +Nomount: + reply(&t->work, &rhdr, Enopsmt); + freefid(t->work.fid); + putsbuf(t); } Fid* @@ -135,15 +145,15 @@ Fid *n; n = newfid(new); - if(n == 0) { + if(n == nil) { n = getfid(new); - if(n == 0) + if(n == nil) fatal("inconsistent fids"); if(n->fid >= 0) close(n->fid); freefid(new); n = newfid(new); - if(n == 0) + if(n == nil) fatal("inconsistent fids2"); } n->f = f->f; @@ -161,9 +171,9 @@ int i; f = getfid(t->work.fid); - if(f == 0) { + if(f == nil) { reply(&t->work, &rhdr, Ebadfid); - t->busy = 0; + putsbuf(t); return; } @@ -176,28 +186,22 @@ rhdr.nwqid = 0; e = nil; for(i=0; iwork.nwname; i++){ - if(i == MAXWELEM){ - e = "Too many path elements"; - break; - } if(strcmp(t->work.wname[i], "..") == 0) { - if(f->f->parent == nil) { - e = Exmnt; + if(f->f->parent != nil) + wf = f->f->parent; + else + wf = f->f; + wf->ref++; + }else{ + wf = file(f->f, t->work.wname[i]); + if(wf == nil){ + errstr(err, sizeof err); + e = err; break; } - wf = f->f->parent; - wf->ref++; - goto Accept; } - - wf = file(f->f, t->work.wname[i]); - if(wf == 0){ - errstr(err, sizeof err); - e = err; - break; - } - Accept: + freefile(f->f); rhdr.wqid[rhdr.nwqid++] = wf->qid; f->f = wf; @@ -209,7 +213,7 @@ if(rhdr.nwqid > 0) e = nil; reply(&t->work, &rhdr, e); - t->busy = 0; + putsbuf(t); } void @@ -219,9 +223,9 @@ Fid *f; f = getfid(t->work.fid); - if(f == 0) { + if(f == nil) { reply(&t->work, &rhdr, Ebadfid); - t->busy = 0; + putsbuf(t); return; } @@ -230,7 +234,7 @@ freefid(t->work.fid); reply(&t->work, &rhdr, 0); - t->busy = 0; + putsbuf(t); } void @@ -244,9 +248,9 @@ uchar *statbuf; f = getfid(t->work.fid); - if(f == 0) { + if(f == nil) { reply(&t->work, &rhdr, Ebadfid); - t->busy = 0; + putsbuf(t); return; } if(f->fid >= 0) @@ -260,7 +264,7 @@ if(d == nil) { errstr(err, sizeof err); reply(&t->work, &rhdr, err); - t->busy = 0; + putsbuf(t); return; } @@ -273,7 +277,7 @@ rhdr.stat = statbuf; reply(&t->work, &rhdr, 0); free(statbuf); - t->busy = 0; + putsbuf(t); } static int @@ -297,13 +301,13 @@ if(readonly) { reply(&t->work, &rhdr, Ereadonly); - t->busy = 0; + putsbuf(t); return; } f = getfid(t->work.fid); - if(f == 0) { + if(f == nil) { reply(&t->work, &rhdr, Ebadfid); - t->busy = 0; + putsbuf(t); return; } @@ -314,15 +318,15 @@ if(f->fid < 0) { errstr(err, sizeof err); reply(&t->work, &rhdr, err); - t->busy = 0; + putsbuf(t); return; } nf = file(f->f, t->work.name); - if(nf == 0) { + if(nf == nil) { errstr(err, sizeof err); reply(&t->work, &rhdr, err); - t->busy = 0; + putsbuf(t); return; } @@ -332,7 +336,7 @@ rhdr.qid = f->f->qid; rhdr.iounit = getiounit(f->fid); reply(&t->work, &rhdr, 0); - t->busy = 0; + putsbuf(t); } void @@ -344,13 +348,13 @@ if(readonly) { reply(&t->work, &rhdr, Ereadonly); - t->busy = 0; + putsbuf(t); return; } f = getfid(t->work.fid); - if(f == 0) { + if(f == nil) { reply(&t->work, &rhdr, Ebadfid); - t->busy = 0; + putsbuf(t); return; } @@ -360,7 +364,7 @@ free(path); errstr(err, sizeof err); reply(&t->work, &rhdr, err); - t->busy = 0; + putsbuf(t); return; } free(path); @@ -371,7 +375,7 @@ freefid(t->work.fid); reply(&t->work, &rhdr, 0); - t->busy = 0; + putsbuf(t); } void @@ -386,20 +390,20 @@ if(readonly) { reply(&t->work, &rhdr, Ereadonly); - t->busy = 0; + putsbuf(t); return; } f = getfid(t->work.fid); - if(f == 0) { + if(f == nil) { reply(&t->work, &rhdr, Ebadfid); - t->busy = 0; + putsbuf(t); return; } strings = emallocz(t->work.nstat); /* ample */ if(convM2D(t->work.stat, t->work.nstat, &d, strings) <= BIT16SZ){ rerrstr(err, sizeof err); reply(&t->work, &rhdr, err); - t->busy = 0; + putsbuf(t); free(strings); return; } @@ -417,14 +421,14 @@ } else { /* wstat may really be rename */ - if(strcmp(d.name, f->f->name)!=0 && strcmp(d.name, "")!=0){ + if(strcmp(d.name, f->f->name)!=0 && d.name[0]!=0){ free(f->f->name); f->f->name = estrdup(d.name); } reply(&t->work, &rhdr, 0); } free(strings); - t->busy = 0; + putsbuf(t); } /* @@ -455,90 +459,99 @@ void slave(Fsrpc *f) { - Proc *p; - uintptr pid; - Fcall rhdr; static int nproc; + Proc *m, **l; + Fcall rhdr; + int omode; + int pid; if(readonly){ switch(f->work.type){ case Twrite: reply(&f->work, &rhdr, Ereadonly); - f->busy = 0; + putsbuf(f); return; case Topen: - if((f->work.mode&3) == OWRITE || (f->work.mode&OTRUNC)){ + omode = f->work.mode & 3; + if(omode != OREAD && omode != OEXEC || (f->work.mode&(OTRUNC|ORCLOSE)) != 0){ reply(&f->work, &rhdr, Ereadonly); - f->busy = 0; + putsbuf(f); return; } } } for(;;) { - for(p = Proclist; p; p = p->next) { - if(p->busy == 0) { - f->pid = p->pid; - p->busy = 1; - pid = (uintptr)rendezvous((void*)p->pid, f); - if(pid != p->pid) - fatal("rendezvous sync fail"); - return; - } - } + for(l = &Proclist; (m = *l) != nil; l = &m->next) { + if(m->busy != nil) + continue; + + m->busy = f; + while(rendezvous(m, f) == (void*)~0) + ; + + /* swept a slave proc */ + if(f == nil){ + *l = m->next; + free(m); + nproc--; + break; + } + f = nil; - if(++nproc > MAXPROC) - fatal("too many procs"); + /* + * as long as the number of slave procs + * is small, dont bother sweeping. + */ + if(nproc < 16) + break; + } + if(f == nil) + return; - pid = rfork(RFPROC|RFMEM); + m = emallocz(sizeof(Proc)); + pid = rfork(RFPROC|RFMEM|RFNOWAIT); switch(pid) { case -1: - fatal("rfork"); + reply(&f->work, &rhdr, Enoprocs); + putsbuf(f); + free(m); + return; case 0: - if (local[0] != '\0') - if (netdir[0] != '\0') - procsetname("%s: %s -> %s", netdir, - local, remote); + if(local[0] != '\0'){ + if(netdir[0] != '\0') + procsetname("%s: %s -> %s", netdir, local, remote); else procsetname("%s -> %s", local, remote); - blockingslave(); - fatal("slave"); + } + blockingslave(m); + _exits(0); default: - p = malloc(sizeof(Proc)); - if(p == 0) - fatal("out of memory"); - - p->busy = 0; - p->pid = pid; - p->next = Proclist; - Proclist = p; - - rendezvous((void*)pid, p); + m->pid = pid; + m->next = Proclist; + Proclist = m; + nproc++; } } } void -blockingslave(void) +blockingslave(Proc *m) { Fsrpc *p; Fcall rhdr; - Proc *m; - uintptr pid; notify(flushaction); - pid = getpid(); - - m = rendezvous((void*)pid, 0); - for(;;) { - p = rendezvous((void*)pid, (void*)pid); - if(p == (void*)~0) /* Interrupted */ + p = rendezvous(m, nil); + if(p == (void*)~0) /* Interrupted */ continue; + if(p == nil) /* Swept */ + break; - DEBUG(DFD, "\tslave: %p %F b %d p %p\n", pid, &p->work, p->busy, p->pid); + DEBUG(DFD, "\tslave: %d %F\n", m->pid, &p->work); if(p->flushtag != NOTAG) goto flushme; @@ -558,28 +571,35 @@ default: reply(&p->work, &rhdr, "exportfs: slave type error"); } - if(p->flushtag != NOTAG) { flushme: + lock(m); + m->busy = nil; + unlock(m); + + /* no more flushes can come in now */ + if(p->flushtag != NOTAG) { p->work.type = Tflush; p->work.tag = p->flushtag; reply(&p->work, &rhdr, 0); } - p->busy = 0; - m->busy = 0; + putsbuf(p); } } int openmount(int sfd) { - int p[2]; + int p[2], fd, i, n; char *arg[10], fdbuf[20], mbuf[20]; + Dir *dir; if(pipe(p) < 0) return -1; - switch(rfork(RFPROC|RFMEM|RFNOWAIT|RFNAMEG|RFFDG)){ + switch(rfork(RFPROC|RFMEM|RFNOWAIT|RFNAMEG|RFFDG|RFREND)){ case -1: + close(p[0]); + close(p[1]); return -1; default: @@ -591,20 +611,30 @@ break; } - close(p[1]); + dup(p[0], 0); + dup(p[0], 1); + + /* close all remaining file descriptors except sfd */ + if((fd = open("/fd", OREAD)) < 0) + _exits("open /fd failed"); + n = dirreadall(fd, &dir); + for(i=0; i 2 && fd != sfd) + close(fd); + } + free(dir); - arg[0] = "exportfs"; + arg[0] = argv0; /* "/bin/exportfs" */ snprint(fdbuf, sizeof fdbuf, "-S/fd/%d", sfd); arg[1] = fdbuf; snprint(mbuf, sizeof mbuf, "-m%lud", messagesize-IOHDRSZ); arg[2] = mbuf; arg[3] = nil; - close(0); - close(1); - dup(p[0], 0); - dup(p[0], 1); - exec("/bin/exportfs", arg); + exec(arg[0], arg); _exits("whoops: exec failed"); return -1; } @@ -620,7 +650,7 @@ work = &p->work; f = getfid(work->fid); - if(f == 0) { + if(f == nil) { reply(work, &rhdr, Ebadfid); return; } @@ -631,16 +661,8 @@ path = makepath(f->f, ""); DEBUG(DFD, "\topen: %s %d\n", path, work->mode); - - p->canint = 1; - if(p->flushtag != NOTAG){ - free(path); - return; - } - /* There is a race here I ignore because there are no locks */ f->fid = open(path, work->mode); free(path); - p->canint = 0; if(f->fid < 0 || (d = dirfstat(f->fid)) == nil) { Error: errstr(err, sizeof err); @@ -674,32 +696,29 @@ work = &p->work; f = getfid(work->fid); - if(f == 0) { + if(f == nil) { reply(work, &rhdr, Ebadfid); return; } n = (work->count > messagesize-IOHDRSZ) ? messagesize-IOHDRSZ : work->count; - p->canint = 1; - if(p->flushtag != NOTAG) - return; data = malloc(n); - if(data == nil) - fatal(Enomem); + if(data == nil) { + reply(work, &rhdr, Enomem); + return; + } /* can't just call pread, since directories must update the offset */ if(patternfile != nil && (f->f->qid.type&QTDIR)) r = preaddir(f, (uchar*)data, n, work->offset); else r = pread(f->fid, data, n, work->offset); - p->canint = 0; if(r < 0) { free(data); errstr(err, sizeof err); reply(work, &rhdr, err); return; } - DEBUG(DFD, "\tread: fd=%d %d bytes\n", f->fid, r); rhdr.data = data; @@ -719,17 +738,13 @@ work = &p->work; f = getfid(work->fid); - if(f == 0) { + if(f == nil) { reply(work, &rhdr, Ebadfid); return; } n = (work->count > messagesize-IOHDRSZ) ? messagesize-IOHDRSZ : work->count; - p->canint = 1; - if(p->flushtag != NOTAG) - return; n = pwrite(f->fid, work->data, n, work->offset); - p->canint = 0; if(n < 0) { errstr(err, sizeof err); reply(work, &rhdr, err); diff -Nru /n/sources/plan9/sys/src/cmd/exportfs/pattern.c /sys/src/cmd/exportfs/pattern.c --- /n/sources/plan9/sys/src/cmd/exportfs/pattern.c Wed Oct 22 11:44:52 2003 +++ /sys/src/cmd/exportfs/pattern.c Sun Feb 28 00:00:00 2016 @@ -24,15 +24,11 @@ fatal("cannot open patternfile"); ni = 0; nmaxi = 100; - include = malloc(nmaxi*sizeof(*include)); - if(include == nil) - fatal("out of memory"); + include = emallocz(nmaxi*sizeof(*include)); include[0] = nil; ne = 0; nmaxe = 100; - exclude = malloc(nmaxe*sizeof(*exclude)); - if(exclude == nil) - fatal("out of memory"); + exclude = emallocz(nmaxe*sizeof(*exclude)); exclude[0] = nil; while(line = Brdline(f, '\n')){ line[Blinelen(f) - 1] = 0; @@ -80,16 +76,16 @@ else p = path+1; - DEBUG(DFD, "checking %s\n", path); + DEBUG(DFD, "checking %s\n", p); for(re = include; *re != nil; re++){ if(regexec(*re, p, nil, 0) != 1){ - DEBUG(DFD, "excluded+ %s\n", path); + DEBUG(DFD, "excluded+ %s\n", p); return -1; } } for(re = exclude; *re != nil; re++){ if(regexec(*re, p, nil, 0) == 1){ - DEBUG(DFD, "excluded- %s\n", path); + DEBUG(DFD, "excluded- %s\n", p); return -1; } }