Commit 7b723008 authored by Chuck Lever's avatar Chuck Lever

NFSD: Restore NFSv4 decoding's SAVEMEM functionality

While converting the NFSv4 decoder to use xdr_stream-based XDR
processing, I removed the old SAVEMEM() macro. This macro wrapped
a bit of logic that avoided a memory allocation by recognizing when
the decoded item resides in a linear section of the Receive buffer.
In that case, it returned a pointer into that buffer instead of
allocating a bounce buffer.

The bounce buffer is necessary only when xdr_inline_decode() has
placed the decoded item in the xdr_stream's scratch buffer, which
disappears the next time xdr_inline_decode() is called with that
xdr_stream. That happens only if the data item crosses a page
boundary in the receive buffer, an exceedingly rare occurrence.

Allocating a bounce buffer every time results in a minor performance
regression that was introduced by the recent NFSv4 decoder overhaul.
Let's restore the previous behavior. On average, it saves about 1.5
kmalloc() calls per COMPOUND.
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
parent 4a85a6a3
...@@ -147,6 +147,25 @@ svcxdr_dupstr(struct nfsd4_compoundargs *argp, void *buf, u32 len) ...@@ -147,6 +147,25 @@ svcxdr_dupstr(struct nfsd4_compoundargs *argp, void *buf, u32 len)
return p; return p;
} }
static void *
svcxdr_savemem(struct nfsd4_compoundargs *argp, __be32 *p, u32 len)
{
__be32 *tmp;
/*
* The location of the decoded data item is stable,
* so @p is OK to use. This is the common case.
*/
if (p != argp->xdr->scratch.iov_base)
return p;
tmp = svcxdr_tmpalloc(argp, len);
if (!tmp)
return NULL;
memcpy(tmp, p, len);
return tmp;
}
/* /*
* NFSv4 basic data type decoders * NFSv4 basic data type decoders
*/ */
...@@ -183,11 +202,10 @@ nfsd4_decode_opaque(struct nfsd4_compoundargs *argp, struct xdr_netobj *o) ...@@ -183,11 +202,10 @@ nfsd4_decode_opaque(struct nfsd4_compoundargs *argp, struct xdr_netobj *o)
p = xdr_inline_decode(argp->xdr, len); p = xdr_inline_decode(argp->xdr, len);
if (!p) if (!p)
return nfserr_bad_xdr; return nfserr_bad_xdr;
o->data = svcxdr_tmpalloc(argp, len); o->data = svcxdr_savemem(argp, p, len);
if (!o->data) if (!o->data)
return nfserr_jukebox; return nfserr_jukebox;
o->len = len; o->len = len;
memcpy(o->data, p, len);
return nfs_ok; return nfs_ok;
} }
...@@ -205,10 +223,9 @@ nfsd4_decode_component4(struct nfsd4_compoundargs *argp, char **namp, u32 *lenp) ...@@ -205,10 +223,9 @@ nfsd4_decode_component4(struct nfsd4_compoundargs *argp, char **namp, u32 *lenp)
status = check_filename((char *)p, *lenp); status = check_filename((char *)p, *lenp);
if (status) if (status)
return status; return status;
*namp = svcxdr_tmpalloc(argp, *lenp); *namp = svcxdr_savemem(argp, p, *lenp);
if (!*namp) if (!*namp)
return nfserr_jukebox; return nfserr_jukebox;
memcpy(*namp, p, *lenp);
return nfs_ok; return nfs_ok;
} }
...@@ -1200,10 +1217,9 @@ nfsd4_decode_putfh(struct nfsd4_compoundargs *argp, struct nfsd4_putfh *putfh) ...@@ -1200,10 +1217,9 @@ nfsd4_decode_putfh(struct nfsd4_compoundargs *argp, struct nfsd4_putfh *putfh)
p = xdr_inline_decode(argp->xdr, putfh->pf_fhlen); p = xdr_inline_decode(argp->xdr, putfh->pf_fhlen);
if (!p) if (!p)
return nfserr_bad_xdr; return nfserr_bad_xdr;
putfh->pf_fhval = svcxdr_tmpalloc(argp, putfh->pf_fhlen); putfh->pf_fhval = svcxdr_savemem(argp, p, putfh->pf_fhlen);
if (!putfh->pf_fhval) if (!putfh->pf_fhval)
return nfserr_jukebox; return nfserr_jukebox;
memcpy(putfh->pf_fhval, p, putfh->pf_fhlen);
return nfs_ok; return nfs_ok;
} }
...@@ -1318,24 +1334,20 @@ nfsd4_decode_setclientid(struct nfsd4_compoundargs *argp, struct nfsd4_setclient ...@@ -1318,24 +1334,20 @@ nfsd4_decode_setclientid(struct nfsd4_compoundargs *argp, struct nfsd4_setclient
p = xdr_inline_decode(argp->xdr, setclientid->se_callback_netid_len); p = xdr_inline_decode(argp->xdr, setclientid->se_callback_netid_len);
if (!p) if (!p)
return nfserr_bad_xdr; return nfserr_bad_xdr;
setclientid->se_callback_netid_val = svcxdr_tmpalloc(argp, setclientid->se_callback_netid_val = svcxdr_savemem(argp, p,
setclientid->se_callback_netid_len); setclientid->se_callback_netid_len);
if (!setclientid->se_callback_netid_val) if (!setclientid->se_callback_netid_val)
return nfserr_jukebox; return nfserr_jukebox;
memcpy(setclientid->se_callback_netid_val, p,
setclientid->se_callback_netid_len);
if (xdr_stream_decode_u32(argp->xdr, &setclientid->se_callback_addr_len) < 0) if (xdr_stream_decode_u32(argp->xdr, &setclientid->se_callback_addr_len) < 0)
return nfserr_bad_xdr; return nfserr_bad_xdr;
p = xdr_inline_decode(argp->xdr, setclientid->se_callback_addr_len); p = xdr_inline_decode(argp->xdr, setclientid->se_callback_addr_len);
if (!p) if (!p)
return nfserr_bad_xdr; return nfserr_bad_xdr;
setclientid->se_callback_addr_val = svcxdr_tmpalloc(argp, setclientid->se_callback_addr_val = svcxdr_savemem(argp, p,
setclientid->se_callback_addr_len); setclientid->se_callback_addr_len);
if (!setclientid->se_callback_addr_val) if (!setclientid->se_callback_addr_val)
return nfserr_jukebox; return nfserr_jukebox;
memcpy(setclientid->se_callback_addr_val, p,
setclientid->se_callback_addr_len);
if (xdr_stream_decode_u32(argp->xdr, &setclientid->se_callback_ident) < 0) if (xdr_stream_decode_u32(argp->xdr, &setclientid->se_callback_ident) < 0)
return nfserr_bad_xdr; return nfserr_bad_xdr;
...@@ -1375,10 +1387,9 @@ nfsd4_decode_verify(struct nfsd4_compoundargs *argp, struct nfsd4_verify *verify ...@@ -1375,10 +1387,9 @@ nfsd4_decode_verify(struct nfsd4_compoundargs *argp, struct nfsd4_verify *verify
p = xdr_inline_decode(argp->xdr, verify->ve_attrlen); p = xdr_inline_decode(argp->xdr, verify->ve_attrlen);
if (!p) if (!p)
return nfserr_bad_xdr; return nfserr_bad_xdr;
verify->ve_attrval = svcxdr_tmpalloc(argp, verify->ve_attrlen); verify->ve_attrval = svcxdr_savemem(argp, p, verify->ve_attrlen);
if (!verify->ve_attrval) if (!verify->ve_attrval)
return nfserr_jukebox; return nfserr_jukebox;
memcpy(verify->ve_attrval, p, verify->ve_attrlen);
return nfs_ok; return nfs_ok;
} }
...@@ -2333,10 +2344,9 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp) ...@@ -2333,10 +2344,9 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
p = xdr_inline_decode(argp->xdr, argp->taglen); p = xdr_inline_decode(argp->xdr, argp->taglen);
if (!p) if (!p)
return 0; return 0;
argp->tag = svcxdr_tmpalloc(argp, argp->taglen); argp->tag = svcxdr_savemem(argp, p, argp->taglen);
if (!argp->tag) if (!argp->tag)
return 0; return 0;
memcpy(argp->tag, p, argp->taglen);
max_reply += xdr_align_size(argp->taglen); max_reply += xdr_align_size(argp->taglen);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment