shithub: riscv

Download patch

ref: ff494b954f950a3b060b9770212321e7576dca49
parent: 23f78400561e0172a55e1fad8172a848d9cafab6
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Mon Jul 27 00:33:46 EDT 2015

devmnt: use c->iounit instead of msize-IOHDRSZ to chunk reads and writes, reduce memory overhead for Mntrpc, mntalloc lock

use the actual iounit returned from Ropen/Rcreate to chunk reads and writes
instead of c->mux->msize-IOHDRSZ.

dont preallocate the rpc buffers to msize, most 9p requests are rather small
(except Twrite of course). so we allocate the buffer on demand in mountio()
with some rounding to avoid frequent reallocations.

avoid malloc()/free() while holding mntalloc lock.

--- a/sys/src/9/port/devmnt.c
+++ b/sys/src/9/port/devmnt.c
@@ -48,21 +48,21 @@
 	Mnt*	list;		/* Mount devices in use */
 	Mnt*	mntfree;	/* Free list */
 	Mntrpc*	rpcfree;
-	int	nrpcfree;
-	int	nrpcused;
+	ulong	nrpcfree;
+	ulong	nrpcused;
 	ulong	id;
 	ulong	tagmask[NMASK];
-}mntalloc;
+} mntalloc;
 
 static Chan*	mntchan(void);
 static Mnt*	mntchk(Chan*);
 static void	mntdirfix(uchar*, Chan*);
-static Mntrpc*	mntflushalloc(Mntrpc*, ulong);
+static Mntrpc*	mntflushalloc(Mntrpc*);
 static Mntrpc*	mntflushfree(Mnt*, Mntrpc*);
 static void	mntfree(Mntrpc*);
 static void	mntgate(Mnt*);
 static void	mntqrm(Mnt*, Mntrpc*);
-static Mntrpc*	mntralloc(Chan*, ulong);
+static Mntrpc*	mntralloc(Chan*);
 static long	mntrdwr(int, Chan*, void*, long, vlong);
 static int	mntrpcread(Mnt*, Mntrpc*);
 static void	mountio(Mnt*, Mntrpc*);
@@ -213,13 +213,14 @@
 	if(m != nil)
 		mntalloc.mntfree = m->list;
 	else {
+		unlock(&mntalloc);
 		m = malloc(sizeof(Mnt));
 		if(m == nil) {
 			qfree(q);
 			free(v);
-			unlock(&mntalloc);
 			exhausted("mount devices");
 		}
+		lock(&mntalloc);
 	}
 	m->list = mntalloc.list;
 	mntalloc.list = m;
@@ -273,7 +274,7 @@
 		nexterror();
 	}
 
-	r = mntralloc(0, m->msize);
+	r = mntralloc(c);
 	if(waserror()) {
 		mntfree(r);
 		nexterror();
@@ -290,6 +291,7 @@
 	incref(m->c);
 	c->mqid = c->qid;
 	c->mode = ORDWR;
+	c->iounit = m->msize-IOHDRSZ;
 
 	poperror();	/* r */
 	mntfree(r);
@@ -333,8 +335,7 @@
 		nexterror();
 	}
 
-	r = mntralloc(0, m->msize);
-
+	r = mntralloc(c);
 	if(waserror()) {
 		mntfree(r);
 		nexterror();
@@ -374,7 +375,7 @@
 	c->dev = mntalloc.id++;
 	unlock(&mntalloc);
 
-	if(c->mchan)
+	if(c->mchan != nil)
 		panic("mntchan non-zero %p", c->mchan);
 	return c;
 }
@@ -402,7 +403,7 @@
 
 	alloc = 0;
 	m = mntchk(c);
