Skip to content

Commit 8d8928d

Browse files
trondmypdTrond Myklebust
authored andcommitted
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>
1 parent 80f4236 commit 8d8928d

File tree

4 files changed

+15
-2
lines changed

4 files changed

+15
-2
lines changed

fs/nfs/nfs3proc.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -786,13 +786,17 @@ nfs3_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
786786
static int nfs3_read_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
787787
{
788788
struct inode *inode = hdr->inode;
789+
struct nfs_server *server = NFS_SERVER(inode);
789790

790791
if (hdr->pgio_done_cb != NULL)
791792
return hdr->pgio_done_cb(task, hdr);
792793

793794
if (nfs3_async_handle_jukebox(task, inode))
794795
return -EAGAIN;
795796

797+
if (task->tk_status >= 0 && !server->read_hdrsize)
798+
cmpxchg(&server->read_hdrsize, 0, hdr->res.replen);
799+
796800
nfs_invalidate_atime(inode);
797801
nfs_refresh_inode(inode, &hdr->fattr);
798802
return 0;
@@ -802,6 +806,7 @@ static void nfs3_proc_read_setup(struct nfs_pgio_header *hdr,
802806
struct rpc_message *msg)
803807
{
804808
msg->rpc_proc = &nfs3_procedures[NFS3PROC_READ];
809+
hdr->args.replen = NFS_SERVER(hdr->inode)->read_hdrsize;
805810
}
806811

807812
static int nfs3_proc_pgio_rpc_prepare(struct rpc_task *task,

fs/nfs/nfs3xdr.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -983,10 +983,11 @@ static void nfs3_xdr_enc_read3args(struct rpc_rqst *req,
983983
const void *data)
984984
{
985985
const struct nfs_pgio_args *args = data;
986+
unsigned int replen = args->replen ? args->replen : NFS3_readres_sz;
986987

987988
encode_read3args(xdr, args);
988989
prepare_reply_buffer(req, args->pages, args->pgbase,
989-
args->count, NFS3_readres_sz);
990+
args->count, replen);
990991
req->rq_rcv_buf.flags |= XDRBUF_READ;
991992
}
992993

@@ -1675,9 +1676,11 @@ static int nfs3_xdr_dec_read3res(struct rpc_rqst *req, struct xdr_stream *xdr,
16751676
void *data)
16761677
{
16771678
struct nfs_pgio_res *result = data;
1679+
unsigned int pos;
16781680
enum nfs_stat status;
16791681
int error;
16801682

1683+
pos = xdr_stream_pos(xdr);
16811684
error = decode_nfsstat3(xdr, &status);
16821685
if (unlikely(error))
16831686
goto out;
@@ -1687,6 +1690,7 @@ static int nfs3_xdr_dec_read3res(struct rpc_rqst *req, struct xdr_stream *xdr,
16871690
result->op_status = status;
16881691
if (status != NFS3_OK)
16891692
goto out_status;
1693+
result->replen = 3 + ((xdr_stream_pos(xdr) - pos) >> 2);
16901694
error = decode_read3resok(xdr, result);
16911695
out:
16921696
return error;

include/linux/nfs_fs_sb.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,9 @@ struct nfs_server {
228228
unsigned short mountd_port;
229229
unsigned short mountd_protocol;
230230
struct rpc_wait_queue uoc_rpcwaitq;
231+
232+
/* XDR related information */
233+
unsigned int read_hdrsize;
231234
};
232235

233236
/* Server capabilities */

include/linux/nfs_xdr.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,7 @@ struct nfs_pgio_args {
608608
__u32 count;
609609
unsigned int pgbase;
610610
struct page ** pages;
611+
unsigned int replen; /* used by read */
611612
const u32 * bitmask; /* used by write */
612613
enum nfs3_stable_how stable; /* used by write */
613614
};
@@ -618,9 +619,9 @@ struct nfs_pgio_res {
618619
__u32 count;
619620
__u32 op_status;
620621
int eof; /* used by read */
622+
unsigned int replen; /* used by read */
621623
struct nfs_writeverf * verf; /* used by write */
622624
const struct nfs_server *server; /* used by write */
623-
624625
};
625626

626627
/*

0 commit comments

Comments
 (0)