]> git.baikalelectronics.ru Git - kernel.git/commitdiff
NFSv3: Improve NFSv3 performance when server returns no post-op attributes
authorTrond Myklebust <trond.myklebust@primarydata.com>
Mon, 5 Mar 2018 17:03:00 +0000 (12:03 -0500)
committerTrond Myklebust <trond.myklebust@hammerspace.com>
Sun, 30 Sep 2018 19:35:17 +0000 (15:35 -0400)
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>
fs/nfs/nfs3proc.c
fs/nfs/nfs3xdr.c
include/linux/nfs_fs_sb.h
include/linux/nfs_xdr.h

index ec8a9efa268fec13f78daaf347b37a6b707d6f1e..71bc16225b9817ece6719a687c2c7c18d4ca81ef 100644 (file)
@@ -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)
 {
        struct inode *inode = hdr->inode;
+       struct nfs_server *server = NFS_SERVER(inode);
 
        if (hdr->pgio_done_cb != NULL)
                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)
        if (nfs3_async_handle_jukebox(task, inode))
                return -EAGAIN;
 
+       if (task->tk_status >= 0 && !server->read_hdrsize)
+               cmpxchg(&server->read_hdrsize, 0, hdr->res.replen);
+
        nfs_invalidate_atime(inode);
        nfs_refresh_inode(inode, &hdr->fattr);
        return 0;
@@ -802,6 +806,7 @@ static void nfs3_proc_read_setup(struct nfs_pgio_header *hdr,
                                 struct rpc_message *msg)
 {
        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,
index d8c4c10b15f7979ba221d822e63d76ba35997de6..78df4eb60f85b50561710e4c7285958c0674f947 100644 (file)
@@ -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;
index bf39d9c92201f811c76df9db76ab44a60b29eb41..0fc0b9135d461bc81e1aa06b2fc8040583db3dc9 100644 (file)
@@ -228,6 +228,9 @@ struct nfs_server {
        unsigned short          mountd_port;
        unsigned short          mountd_protocol;
        struct rpc_wait_queue   uoc_rpcwaitq;
+
+       /* XDR related information */
+       unsigned int            read_hdrsize;
 };
 
 /* Server capabilities */
index bd1c889a9ed956c14543117a8835eb4ae4474a9a..7f5535e5e852c6b39b7a234fc0799d52ca780ec6 100644 (file)
@@ -608,6 +608,7 @@ struct nfs_pgio_args {
        __u32                   count;
        unsigned int            pgbase;
        struct page **          pages;
+       unsigned int            replen;         /* used by read */
        const u32 *             bitmask;        /* used by write */
        enum nfs3_stable_how    stable;         /* used by write */
 };
@@ -618,9 +619,9 @@ struct nfs_pgio_res {
        __u32                   count;
        __u32                   op_status;
        int                     eof;            /* used by read */
+       unsigned int            replen;         /* used by read */
        struct nfs_writeverf *  verf;           /* used by write */
        const struct nfs_server *server;        /* used by write */
-
 };
 
 /*