From 40d71baf7f44b17fcf323ebed8b835d86f340e84 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Fri, 21 Feb 2014 05:23:21 +0100 Subject: exportfs: bring back the changes, bug was due to rendezvous group being shared by listen exportfs used pid of slave proc as rendezvous tag. when we changed it to use Proc* memory address, there where tag collisions because listen didnt fork the rendezvous group (bug!). for now, just do rfork(RFREND) in main just in case. will fix aux/listen in a follow up changeset. -- cinap --- sys/src/cmd/exportfs/exportsrv.c | 126 +++++++++++++++++++-------------------- 1 file changed, 60 insertions(+), 66 deletions(-) (limited to 'sys/src/cmd/exportfs/exportsrv.c') diff --git a/sys/src/cmd/exportfs/exportsrv.c b/sys/src/cmd/exportfs/exportsrv.c index d7a0ad290..d5873b2b9 100644 --- a/sys/src/cmd/exportfs/exportsrv.c +++ b/sys/src/cmd/exportfs/exportsrv.c @@ -64,14 +64,20 @@ Xflush(Fsrpc *t) for(m = Proclist; m; m = m->next){ w = m->busy; - if(w != 0 && w->pid == m->pid && w->work.tag == t->work.oldtag) { + if(w == nil || w->work.tag != t->work.oldtag) + continue; + + 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); - if(w->canint) - postnote(PNPROC, w->pid, "flush"); + postnote(PNPROC, m->pid, "flush"); + unlock(m); putsbuf(t); return; } + unlock(m); } reply(&t->work, &rhdr, 0); @@ -459,10 +465,10 @@ procsetname(char *fmt, ...) void slave(Fsrpc *f) { - Proc *p; - uintptr pid; - Fcall rhdr; static int nproc; + Proc *m, **l; + Fcall rhdr; + int pid; if(readonly){ switch(f->work.type){ @@ -479,30 +485,41 @@ slave(Fsrpc *f) } } for(;;) { - for(p = Proclist; p; p = p->next) { - if(p->busy == 0) { - f->pid = p->pid; - p->busy = f; - do { - pid = (uintptr)rendezvous((void*)p->pid, f); - } - while(pid == ~0); /* Interrupted */ - 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; + + /* + * as long as the number of slave procs + * is small, dont bother sweeping. + */ + if(nproc < 16) + break; } + if(f == nil) + return; - if(nproc >= MAXPROC){ + m = emallocz(sizeof(Proc)); + pid = rfork(RFPROC|RFMEM|RFNOWAIT); + switch(pid) { + case -1: reply(&f->work, &rhdr, Enoprocs); putsbuf(f); + free(m); return; - } - nproc++; - pid = rfork(RFPROC|RFMEM); - switch(pid) { - case -1: - fatal("rfork"); case 0: if (local[0] != '\0') @@ -511,44 +528,34 @@ slave(Fsrpc *f) local, remote); else procsetname("%s -> %s", local, remote); - blockingslave(); - fatal("slave"); + blockingslave(m); + _exits(0); default: - p = emallocz(sizeof(Proc)); - p->busy = 0; - p->pid = pid; - p->next = Proclist; - Proclist = p; - while(rendezvous((void*)pid, p) == (void*)~0) - ; + 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(); - - do { - m = rendezvous((void*)pid, 0); - } - while(m == (void*)~0); /* Interrupted */ - 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 p %p\n", pid, &p->work, p->pid); + DEBUG(DFD, "\tslave: %d %F\n", m->pid, &p->work); if(p->flushtag != NOTAG) goto flushme; @@ -568,13 +575,17 @@ blockingslave(void) 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); } - m->busy = 0; putsbuf(p); } } @@ -654,16 +665,8 @@ slaveopen(Fsrpc *p) 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); @@ -703,9 +706,6 @@ slaveread(Fsrpc *p) } n = (work->count > messagesize-IOHDRSZ) ? messagesize-IOHDRSZ : work->count; - p->canint = 1; - if(p->flushtag != NOTAG) - return; data = malloc(n); if(data == 0) { reply(work, &rhdr, Enomem); @@ -717,14 +717,12 @@ slaveread(Fsrpc *p) 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; @@ -750,11 +748,7 @@ slavewrite(Fsrpc *p) } 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); -- cgit v1.2.3