mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 06:31:49 +00:00
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: Chuck Lever <chuck.lever@oracle.com>
This commit is contained in:
parent
4a85a6a332
commit
7b723008f9
@ -147,6 +147,25 @@ svcxdr_dupstr(struct nfsd4_compoundargs *argp, void *buf, u32 len)
|
||||
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
|
||||
*/
|
||||
@ -183,11 +202,10 @@ nfsd4_decode_opaque(struct nfsd4_compoundargs *argp, struct xdr_netobj *o)
|
||||
p = xdr_inline_decode(argp->xdr, len);
|
||||
if (!p)
|
||||
return nfserr_bad_xdr;
|
||||
o->data = svcxdr_tmpalloc(argp, len);
|
||||
o->data = svcxdr_savemem(argp, p, len);
|
||||
if (!o->data)
|
||||
return nfserr_jukebox;
|
||||
o->len = len;
|
||||
memcpy(o->data, p, len);
|
||||
|
||||
return nfs_ok;
|
||||
}
|
||||
@ -205,10 +223,9 @@ nfsd4_decode_component4(struct nfsd4_compoundargs *argp, char **namp, u32 *lenp)
|
||||
status = check_filename((char *)p, *lenp);
|
||||
if (status)
|
||||
return status;
|
||||
*namp = svcxdr_tmpalloc(argp, *lenp);
|
||||
*namp = svcxdr_savemem(argp, p, *lenp);
|
||||
if (!*namp)
|
||||
return nfserr_jukebox;
|
||||
memcpy(*namp, p, *lenp);
|
||||
|
||||
return nfs_ok;
|
||||
}
|
||||
@ -1200,10 +1217,9 @@ nfsd4_decode_putfh(struct nfsd4_compoundargs *argp, struct nfsd4_putfh *putfh)
|
||||
p = xdr_inline_decode(argp->xdr, putfh->pf_fhlen);
|
||||
if (!p)
|
||||
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)
|
||||
return nfserr_jukebox;
|
||||
memcpy(putfh->pf_fhval, p, putfh->pf_fhlen);
|
||||
|
||||
return nfs_ok;
|
||||
}
|
||||
@ -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);
|
||||
if (!p)
|
||||
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);
|
||||
if (!setclientid->se_callback_netid_val)
|
||||
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)
|
||||
return nfserr_bad_xdr;
|
||||
p = xdr_inline_decode(argp->xdr, setclientid->se_callback_addr_len);
|
||||
if (!p)
|
||||
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);
|
||||
if (!setclientid->se_callback_addr_val)
|
||||
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)
|
||||
return nfserr_bad_xdr;
|
||||
|
||||
@ -1375,10 +1387,9 @@ nfsd4_decode_verify(struct nfsd4_compoundargs *argp, struct nfsd4_verify *verify
|
||||
p = xdr_inline_decode(argp->xdr, verify->ve_attrlen);
|
||||
if (!p)
|
||||
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)
|
||||
return nfserr_jukebox;
|
||||
memcpy(verify->ve_attrval, p, verify->ve_attrlen);
|
||||
|
||||
return nfs_ok;
|
||||
}
|
||||
@ -2333,10 +2344,9 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
|
||||
p = xdr_inline_decode(argp->xdr, argp->taglen);
|
||||
if (!p)
|
||||
return 0;
|
||||
argp->tag = svcxdr_tmpalloc(argp, argp->taglen);
|
||||
argp->tag = svcxdr_savemem(argp, p, argp->taglen);
|
||||
if (!argp->tag)
|
||||
return 0;
|
||||
memcpy(argp->tag, p, argp->taglen);
|
||||
max_reply += xdr_align_size(argp->taglen);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user