nci = getnetconninfo(nil, fd);
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);
}
if(messagesize == 0)
messagesize = 8192+IOHDRSZ;
}
-
- Workq = emallocz(sizeof(Fsrpc)*Nr_workbufs);
fhash = emallocz(sizeof(Fid*)*FHASHSIZE);
fmtinstall('F', fcallfmt);
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;
- }
-
- 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;
+ Fsrpc *w;
+
+ lock(&sbufalloc);
+ w = sbufalloc.free;
+ if(w != 0){
+ 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->pid = 0;
+ w->canint = 0;
+ w->flushtag = NOTAG;
+ return w;
+}
+
+void
+putsbuf(Fsrpc *w)
+{
+ w->pid = 0;
+ w->canint = 0;
+ w->flushtag = NOTAG;
+ lock(&sbufalloc);
+ w->next = sbufalloc.free;
+ sbufalloc.free = w;
+ sbufalloc.nfree++;
+ unlock(&sbufalloc);
}
void
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--) {
char Enomem[] = "No memory";
char Eversion[] = "Bad 9P2000 version";
char Ereadonly[] = "File system read only";
+char Enoprocs[] = "Out of processes";
ulong messagesize;
int readonly;
if(t->work.msize < 256){
reply(&t->work, &rhdr, "version: message size too small");
- t->busy = 0;
+ putsbuf(t);
return;
}
if(t->work.msize > messagesize)
messagesize = t->work.msize;
if(strncmp(t->work.version, "9P2000", 6) != 0){
reply(&t->work, &rhdr, Eversion);
- t->busy = 0;
+ putsbuf(t);
return;
}
rhdr.version = "9P2000";
rhdr.msize = t->work.msize;
reply(&t->work, &rhdr, 0);
- t->busy = 0;
+ putsbuf(t);
}
void
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(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;
- }
+ for(m = Proclist; m; m = m->next){
+ w = m->busy;
+ if(w != 0 && w->pid == m->pid && 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");
+ putsbuf(t);
+ return;
}
}
reply(&t->work, &rhdr, 0);
DEBUG(DFD, "\tflush reply\n");
- t->busy = 0;
+ putsbuf(t);
}
void
f = newfid(t->work.fid);
if(f == 0) {
reply(&t->work, &rhdr, Ebadfid);
- t->busy = 0;
+ putsbuf(t);
return;
}
if(psmpt == 0){
Nomount:
reply(&t->work, &rhdr, Enopsmt);
- t->busy = 0;
freefid(t->work.fid);
+ putsbuf(t);
return;
}
for(i=0; i<Npsmpt; i++)
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;
}
rhdr.qid = f->f->qid;
reply(&t->work, &rhdr, 0);
- t->busy = 0;
+ putsbuf(t);
}
Fid*
f = getfid(t->work.fid);
if(f == 0) {
reply(&t->work, &rhdr, Ebadfid);
- t->busy = 0;
+ putsbuf(t);
return;
}
if(rhdr.nwqid > 0)
e = nil;
reply(&t->work, &rhdr, e);
- t->busy = 0;
+ putsbuf(t);
}
void
f = getfid(t->work.fid);
if(f == 0) {
reply(&t->work, &rhdr, Ebadfid);
- t->busy = 0;
+ putsbuf(t);
return;
}
freefid(t->work.fid);
reply(&t->work, &rhdr, 0);
- t->busy = 0;
+ putsbuf(t);
}
void
f = getfid(t->work.fid);
if(f == 0) {
reply(&t->work, &rhdr, Ebadfid);
- t->busy = 0;
+ putsbuf(t);
return;
}
if(f->fid >= 0)
if(d == nil) {
errstr(err, sizeof err);
reply(&t->work, &rhdr, err);
- t->busy = 0;
+ putsbuf(t);
return;
}
rhdr.stat = statbuf;
reply(&t->work, &rhdr, 0);
free(statbuf);
- t->busy = 0;
+ putsbuf(t);
}
static int
if(readonly) {
reply(&t->work, &rhdr, Ereadonly);
- t->busy = 0;
+ putsbuf(t);
return;
}
f = getfid(t->work.fid);
if(f == 0) {
reply(&t->work, &rhdr, Ebadfid);
- t->busy = 0;
+ putsbuf(t);
return;
}
if(f->fid < 0) {
errstr(err, sizeof err);
reply(&t->work, &rhdr, err);
- t->busy = 0;
+ putsbuf(t);
return;
}
if(nf == 0) {
errstr(err, sizeof err);
reply(&t->work, &rhdr, err);
- t->busy = 0;
+ putsbuf(t);
return;
}
rhdr.qid = f->f->qid;
rhdr.iounit = getiounit(f->fid);
reply(&t->work, &rhdr, 0);
- t->busy = 0;
+ putsbuf(t);
}
void
if(readonly) {
reply(&t->work, &rhdr, Ereadonly);
- t->busy = 0;
+ putsbuf(t);
return;
}
f = getfid(t->work.fid);
if(f == 0) {
reply(&t->work, &rhdr, Ebadfid);
- t->busy = 0;
+ putsbuf(t);
return;
}
free(path);
errstr(err, sizeof err);
reply(&t->work, &rhdr, err);
- t->busy = 0;
+ putsbuf(t);
return;
}
free(path);
freefid(t->work.fid);
reply(&t->work, &rhdr, 0);
- t->busy = 0;
+ putsbuf(t);
}
void
if(readonly) {
reply(&t->work, &rhdr, Ereadonly);
- t->busy = 0;
+ putsbuf(t);
return;
}
f = getfid(t->work.fid);
if(f == 0) {
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;
}
reply(&t->work, &rhdr, 0);
}
free(strings);
- t->busy = 0;
+ putsbuf(t);
}
/*
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)){
reply(&f->work, &rhdr, Ereadonly);
- f->busy = 0;
+ putsbuf(f);
return;
}
}
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);
+ p->busy = f;
+ do {
+ pid = (uintptr)rendezvous((void*)p->pid, f);
+ }
+ while(pid == ~0); /* Interrupted */
if(pid != p->pid)
fatal("rendezvous sync fail");
return;
}
}
- if(++nproc > MAXPROC)
- fatal("too many procs");
-
+ if(nproc >= MAXPROC){
+ reply(&f->work, &rhdr, Enoprocs);
+ putsbuf(f);
+ return;
+ }
+ nproc++;
pid = rfork(RFPROC|RFMEM);
switch(pid) {
case -1:
fatal("slave");
default:
- p = malloc(sizeof(Proc));
- if(p == 0)
- fatal("out of memory");
-
+ p = emallocz(sizeof(Proc));
p->busy = 0;
p->pid = pid;
p->next = Proclist;
Proclist = p;
-
- rendezvous((void*)pid, p);
+ while(rendezvous((void*)pid, p) == (void*)~0)
+ ;
}
}
}
pid = getpid();
- m = rendezvous((void*)pid, 0);
+ do {
+ m = rendezvous((void*)pid, 0);
+ }
+ while(m == (void*)~0); /* Interrupted */
for(;;) {
p = rendezvous((void*)pid, (void*)pid);
if(p == (void*)~0) /* Interrupted */
continue;
- DEBUG(DFD, "\tslave: %p %F b %d p %p\n", pid, &p->work, p->busy, p->pid);
+ DEBUG(DFD, "\tslave: %p %F p %p\n", pid, &p->work, p->pid);
if(p->flushtag != NOTAG)
goto flushme;
p->work.tag = p->flushtag;
reply(&p->work, &rhdr, 0);
}
- p->busy = 0;
m->busy = 0;
+ putsbuf(p);
}
}
if(p->flushtag != NOTAG)
return;
data = malloc(n);
- if(data == nil)
- fatal(Enomem);
+ if(data == 0) {
+ reply(work, &rhdr, Enomem);
+ return;
+ }
/* can't just call pread, since directories must update the offset */
if(patternfile != nil && (f->f->qid.type&QTDIR))