Commit 8d8928d8 authored by Trond Myklebust's avatar Trond Myklebust Committed by Trond Myklebust

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: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
parent 80f42368
...@@ -786,6 +786,7 @@ nfs3_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, ...@@ -786,6 +786,7 @@ nfs3_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
static int nfs3_read_done(struct rpc_task *task, struct nfs_pgio_header *hdr) static int nfs3_read_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
{ {
struct inode *inode = hdr->inode; struct inode *inode = hdr->inode;
struct nfs_server *server = NFS_SERVER(inode);
if (hdr->pgio_done_cb != NULL) if (hdr->pgio_done_cb != NULL)
return hdr->pgio_done_cb(task, hdr); 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,6 +794,9 @@ static int nfs3_read_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
if (nfs3_async_handle_jukebox(task, inode)) if (nfs3_async_handle_jukebox(task, inode))
return -EAGAIN; return -EAGAIN;
if (task->tk_status >= 0 && !server->read_hdrsize)
cmpxchg(&server->read_hdrsize, 0, hdr->res.replen);
nfs_invalidate_atime(inode); nfs_invalidate_atime(inode);
nfs_refresh_inode(inode, &hdr->fattr); nfs_refresh_inode(inode, &hdr->fattr);
return 0; return 0;
...@@ -802,6 +806,7 @@ static void nfs3_proc_read_setup(struct nfs_pgio_header *hdr, ...@@ -802,6 +806,7 @@ static void nfs3_proc_read_setup(struct nfs_pgio_header *hdr,
struct rpc_message *msg) struct rpc_message *msg)
{ {
msg->rpc_proc = &nfs3_procedures[NFS3PROC_READ]; msg->rpc_proc = &nfs3_procedures[NFS3PROC_READ];
hdr->args.replen = NFS_SERVER(hdr->inode)->read_hdrsize;
} }
static int nfs3_proc_pgio_rpc_prepare(struct rpc_task *task, static int nfs3_proc_pgio_rpc_prepare(struct rpc_task *task,
......
...@@ -983,10 +983,11 @@ static void nfs3_xdr_enc_read3args(struct rpc_rqst *req, ...@@ -983,10 +983,11 @@ static void nfs3_xdr_enc_read3args(struct rpc_rqst *req,
const void *data) const void *data)
{ {
const struct nfs_pgio_args *args = data; const struct nfs_pgio_args *args = data;
unsigned int replen = args->replen ? args->replen : NFS3_readres_sz;
encode_read3args(xdr, args); encode_read3args(xdr, args);
prepare_reply_buffer(req, args->pages, args->pgbase, prepare_reply_buffer(req, args->pages, args->pgbase,
args->count, NFS3_readres_sz); args->count, replen);
req->rq_rcv_buf.flags |= XDRBUF_READ; 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, ...@@ -1675,9 +1676,11 @@ static int nfs3_xdr_dec_read3res(struct rpc_rqst *req, struct xdr_stream *xdr,
void *data) void *data)
{ {
struct nfs_pgio_res *result = data; struct nfs_pgio_res *result = data;
unsigned int pos;
enum nfs_stat status; enum nfs_stat status;
int error; int error;
pos = xdr_stream_pos(xdr);
error = decode_nfsstat3(xdr, &status); error = decode_nfsstat3(xdr, &status);
if (unlikely(error)) if (unlikely(error))
goto out; goto out;
...@@ -1687,6 +1690,7 @@ static int nfs3_xdr_dec_read3res(struct rpc_rqst *req, struct xdr_stream *xdr, ...@@ -1687,6 +1690,7 @@ static int nfs3_xdr_dec_read3res(struct rpc_rqst *req, struct xdr_stream *xdr,
result->op_status = status; result->op_status = status;
if (status != NFS3_OK) if (status != NFS3_OK)
goto out_status; goto out_status;
result->replen = 3 + ((xdr_stream_pos(xdr) - pos) >> 2);
error = decode_read3resok(xdr, result); error = decode_read3resok(xdr, result);
out: out:
return error; return error;
......
...@@ -228,6 +228,9 @@ struct nfs_server { ...@@ -228,6 +228,9 @@ struct nfs_server {
unsigned short mountd_port; unsigned short mountd_port;
unsigned short mountd_protocol; unsigned short mountd_protocol;
struct rpc_wait_queue uoc_rpcwaitq; struct rpc_wait_queue uoc_rpcwaitq;
/* XDR related information */
unsigned int read_hdrsize;
}; };
/* Server capabilities */ /* Server capabilities */
......
...@@ -608,6 +608,7 @@ struct nfs_pgio_args { ...@@ -608,6 +608,7 @@ struct nfs_pgio_args {
__u32 count; __u32 count;
unsigned int pgbase; unsigned int pgbase;
struct page ** pages; struct page ** pages;
unsigned int replen; /* used by read */
const u32 * bitmask; /* used by write */ const u32 * bitmask; /* used by write */
enum nfs3_stable_how stable; /* used by write */ enum nfs3_stable_how stable; /* used by write */
}; };
...@@ -618,9 +619,9 @@ struct nfs_pgio_res { ...@@ -618,9 +619,9 @@ struct nfs_pgio_res {
__u32 count; __u32 count;
__u32 op_status; __u32 op_status;
int eof; /* used by read */ int eof; /* used by read */
unsigned int replen; /* used by read */
struct nfs_writeverf * verf; /* used by write */ struct nfs_writeverf * verf; /* used by write */
const struct nfs_server *server; /* used by write */ const struct nfs_server *server; /* used by write */
}; };
/* /*
......
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