shithub: riscv

Download patch

ref: 35484945e2f782fe312fcae4f0269b80c4184367
parent: 7d001bd2b29859744630f8743ce76ba873d66d88
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Dec 15 02:49:53 EST 2013

exportfs: get rid of limits, cleanup

get rid of the service buffer limit. keep service buffers
on a global freelist protected by lock.

dont fatal when we hit the process limit. instead, just
abort the rpc with an error.

handle rendezvous() interrupts.

--- a/sys/src/cmd/exportfs/exportfs.c
+++ b/sys/src/cmd/exportfs/exportfs.c
@@ -76,9 +76,9 @@
 	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);
 }
 
@@ -237,8 +237,6 @@
 		if(messagesize == 0)
 			messagesize = 8192+IOHDRSZ;
 	}
-
-	Workq = emallocz(sizeof(Fsrpc)*Nr_workbufs);
 	fhash = emallocz(sizeof(Fid*)*FHASHSIZE);
 
 	fmtinstall('F', fcallfmt);
@@ -546,44 +544,52 @@
 	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;
+	Fsrpc *w;
 
-	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;
+	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
 freefile(File *f)
 {
 	File *parent, *child;
@@ -711,9 +717,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--) {
--- a/sys/src/cmd/exportfs/exportfs.h
+++ b/sys/src/cmd/exportfs/exportfs.h
@@ -14,12 +14,12 @@
 
 struct Fsrpc
 {
-	int	busy;		/* Work buffer has pending rpc to service */
+	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 */
+	uchar	buf[];		/* Data buffer */
 };
 
 struct Fid
@@ -54,7 +54,7 @@
 struct Proc
 {
 	uintptr	pid;
-	int	busy;
+	Fsrpc	*busy;
 	Proc	*next;
 };
 
@@ -72,7 +72,6 @@
 {
 	MAXPROC		= 50,
 	FHASHSIZE	= 64,
-	Nr_workbufs 	= 50,
 	Fidchunk	= 1000,
 	Npsmpt		= 32,
 	Nqidbits		= 5,
@@ -88,7 +87,6 @@
 char Emip[];
 char Enopsmt[];
 
-Extern Fsrpc	*Workq;
 Extern int  	dbg;
 Extern File	*root;
 Extern File	*psmpt;
@@ -121,6 +119,7 @@
 int	freefid(int);
 Fid	*newfid(int);
 Fsrpc	*getsbuf(void);
+void	putsbuf(Fsrpc*);
 void	initroot(void);
 void	fatal(char*, ...);
 char*	makepath(File*, char*);
--- a/sys/src/cmd/exportfs/exportsrv.c
+++ b/sys/src/cmd/exportfs/exportsrv.c
@@ -17,6 +17,7 @@
 char Enomem[] = "No memory";
 char Eversion[] = "Bad 9P2000 version";
 char Ereadonly[] = "File system read only";
+char Enoprocs[] = "Out of processes";
 
 ulong messagesize;
 int readonly;
@@ -28,7 +29,7 @@
 
 	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)
@@ -36,13 +37,13 @@
 	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
@@ -51,34 +52,31 @@
 	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
@@ -92,7 +90,7 @@
 	f = newfid(t->work.fid);
 	if(f == 0) {
 		reply(&t->work, &rhdr, Ebadfid);
-		t->busy = 0;
+		putsbuf(t);
 		return;
 	}
 
@@ -100,8 +98,8 @@
 		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++)
@@ -118,8 +116,8 @@
 		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;
 		}
@@ -132,7 +130,7 @@
 
 	rhdr.qid = f->f->qid;
 	reply(&t->work, &rhdr, 0);
-	t->busy = 0;
+	putsbuf(t);
 }
 
 Fid*
@@ -169,7 +167,7 @@
 	f = getfid(t->work.fid);
 	if(f == 0) {
 		reply(&t->work, &rhdr, Ebadfid);
-		t->busy = 0;
+		putsbuf(t);
 		return;
 	}
 
