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 /sys/src/9/port | |
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.
Diffstat (limited to 'sys/src/9/port')
-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); } |