This makes exportfs fully threaded and solves a problem, posted by Eric Van Hensbergen: % srvfs test / % mount /srv/test /n/test % lc /n/test/n/test [no response] This was because exportfs did send a Tstat to itself, but since Tstat was single-threaded, wasn't there a thread to readn() the message and so it all stucks. Notes: Tue Jun 21 08:19:57 EDT 2005 rsc This might be worth fixing, but it will take a little more than that. Your new code has various race conditions, especially in the fid management, because it's no longer single-threaded. Also, there are various changes you're undoing, presumably because you're not completely up-to-date with our sources. I'll push exportfs just in case. Also, please don't move functions around in the file when you make patches. It just makes them hard to read and understand. Thanks. Tue Jun 21 08:22:05 EDT 2005 rsc Actually, exportfs was already up-to-date on sources. You should pull the latest copy before making your changes again. Reference: /n/sources/patch/sorry/exportfs-threads Date: Tue Jun 21 01:34:50 CES 2005 Reviewed-by: rsc --- /sys/src/cmd/exportfs/exportfs.c Tue Jun 21 01:33:45 2005 +++ /sys/src/cmd/exportfs/exportfs.c Tue Jun 21 01:33:40 2005 @@ -20,19 +20,19 @@ void (*fcalls[])(Fsrpc*) = { - [Tversion] Xversion, - [Tauth] Xauth, - [Tflush] Xflush, - [Tattach] Xattach, - [Twalk] Xwalk, + [Tversion] slave, + [Tauth] slave, + [Tflush] slave, + [Tattach] slave, + [Twalk] slave, [Topen] slave, - [Tcreate] Xcreate, - [Tclunk] Xclunk, + [Tcreate] slave, + [Tclunk] slave, [Tread] slave, [Twrite] slave, - [Tremove] Xremove, - [Tstat] Xstat, - [Twstat] Xwstat, + [Tremove] slave, + [Tstat] slave, + [Twstat] slave, }; /* accounting and debugging counters */ @@ -59,33 +59,33 @@ void usage(void) { - fprint(2, "usage: %s [-adnsR] [-f dbgfile] [-m msize] [-r root] [-S srvfile] [-e 'crypt hash'] [-A announce-string] [-B address]\n", argv0); + fprint(2, "usage: %s [-ads] [-f dbgfile] [-m msize] [-r root] [-S srvfile] [-e 'crypt hash'] [-A announce-string]\n", argv0); + fprint(2, " %s -B address\n", argv0); fatal("usage"); } void main(int argc, char **argv) { - char buf[ERRMAX], ebuf[ERRMAX], *srvfdfile; + char buf[ERRMAX], ebuf[ERRMAX], isauth; Fsrpc *r; - int doauth, n, fd; - char *dbfile, *srv, *na, *nsfile, *keyspec; + int n, fd, i; + char *dbfile, *srv, *file, *na, *nsfile, *keyspec; AuthInfo *ai; ulong initial; dbfile = "/tmp/exportdb"; srv = nil; srvfd = -1; - srvfdfile = nil; na = nil; nsfile = nil; keyspec = ""; - doauth = 0; + isauth = 'n'; ai = nil; ARGBEGIN{ case 'a': - doauth = 1; + isauth = 'y'; break; case 'k': @@ -93,15 +93,19 @@ break; case 'e': - ealgs = EARGF(usage()); + ealgs = ARGF(); + if(ealgs == nil) + usage(); if(*ealgs == 0 || strcmp(ealgs, "clear") == 0) ealgs = nil; break; case 'S': - if(srvfdfile) + if(srvfd != -1) usage(); - srvfdfile = EARGF(usage()); + file = EARGF(usage()); + if((srvfd = open(file, ORDWR)) < 0) + sysfatal("open '%s': %r", file); break; case 'd': @@ -157,7 +161,7 @@ }ARGEND USED(argc, argv); - if(doauth){ + if(isauth == 'y'){ /* * 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 @@ -174,11 +178,6 @@ putenv("service", "exportfs"); } - if(srvfdfile){ - if((srvfd = open(srvfdfile, ORDWR)) < 0) - sysfatal("open '%s': %r", srvfdfile); - } - if(na){ if(srv == nil) sysfatal("-B requires -s"); @@ -219,8 +218,8 @@ } Workq = emallocz(sizeof(Fsrpc)*Nr_workbufs); -// for(i=0; ibuf, messagesize, &initial); if(n <= 0) fatal(nil); @@ -523,7 +522,7 @@ static int ap; int look, rounds; Fsrpc *wb; - int small_instead_of_fast = 1; + int small_instead_of_fast = 0; if(small_instead_of_fast) ap = 0; /* so we always start looking at the beginning and reuse buffers */ --- /sys/src/cmd/exportfs/exportfs.h Tue Jun 21 01:34:03 2005 +++ /sys/src/cmd/exportfs/exportfs.h Tue Jun 21 01:33:59 2005 @@ -103,17 +103,17 @@ Extern char* patternfile; /* File system protocol service procedures */ -void Xattach(Fsrpc*); -void Xauth(Fsrpc*); -void Xclunk(Fsrpc*); -void Xcreate(Fsrpc*); -void Xflush(Fsrpc*); -void Xnop(Fsrpc*); -void Xremove(Fsrpc*); -void Xstat(Fsrpc*); -void Xversion(Fsrpc*); -void Xwalk(Fsrpc*); -void Xwstat(Fsrpc*); +void slaveattach(Fsrpc*); +void slaveauth(Fsrpc*); +void slaveclunk(Fsrpc*); +void slavecreate(Fsrpc*); +void slaveflush(Fsrpc*); +void slavenop(Fsrpc*); +void slaveremove(Fsrpc*); +void slavestat(Fsrpc*); +void slaveversion(Fsrpc*); +void slavewalk(Fsrpc*); +void slavewstat(Fsrpc*); void slave(Fsrpc*); void reply(Fcall*, Fcall*, char*); --- /sys/src/cmd/exportfs/exportsrv.c Tue Jun 21 01:34:27 2005 +++ /sys/src/cmd/exportfs/exportsrv.c Tue Jun 21 01:34:23 2005 @@ -20,7 +20,157 @@ int readonly; void -Xversion(Fsrpc *t) +slave(Fsrpc *f) +{ + Proc *p; + int pid; + Fcall rhdr; + static int nproc; + + if(readonly){ + switch(f->work.type){ + case Tcreate: + case Tremove: + case Twstat: + case Twrite: + reply(&f->work, &rhdr, Ereadonly); + f->busy = 0; + return; + case Topen: + if((f->work.mode&3) == OWRITE || (f->work.mode&OTRUNC)){ + reply(&f->work, &rhdr, Ereadonly); + f->busy = 0; + return; + } + } + } + for(;;) { + for(p = Proclist; p; p = p->next) { + if(p->busy == 0) { + f->pid = p->pid; + p->busy = 1; + pid = rendezvous(p->pid, (ulong)f); + if(pid != p->pid) + fatal("rendezvous sync fail"); + return; + } + } + + if(++nproc > MAXPROC) + fatal("too many procs"); + + pid = rfork(RFPROC|RFMEM); + switch(pid) { + case -1: + fatal("rfork"); + + case 0: + blockingslave(); + fatal("slave"); + + default: + p = malloc(sizeof(Proc)); + if(p == 0) + fatal("out of memory"); + + p->busy = 0; + p->pid = pid; + p->next = Proclist; + Proclist = p; + + rendezvous(pid, (ulong)p); + } + } +} + +void +blockingslave(void) +{ + Fsrpc *p; + Fcall rhdr; + Proc *m; + int pid; + + notify(flushaction); + + pid = getpid(); + + m = (Proc*)rendezvous(pid, 0); + + for(;;) { + p = (Fsrpc*)rendezvous(pid, pid); + if((int)p == ~0) /* Interrupted */ + continue; + + DEBUG(DFD, "\tslave: %d %F b %d p %d\n", pid, &p->work, p->busy, p->pid); + if(p->flushtag != NOTAG) + goto flushme; + + switch(p->work.type) { + case Tversion: + slaveversion(p); + break; + + case Tauth: + slaveauth(p); + break; + + case Tattach: + slaveattach(p); + break; + + case Twalk: + slavewalk(p); + break; + + case Tcreate: + slavecreate(p); + break; + + case Tclunk: + slaveclunk(p); + break; + + case Tremove: + slaveremove(p); + break; + + case Tstat: + slavestat(p); + break; + + case Twstat: + slavewstat(p); + break; + + case Tread: + slaveread(p); + break; + + case Twrite: + slavewrite(p); + break; + + case Topen: + slaveopen(p); + break; + + default: + reply(&p->work, &rhdr, "exportfs: slave type error"); + } + if(p->flushtag != NOTAG) { +flushme: + p->work.type = Tflush; + p->work.tag = p->flushtag; + reply(&p->work, &rhdr, 0); + } + p->busy = 0; + m->busy = 0; + } +} + +void +slaveversion(Fsrpc *t) { Fcall rhdr; @@ -38,7 +188,7 @@ } void -Xauth(Fsrpc *t) +slaveauth(Fsrpc *t) { Fcall rhdr; @@ -47,7 +197,7 @@ } void -Xflush(Fsrpc *t) +slaveflush(Fsrpc *t) { Fsrpc *w, *e; Fcall rhdr; @@ -74,7 +224,7 @@ } void -Xattach(Fsrpc *t) +slaveattach(Fsrpc *t) { int i, nfd; Fcall rhdr; @@ -150,7 +300,7 @@ } void -Xwalk(Fsrpc *t) +slavewalk(Fsrpc *t) { char err[ERRMAX], *e; Fcall rhdr; @@ -211,7 +361,7 @@ } void -Xclunk(Fsrpc *t) +slaveclunk(Fsrpc *t) { Fcall rhdr; Fid *f; @@ -232,7 +382,7 @@ } void -Xstat(Fsrpc *t) +slavestat(Fsrpc *t) { char err[ERRMAX], *path; Fcall rhdr; @@ -286,18 +436,13 @@ } void -Xcreate(Fsrpc *t) +slavecreate(Fsrpc *t) { char err[ERRMAX], *path; Fcall rhdr; Fid *f; File *nf; - if(readonly) { - reply(&t->work, &rhdr, Ereadonly); - t->busy = 0; - return; - } f = getfid(t->work.fid); if(f == 0) { reply(&t->work, &rhdr, Ebadfid); @@ -305,7 +450,6 @@ return; } - path = makepath(f->f, t->work.name); f->fid = create(path, t->work.mode, t->work.perm); free(path); @@ -334,17 +478,12 @@ } void -Xremove(Fsrpc *t) +slaveremove(Fsrpc *t) { char err[ERRMAX], *path; Fcall rhdr; Fid *f; - if(readonly) { - reply(&t->work, &rhdr, Ereadonly); - t->busy = 0; - return; - } f = getfid(t->work.fid); if(f == 0) { reply(&t->work, &rhdr, Ebadfid); @@ -373,7 +512,7 @@ } void -Xwstat(Fsrpc *t) +slavewstat(Fsrpc *t) { char err[ERRMAX], *path; Fcall rhdr; @@ -382,11 +521,6 @@ char *strings; Dir d; - if(readonly) { - reply(&t->work, &rhdr, Ereadonly); - t->busy = 0; - return; - } f = getfid(t->work.fid); if(f == 0) { reply(&t->work, &rhdr, Ebadfid); @@ -423,117 +557,6 @@ } free(strings); t->busy = 0; -} - -void -slave(Fsrpc *f) -{ - Proc *p; - int pid; - Fcall rhdr; - static int nproc; - - if(readonly){ - switch(f->work.type){ - case Twrite: - reply(&f->work, &rhdr, Ereadonly); - f->busy = 0; - return; - case Topen: - if((f->work.mode&3) == OWRITE || (f->work.mode&OTRUNC)){ - reply(&f->work, &rhdr, Ereadonly); - f->busy = 0; - return; - } - } - } - for(;;) { - for(p = Proclist; p; p = p->next) { - if(p->busy == 0) { - f->pid = p->pid; - p->busy = 1; - pid = rendezvous(p->pid, (ulong)f); - if(pid != p->pid) - fatal("rendezvous sync fail"); - return; - } - } - - if(++nproc > MAXPROC) - fatal("too many procs"); - - pid = rfork(RFPROC|RFMEM); - switch(pid) { - case -1: - fatal("rfork"); - - case 0: - blockingslave(); - fatal("slave"); - - default: - p = malloc(sizeof(Proc)); - if(p == 0) - fatal("out of memory"); - - p->busy = 0; - p->pid = pid; - p->next = Proclist; - Proclist = p; - - rendezvous(pid, (ulong)p); - } - } -} - -void -blockingslave(void) -{ - Fsrpc *p; - Fcall rhdr; - Proc *m; - int pid; - - notify(flushaction); - - pid = getpid(); - - m = (Proc*)rendezvous(pid, 0); - - for(;;) { - p = (Fsrpc*)rendezvous(pid, pid); - if((int)p == ~0) /* Interrupted */ - continue; - - DEBUG(DFD, "\tslave: %d %F b %d p %d\n", pid, &p->work, p->busy, p->pid); - if(p->flushtag != NOTAG) - goto flushme; - - switch(p->work.type) { - case Tread: - slaveread(p); - break; - - case Twrite: - slavewrite(p); - break; - - case Topen: - slaveopen(p); - break; - - default: - reply(&p->work, &rhdr, "exportfs: slave type error"); - } - if(p->flushtag != NOTAG) { -flushme: - p->work.type = Tflush; - p->work.tag = p->flushtag; - reply(&p->work, &rhdr, 0); - } - p->busy = 0; - m->busy = 0; - } } int