@@ -215,7 +213,7 @@
 	if(rhdr.nwqid > 0)
 		e = nil;
 	reply(&t->work, &rhdr, e);
-	t->busy = 0;
+	putsbuf(t);
 }
 
 void
@@ -227,7 +225,7 @@
 	f = getfid(t->work.fid);
 	if(f == 0) {
 		reply(&t->work, &rhdr, Ebadfid);
-		t->busy = 0;
+		putsbuf(t);
 		return;
 	}
 
@@ -236,7 +234,7 @@
 
 	freefid(t->work.fid);
 	reply(&t->work, &rhdr, 0);
-	t->busy = 0;
+	putsbuf(t);
 }
 
 void
@@ -252,7 +250,7 @@
 	f = getfid(t->work.fid);
 	if(f == 0) {
 		reply(&t->work, &rhdr, Ebadfid);
-		t->busy = 0;
+		putsbuf(t);
 		return;
 	}
 	if(f->fid >= 0)
@@ -266,7 +264,7 @@
 	if(d == nil) {
 		errstr(err, sizeof err);
 		reply(&t->work, &rhdr, err);
-		t->busy = 0;
+		putsbuf(t);
 		return;
 	}
 
@@ -279,7 +277,7 @@
 	rhdr.stat = statbuf;
 	reply(&t->work, &rhdr, 0);
 	free(statbuf);
-	t->busy = 0;
+	putsbuf(t);
 }
 
 static int
@@ -303,13 +301,13 @@
 
 	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;
 	}
 	
@@ -320,7 +318,7 @@
 	if(f->fid < 0) {
 		errstr(err, sizeof err);
 		reply(&t->work, &rhdr, err);
-		t->busy = 0;
+		putsbuf(t);
 		return;
 	}
 
@@ -328,7 +326,7 @@
 	if(nf == 0) {
 		errstr(err, sizeof err);
 		reply(&t->work, &rhdr, err);
-		t->busy = 0;
+		putsbuf(t);
 		return;
 	}
 
@@ -338,7 +336,7 @@
 	rhdr.qid = f->f->qid;
 	rhdr.iounit = getiounit(f->fid);
 	reply(&t->work, &rhdr, 0);
-	t->busy = 0;
+	putsbuf(t);
 }
 
 void
@@ -350,13 +348,13 @@
 
 	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;
 	}
 
@@ -366,7 +364,7 @@
 		free(path);
 		errstr(err, sizeof err);
 		reply(&t->work, &rhdr, err);
-		t->busy = 0;
+		putsbuf(t);
 		return;
 	}
 	free(path);
@@ -377,7 +375,7 @@
 	freefid(t->work.fid);
 
 	reply(&t->work, &rhdr, 0);
-	t->busy = 0;
+	putsbuf(t);
 }
 
 void
@@ -392,13 +390,13 @@
 
 	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 */
@@ -405,7 +403,7 @@
 	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;
 	}
@@ -430,7 +428,7 @@
 		reply(&t->work, &rhdr, 0);
 	}
 	free(strings);
-	t->busy = 0;
+	putsbuf(t);
 }
 
 /*
@@ -470,12 +468,12 @@
 		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;
 			}
 		}
@@ -484,8 +482,11 @@
 		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;
@@ -492,9 +493,12 @@
 			}	
 		}
 
-		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:
@@ -511,16 +515,13 @@
 			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)
+				;
 		}
 	}
 }
@@ -537,7 +538,10 @@
 
 	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);
@@ -544,7 +548,7 @@
 		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;
 
@@ -570,8 +574,8 @@
 			p->work.tag = p->flushtag;
 			reply(&p->work, &rhdr, 0);
 		}
-		p->busy = 0;
 		m->busy = 0;
+		putsbuf(p);
 	}
 }
 
@@ -703,8 +707,10 @@
 	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))
--- a/sys/src/cmd/exportfs/pattern.c
+++ b/sys/src/cmd/exportfs/pattern.c
@@ -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;
--