-	r = mntralloc(c, m->msize);
+	r = mntralloc(c);
 	if(nc == nil){
 		nc = devclone(c);
 		/*
@@ -470,7 +471,7 @@
 	if(n < BIT16SZ)
 		error(Eshortstat);
 	m = mntchk(c);
-	r = mntralloc(c, m->msize);
+	r = mntralloc(c);
 	if(waserror()) {
 		mntfree(r);
 		nexterror();
@@ -500,7 +501,7 @@
 	Mntrpc *r;
 
 	m = mntchk(c);
-	r = mntralloc(c, m->msize);
+	r = mntralloc(c);
 	if(waserror()) {
 		mntfree(r);
 		nexterror();
@@ -550,8 +551,8 @@
 
 	cclunk(c);
 	m = mntchk(c);
-	r = mntralloc(c, m->msize);
-	if(waserror()){
+	r = mntralloc(c);
+	if(waserror()) {
 		mntfree(r);
 		nexterror();
 	}
@@ -611,7 +612,7 @@
 	Mntrpc *r;
 
 	m = mntchk(c);
-	r = mntralloc(c, m->msize);
+	r = mntralloc(c);
 	if(waserror()) {
 		mntfree(r);
 		nexterror();
@@ -702,8 +703,8 @@
 
 	for(;;) {
 		nreq = n;
-		if(nreq > m->msize-IOHDRSZ)
-			nreq = m->msize-IOHDRSZ;
+		if(nreq > c->iounit)
+			nreq = c->iounit;
 
 		if(type == Tread) {
 			nr = cread(c, (uchar*)uba, nreq, off);
@@ -713,7 +714,7 @@
 			}
 		}
 
-		r = mntralloc(c, m->msize);
+		r = mntralloc(c);
 		if(waserror()) {
 			mntfree(r);
 			nexterror();
@@ -889,7 +890,6 @@
 	Mntrpc *r, **rr;
 	vlong o, w, e;
 	long n, tot;
-	Mnt *m;
 
 	if(len <= 0)
 		return 0;
@@ -915,8 +915,7 @@
 				mntfree(r);
 			}
 
-			m = mntchk(c);
-			r = mntralloc(c, m->msize);
+			r = mntralloc(c);
 			r->request.type = Tread;
 			r->request.fid = c->fid;
 			r->request.offset = o;
@@ -972,7 +971,6 @@
 static void
 mountrpc(Mnt *m, Mntrpc *r)
 {
-	char *sn, *cn;
 	int t;
 
 	r->reply.tag = 0;
@@ -989,14 +987,8 @@
 	default:
 		if(t == r->request.type+1)
 			break;
-		sn = "?";
-		if(m->c->path != nil)
-			sn = m->c->path->s;
-		cn = "?";
-		if(r->c != nil && r->c->path != nil)
-			cn = r->c->path->s;
 		print("mnt: proc %s %lud: mismatch from %s %s rep %#p tag %d fid %d T%d R%d rp %d\n",
-			up->text, up->pid, sn, cn,
+			up->text, up->pid, chanpath(m->c), chanpath(r->c),
 			r, r->request.tag, r->request.fid, r->request.type,
 			r->reply.type, r->reply.tag);
 		error(Emountrpc);
@@ -1022,7 +1014,7 @@
 			}
 			nexterror();
 		}
-		r = mntflushalloc(r, m->msize);
+		r = mntflushalloc(r);
 		poperror();
 	}
 
@@ -1037,10 +1029,18 @@
 	unlock(m);
 
 	/* Transmit a file system rpc */
-	if(m->msize == 0)
-		panic("msize");
-	n = convS2M(&r->request, r->rpc, m->msize);
-	if(n <= 0){
+	n = sizeS2M(&r->request);
+	if(n > r->rpclen) {
+		free(r->rpc);
+		r->rpc = mallocz(((uint)n+127) & ~127, 0);
+		if(r->rpc == nil) {
+			r->rpclen = 0;
+			exhausted("mount rpc buffer");
+		}
+		r->rpclen = msize(r->rpc);
+	}
+	n = convS2M(&r->request, r->rpc, r->rpclen);
+	if(n <= 0 || n > m->msize) {
 		print("mountio: proc %s %lud: convS2M returned %d for tag %d fid %d T%d\n",
 			up->text, up->pid, n, r->request.tag, r->request.fid, r->request.type);
 		error(Emountrpc);
@@ -1059,7 +1059,7 @@
 			break;
 		unlock(m);
 		sleep(r->z, rpcattn, r);
-		if(r->done){
+		if(r->done) {
 			poperror();
 			mntflushfree(m, r);
 			return;
@@ -1229,12 +1229,11 @@
  * requests from it
  */
 static Mntrpc*
-mntflushalloc(Mntrpc *r, ulong iounit)
+mntflushalloc(Mntrpc *r)
 {
 	Mntrpc *fr;
 
-	fr = mntralloc(0, iounit);
-
+	fr = mntralloc(r->c);
 	fr->request.type = Tflush;
 	if(r->request.type == Tflush)
 		fr->request.oldtag = r->request.oldtag;
@@ -1298,45 +1297,28 @@
 }
 
 static Mntrpc*
-mntralloc(Chan *c, ulong msize)
+mntralloc(Chan *c)
 {
 	Mntrpc *new;
 
-	lock(&mntalloc);
-	new = mntalloc.rpcfree;
-	if(new == nil){
+	if(mntalloc.nrpcfree == 0) {
+	Alloc:
 		new = malloc(sizeof(Mntrpc));
+		if(new == nil)
+			exhausted("mount rpc header");
+		new->rpc = nil;
+		new->rpclen = 0;
+		lock(&mntalloc);
+		new->request.tag = alloctag();
+	} else {
+		lock(&mntalloc);
+		new = mntalloc.rpcfree;
 		if(new == nil) {
 			unlock(&mntalloc);
-			exhausted("mount rpc header");
+			goto Alloc;
 		}
-		/*
-		 * The header is split from the data buffer as
-		 * mountmux may swap the buffer with another header.
-		 */
-		new->rpc = mallocz(msize, 0);
-		if(new->rpc == nil){
-			free(new);
-			unlock(&mntalloc);
-			exhausted("mount rpc buffer");
-		}
-		new->rpclen = msize;
-		new->request.tag = alloctag();
-	}
-	else {
 		mntalloc.rpcfree = new->list;
 		mntalloc.nrpcfree--;
-		if(new->rpclen < msize){
-			free(new->rpc);
-			new->rpc = mallocz(msize, 0);
-			if(new->rpc == nil){
-				free(new);
-				mntalloc.nrpcused--;
-				unlock(&mntalloc);
-				exhausted("mount rpc buffer");
-			}
-			new->rpclen = msize;
-		}
 	}
 	mntalloc.nrpcused++;
 	unlock(&mntalloc);
@@ -1350,21 +1332,20 @@
 static void
 mntfree(Mntrpc *r)
 {
-	if(r->b != nil)
-		freeblist(r->b);
+	freeblist(r->b);
 	lock(&mntalloc);
-	if(mntalloc.nrpcfree >= 10){
-		free(r->rpc);
-		freetag(r->request.tag);
-		free(r);
-	}
-	else{
+	mntalloc.nrpcused--;
+	if(mntalloc.nrpcfree < 32) {
 		r->list = mntalloc.rpcfree;
 		mntalloc.rpcfree = r;
 		mntalloc.nrpcfree++;
+		unlock(&mntalloc);
+		return;
 	}
-	mntalloc.nrpcused--;
+	freetag(r->request.tag);
 	unlock(&mntalloc);
+	free(r->rpc);
+	free(r);
 }
 
 static void
@@ -1392,12 +1373,10 @@
 	Mnt *m;
 
 	/* This routine is mostly vestiges of prior lives; now it's just sanity checking */
-
 	if(c->mchan == nil)
 		panic("mntchk 1: nil mchan c %s", chanpath(c));
 
 	m = c->mchan->mux;
-
 	if(m == nil)
 		print("mntchk 2: nil mux c %s c->mchan %s \n", chanpath(c), chanpath(c->mchan));