summaryrefslogtreecommitdiffstats
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
parent80f42368868e082c5c1dcca6ada94f6b8eab4991 (diff)
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>
-rw-r--r--fs/nfs/nfs3proc.c5
-rw-r--r--fs/nfs/nfs3xdr.c6
-rw-r--r--include/linux/nfs_fs_sb.h3
-rw-r--r--include/linux/nfs_xdr.h3
4 files changed, 15 insertions, 2 deletions
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index ec8a9efa268f..71bc16225b98 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -786,6 +786,7 @@ nfs3_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
786static int nfs3_read_done(struct rpc_task *task, struct nfs_pgio_header *hdr) 786static int nfs3_read_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
787{ 787{
788 struct inode *inode = hdr->inode; 788 struct inode *inode = hdr->inode;
789 struct nfs_server *server = NFS_SERVER(inode);
789 790
790 if (hdr->pgio_done_cb != NULL) 791 if (hdr->pgio_done_cb != NULL)
791 return hdr->pgio_done_cb(task, hdr); 792 return hdr->pgio_done_cb(task, hdr);
@@ -793,6 +794,9 @@ static int nfs3_read_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
793 if (nfs3_async_handle_jukebox(task, inode)) 794 if (nfs3_async_handle_jukebox(task, inode))
794 return -EAGAIN; 795 return -EAGAIN;
795 796
797 if (task->tk_status >= 0 && !server->read_hdrsize)
798 cmpxchg(&server->read_hdrsize, 0, hdr->res.replen);
799
796 nfs_invalidate_atime(inode); 800 nfs_invalidate_atime(inode);
797 nfs_refresh_inode(inode, &hdr->fattr); 801 nfs_refresh_inode(inode, &hdr->fattr);
798 return 0; 802 return 0;
@@ -802,6 +806,7 @@ static void nfs3_proc_read_setup(struct nfs_pgio_header *hdr,
802 struct rpc_message *msg) 806 struct rpc_message *msg)
803{ 807{
804 msg->rpc_proc = &nfs3_procedures[NFS3PROC_READ]; 808 msg->rpc_proc = &nfs3_procedures[NFS3PROC_READ];
809 hdr->args.replen = NFS_SERVER(hdr->inode)->read_hdrsize;
805} 810}
806 811
807static int nfs3_proc_pgio_rpc_prepare(struct rpc_task *task, 812static int nfs3_proc_pgio_rpc_prepare(struct rpc_task *task,
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,
983 const void *data) 983 const void *data)
984{ 984{
985 const struct nfs_pgio_args *args = data; 985 const struct nfs_pgio_args *args = data;
986 unsigned int replen = args->replen ? args->replen : NFS3_readres_sz;
986 987
987 encode_read3args(xdr, args); 988 encode_read3args(xdr, args);
988 prepare_reply_buffer(req, args->pages, args->pgbase, 989 prepare_reply_buffer(req, args->pages, args->pgbase,
989 args->count, NFS3_readres_sz); 990 args->count, replen);
990 req->rq_rcv_buf.flags |= XDRBUF_READ; 991 req->rq_rcv_buf.flags |= XDRBUF_READ;
991} 992}
992 993
@@ -1675,9 +1676,11 @@ static int nfs3_xdr_dec_read3res(struct rpc_rqst *req, struct xdr_stream *xdr,
1675 void *data) 1676 void *data)
1676{ 1677{
1677 struct nfs_pgio_res *result = data; 1678 struct nfs_pgio_res *result = data;
1679 unsigned int pos;
1678 enum nfs_stat status; 1680 enum nfs_stat status;
1679 int error; 1681 int error;
1680 1682
1683 pos = xdr_stream_pos(xdr);
1681 error = decode_nfsstat3(xdr, &status); 1684 error = decode_nfsstat3(xdr, &status);
1682 if (unlikely(error)) 1685 if (unlikely(error))
1683 goto out; 1686 goto out;
@@ -1687,6 +1690,7 @@ static int nfs3_xdr_dec_read3res(struct rpc_rqst *req, struct xdr_stream *xdr,
1687 result->op_status = status; 1690 result->op_status = status;
1688 if (status != NFS3_OK) 1691 if (status != NFS3_OK)
1689 goto out_status; 1692 goto out_status;
1693 result->replen = 3 + ((xdr_stream_pos(xdr) - pos) >> 2);
1690 error = decode_read3resok(xdr, result); 1694 error = decode_read3resok(xdr, result);
1691out: 1695out:
1692 return error; 1696 return error;
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index bf39d9c92201..0fc0b9135d46 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -228,6 +228,9 @@ struct nfs_server {
228 unsigned short mountd_port; 228 unsigned short mountd_port;
229 unsigned short mountd_protocol; 229 unsigned short mountd_protocol;
230 struct rpc_wait_queue uoc_rpcwaitq; 230 struct rpc_wait_queue uoc_rpcwaitq;
231
232 /* XDR related information */
233 unsigned int read_hdrsize;
231}; 234};
232 235
233/* Server capabilities */ 236/* Server capabilities */
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index bd1c889a9ed9..7f5535e5e852 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -608,6 +608,7 @@ struct nfs_pgio_args {
608 __u32 count; 608 __u32 count;
609 unsigned int pgbase; 609 unsigned int pgbase;
610 struct page ** pages; 610 struct page ** pages;
611 unsigned int replen; /* used by read */
611 const u32 * bitmask; /* used by write */ 612 const u32 * bitmask; /* used by write */
612 enum nfs3_stable_how stable; /* used by write */ 613 enum nfs3_stable_how stable; /* used by write */
613}; 614};
@@ -618,9 +619,9 @@ struct nfs_pgio_res {
618 __u32 count; 619 __u32 count;
619 __u32 op_status; 620 __u32 op_status;
620 int eof; /* used by read */ 621 int eof; /* used by read */
622 unsigned int replen; /* used by read */
621 struct nfs_writeverf * verf; /* used by write */ 623 struct nfs_writeverf * verf; /* used by write */
622 const struct nfs_server *server; /* used by write */ 624 const struct nfs_server *server; /* used by write */
623
624}; 625};
625 626
626/* 627/*