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
This commit is contained in:
parent
d7378c10d8
commit
40d71baf7f
3 changed files with 67 additions and 79 deletions
|
@ -230,7 +230,7 @@ main(int argc, char **argv)
|
|||
|
||||
DEBUG(DFD, "exportfs: started\n");
|
||||
|
||||
rfork(RFNOTEG);
|
||||
rfork(RFNOTEG|RFREND);
|
||||
|
||||
if(messagesize == 0){
|
||||
messagesize = iounit(netfd);
|
||||
|
@ -460,8 +460,8 @@ reply(Fcall *r, Fcall *t, char *err)
|
|||
fatal(Enomem);
|
||||
n = convS2M(t, data, messagesize);
|
||||
if(write(netfd, data, n)!=n){
|
||||
syslog(0, "exportfs", "short write: %r");
|
||||
fatal("mount write");
|
||||
/* not fatal, might have got a note due to flush */
|
||||
fprint(2, "exportfs: short write in reply: %r\n");
|
||||
}
|
||||
free(data);
|
||||
}
|
||||
|
@ -570,8 +570,6 @@ getsbuf(void)
|
|||
unlock(&sbufalloc);
|
||||
w = emallocz(sizeof(*w) + messagesize);
|
||||
}
|
||||
w->pid = 0;
|
||||
w->canint = 0;
|
||||
w->flushtag = NOTAG;
|
||||
return w;
|
||||
}
|
||||
|
@ -579,8 +577,6 @@ getsbuf(void)
|
|||
void
|
||||
putsbuf(Fsrpc *w)
|
||||
{
|
||||
w->pid = 0;
|
||||
w->canint = 0;
|
||||
w->flushtag = NOTAG;
|
||||
lock(&sbufalloc);
|
||||
w->next = sbufalloc.free;
|
||||
|
|
|
@ -15,8 +15,6 @@ typedef struct Qidtab Qidtab;
|
|||
struct Fsrpc
|
||||
{
|
||||
Fsrpc *next; /* freelist */
|
||||
uintptr pid; /* Pid of slave process executing the rpc */
|
||||
int canint; /* Interrupt gate */
|
||||
int flushtag; /* Tag on which to reply to flush */
|
||||
Fcall work; /* Plan 9 incoming Fcall */
|
||||
uchar buf[]; /* Data buffer */
|
||||
|
@ -53,9 +51,10 @@ struct File
|
|||
|
||||
struct Proc
|
||||
{
|
||||
uintptr pid;
|
||||
Lock;
|
||||
Fsrpc *busy;
|
||||
Proc *next;
|
||||
int pid;
|
||||
};
|
||||
|
||||
struct Qidtab
|
||||
|
@ -70,7 +69,6 @@ struct Qidtab
|
|||
|
||||
enum
|
||||
{
|
||||
MAXPROC = 50,
|
||||
FHASHSIZE = 64,
|
||||
Fidchunk = 1000,
|
||||
Npsmpt = 32,
|
||||
|
@ -128,7 +126,7 @@ void freefile(File*);
|
|||
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*);
|
||||
|
|
|
@ -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;
|
||||
|
||||
if(nproc >= MAXPROC){
|
||||
reply(&f->work, &rhdr, Enoprocs);
|
||||
putsbuf(f);
|
||||
return;
|
||||
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;
|
||||
}
|
||||
nproc++;
|
||||
pid = rfork(RFPROC|RFMEM);
|
||||
if(f == nil)
|
||||
return;
|
||||
|
||||
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')
|
||||
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue