diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2016-11-05 18:26:12 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2016-11-05 18:26:12 +0100 |
commit | fa5bd7121846bae31ede5d6851a5091e9c16683a (patch) | |
tree | b3a22709d938925a71535c98374f2b7ff0a28e12 | |
parent | 5c1feb0ef0b795e5de71e956f9ccddcd5c4b7f21 (diff) |
devmnt: avoid memory copies of I/O rpc buffer by using bwrite()
given that devmnt will almost always write into a pipe
or a network connection, which supports te bwrite routine,
we can avoid the memory copy that would have been done by
devbwrite(). this also means the i/o buffer for writes
will get freed sooner without having to wait for the 9p
rpc to get a response, saving memory.
theres one case where we have to keep the rpc arround and
that is when we write to a cached file, as we want to update
the cache with the data that was written, but the user buffer
cannot be trusted to stay the same during the rpc.
-rw-r--r-- | sys/src/9/port/devmnt.c | 44 |
1 files changed, 24 insertions, 20 deletions
diff --git a/sys/src/9/port/devmnt.c b/sys/src/9/port/devmnt.c index 96b627eb6..4f88e3832 100644 --- a/sys/src/9/port/devmnt.c +++ b/sys/src/9/port/devmnt.c @@ -26,8 +26,7 @@ struct Mntrpc Fcall reply; /* Incoming reply */ Mnt* m; /* Mount device during rpc */ Rendez* z; /* Place to hang out */ - uchar* rpc; /* I/O Data buffer */ - uint rpclen; /* len of buffer */ + Block* w; /* copy of write rpc for cache */ Block* b; /* reply blocks */ Mntrpc* flushed; /* message this one flushes */ char done; /* Rpc completed */ @@ -68,6 +67,8 @@ static void mountmux(Mnt*, Mntrpc*); static void mountrpc(Mnt*, Mntrpc*); static int rpcattn(void*); +#define cachedchan(c) (((c)->flag & CCACHE) != 0 && (c)->mcp != nil) + char Esbadstat[] = "invalid directory entry received from server"; char Enoversion[] = "version not established for mount channel"; @@ -659,7 +660,7 @@ mntcache(Mntrpc *r) Chan *c; c = r->c; - if((c->flag & CCACHE) == 0 || c->mcp == nil) + if(!cachedchan(c)) return; off = r->request.offset; switch(r->reply.type){ @@ -676,9 +677,13 @@ mntcache(Mntrpc *r) } break; case Rwrite: - if(convM2S(r->rpc, r->rpclen, &r->request) == 0) + b = r->w; + if(convM2S(b->rp, BLEN(b), &r->request) == 0) panic("convM2S"); - cwrite(c, (uchar*)r->request.data, r->request.count, off); + m = r->reply.count; + if(m > r->request.count) + m = r->request.count; + cwrite(c, (uchar*)r->request.data, m, off); break; } } @@ -700,7 +705,7 @@ mntrdwr(int type, Chan *c, void *buf, long n, vlong off) if(nreq > c->iounit) nreq = c->iounit; - if(type == Tread && (c->flag&CCACHE) != 0) { + if(type == Tread && cachedchan(c)) { nr = cread(c, (uchar*)uba, nreq, off); if(nr > 0) { nreq = nr; @@ -992,6 +997,7 @@ mountrpc(Mnt *m, Mntrpc *r) static void mountio(Mnt *m, Mntrpc *r) { + Block *b; int n; while(waserror()) { @@ -1021,23 +1027,22 @@ mountio(Mnt *m, Mntrpc *r) /* Transmit a file system rpc */ 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); + b = allocb(n); + if(waserror()){ + freeb(b); + nexterror(); } - n = convS2M(&r->request, r->rpc, r->rpclen); + n = convS2M(&r->request, b->wp, n); 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); } - if(devtab[m->c->type]->write(m->c, r->rpc, n, 0) != n) - error(Emountrpc); + b->wp += n; + if(r->request.type == Twrite && cachedchan(r->c)) + r->w = copyblock(b, n); + poperror(); + devtab[m->c->type]->bwrite(m->c, b, 0); /* Gate readers onto the mount point one at a time */ for(;;) { @@ -1288,8 +1293,6 @@ mntralloc(Chan *c) new = malloc(sizeof(Mntrpc)); if(new == nil) exhausted("mount rpc header"); - new->rpc = nil; - new->rpclen = 0; lock(&mntalloc); new->request.tag = alloctag(); } else { @@ -1308,12 +1311,14 @@ mntralloc(Chan *c) new->done = 0; new->flushed = nil; new->b = nil; + new->w = nil; return new; } static void mntfree(Mntrpc *r) { + freeb(r->w); freeblist(r->b); lock(&mntalloc); mntalloc.nrpcused--; @@ -1326,7 +1331,6 @@ mntfree(Mntrpc *r) } freetag(r->request.tag); unlock(&mntalloc); - free(r->rpc); free(r); } |