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.
This commit is contained in:
parent
5c1feb0ef0
commit
fa5bd71218
1 changed files with 24 additions and 20 deletions
|
@ -26,8 +26,7 @@ struct Mntrpc
|
||||||
Fcall reply; /* Incoming reply */
|
Fcall reply; /* Incoming reply */
|
||||||
Mnt* m; /* Mount device during rpc */
|
Mnt* m; /* Mount device during rpc */
|
||||||
Rendez* z; /* Place to hang out */
|
Rendez* z; /* Place to hang out */
|
||||||
uchar* rpc; /* I/O Data buffer */
|
Block* w; /* copy of write rpc for cache */
|
||||||
uint rpclen; /* len of buffer */
|
|
||||||
Block* b; /* reply blocks */
|
Block* b; /* reply blocks */
|
||||||
Mntrpc* flushed; /* message this one flushes */
|
Mntrpc* flushed; /* message this one flushes */
|
||||||
char done; /* Rpc completed */
|
char done; /* Rpc completed */
|
||||||
|
@ -68,6 +67,8 @@ static void mountmux(Mnt*, Mntrpc*);
|
||||||
static void mountrpc(Mnt*, Mntrpc*);
|
static void mountrpc(Mnt*, Mntrpc*);
|
||||||
static int rpcattn(void*);
|
static int rpcattn(void*);
|
||||||
|
|
||||||
|
#define cachedchan(c) (((c)->flag & CCACHE) != 0 && (c)->mcp != nil)
|
||||||
|
|
||||||
char Esbadstat[] = "invalid directory entry received from server";
|
char Esbadstat[] = "invalid directory entry received from server";
|
||||||
char Enoversion[] = "version not established for mount channel";
|
char Enoversion[] = "version not established for mount channel";
|
||||||
|
|
||||||
|
@ -659,7 +660,7 @@ mntcache(Mntrpc *r)
|
||||||
Chan *c;
|
Chan *c;
|
||||||
|
|
||||||
c = r->c;
|
c = r->c;
|
||||||
if((c->flag & CCACHE) == 0 || c->mcp == nil)
|
if(!cachedchan(c))
|
||||||
return;
|
return;
|
||||||
off = r->request.offset;
|
off = r->request.offset;
|
||||||
switch(r->reply.type){
|
switch(r->reply.type){
|
||||||
|
@ -676,9 +677,13 @@ mntcache(Mntrpc *r)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Rwrite:
|
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");
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -700,7 +705,7 @@ mntrdwr(int type, Chan *c, void *buf, long n, vlong off)
|
||||||
if(nreq > c->iounit)
|
if(nreq > c->iounit)
|
||||||
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);
|
nr = cread(c, (uchar*)uba, nreq, off);
|
||||||
if(nr > 0) {
|
if(nr > 0) {
|
||||||
nreq = nr;
|
nreq = nr;
|
||||||
|
@ -992,6 +997,7 @@ mountrpc(Mnt *m, Mntrpc *r)
|
||||||
static void
|
static void
|
||||||
mountio(Mnt *m, Mntrpc *r)
|
mountio(Mnt *m, Mntrpc *r)
|
||||||
{
|
{
|
||||||
|
Block *b;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
while(waserror()) {
|
while(waserror()) {
|
||||||
|
@ -1021,23 +1027,22 @@ mountio(Mnt *m, Mntrpc *r)
|
||||||
|
|
||||||
/* Transmit a file system rpc */
|
/* Transmit a file system rpc */
|
||||||
n = sizeS2M(&r->request);
|
n = sizeS2M(&r->request);
|
||||||
if(n > r->rpclen) {
|
b = allocb(n);
|
||||||
free(r->rpc);
|
if(waserror()){
|
||||||
r->rpc = mallocz(((uint)n+127) & ~127, 0);
|
freeb(b);
|
||||||
if(r->rpc == nil) {
|
nexterror();
|
||||||
r->rpclen = 0;
|
|
||||||
exhausted("mount rpc buffer");
|
|
||||||
}
|
|
||||||
r->rpclen = msize(r->rpc);
|
|
||||||
}
|
}
|
||||||
n = convS2M(&r->request, r->rpc, r->rpclen);
|
n = convS2M(&r->request, b->wp, n);
|
||||||
if(n <= 0 || n > m->msize) {
|
if(n <= 0 || n > m->msize) {
|
||||||
print("mountio: proc %s %lud: convS2M returned %d for tag %d fid %d T%d\n",
|
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);
|
up->text, up->pid, n, r->request.tag, r->request.fid, r->request.type);
|
||||||
error(Emountrpc);
|
error(Emountrpc);
|
||||||
}
|
}
|
||||||
if(devtab[m->c->type]->write(m->c, r->rpc, n, 0) != n)
|
b->wp += n;
|
||||||
error(Emountrpc);
|
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 */
|
/* Gate readers onto the mount point one at a time */
|
||||||
for(;;) {
|
for(;;) {
|
||||||
|
@ -1288,8 +1293,6 @@ mntralloc(Chan *c)
|
||||||
new = malloc(sizeof(Mntrpc));
|
new = malloc(sizeof(Mntrpc));
|
||||||
if(new == nil)
|
if(new == nil)
|
||||||
exhausted("mount rpc header");
|
exhausted("mount rpc header");
|
||||||
new->rpc = nil;
|
|
||||||
new->rpclen = 0;
|
|
||||||
lock(&mntalloc);
|
lock(&mntalloc);
|
||||||
new->request.tag = alloctag();
|
new->request.tag = alloctag();
|
||||||
} else {
|
} else {
|
||||||
|
@ -1308,12 +1311,14 @@ mntralloc(Chan *c)
|
||||||
new->done = 0;
|
new->done = 0;
|
||||||
new->flushed = nil;
|
new->flushed = nil;
|
||||||
new->b = nil;
|
new->b = nil;
|
||||||
|
new->w = nil;
|
||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mntfree(Mntrpc *r)
|
mntfree(Mntrpc *r)
|
||||||
{
|
{
|
||||||
|
freeb(r->w);
|
||||||
freeblist(r->b);
|
freeblist(r->b);
|
||||||
lock(&mntalloc);
|
lock(&mntalloc);
|
||||||
mntalloc.nrpcused--;
|
mntalloc.nrpcused--;
|
||||||
|
@ -1326,7 +1331,6 @@ mntfree(Mntrpc *r)
|
||||||
}
|
}
|
||||||
freetag(r->request.tag);
|
freetag(r->request.tag);
|
||||||
unlock(&mntalloc);
|
unlock(&mntalloc);
|
||||||
free(r->rpc);
|
|
||||||
free(r);
|
free(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue