aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs3xdr.c
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2018-03-05 12:03:00 -0500
committerTrond Myklebust <trond.myklebust@hammerspace.com>2018-09-30 15:35:17 -0400
commit8d8928d87960d71f898767185b8c0e4ce3de3cbe (patch)
tree4d512261635e3b1560160af32cf30e04fdc0f643 /fs/nfs/nfs3xdr.c
parentNFSv4: Split out NFS v4.2 copy completion functions (diff)
downloadlinux-dev-8d8928d87960d71f898767185b8c0e4ce3de3cbe.tar.xz
linux-dev-8d8928d87960d71f898767185b8c0e4ce3de3cbe.zip
NFSv3: Improve NFSv3 performance when server returns no post-op attributes
When the server fails to return post-op attributes, the client's attempt to place read data directly in the page cache fails, and so we have to do an extra copy in order to realign the data with page borders. This patch attempts to detect servers that don't return post-op attributes on read (e.g. for pNFS) and adjusts the placement calculation accordingly. Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Diffstat (limited to 'fs/nfs/nfs3xdr.c')
-rw-r--r--fs/nfs/nfs3xdr.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index d8c4c10b15f7..78df4eb60f85 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -983,10 +983,11 @@ static void nfs3_xdr_enc_read3args(struct rpc_rqst *req,
const void *data)
{
const struct nfs_pgio_args *args = data;
+ unsigned int replen = args->replen ? args->replen : NFS3_readres_sz;
encode_read3args(xdr, args);
prepare_reply_buffer(req, args->pages, args->pgbase,
- args->count, NFS3_readres_sz);
+ args->count, replen);
req->rq_rcv_buf.flags |= XDRBUF_READ;
}
@@ -1675,9 +1676,11 @@ static int nfs3_xdr_dec_read3res(struct rpc_rqst *req, struct xdr_stream *xdr,
void *data)
{
struct nfs_pgio_res *result = data;
+ unsigned int pos;
enum nfs_stat status;
int error;
+ pos = xdr_stream_pos(xdr);
error = decode_nfsstat3(xdr, &status);
if (unlikely(error))
goto out;
@@ -1687,6 +1690,7 @@ static int nfs3_xdr_dec_read3res(struct rpc_rqst *req, struct xdr_stream *xdr,
result->op_status = status;
if (status != NFS3_OK)
goto out_status;
+ result->replen = 3 + ((xdr_stream_pos(xdr) - pos) >> 2);
error = decode_read3resok(xdr, result);
out:
return error;