lkml.org 
[lkml]   [2018]   [Apr]   [25]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.14 029/183] xprtrdma: Fix backchannel allocation of extra rpcrdma_reps
    Date
    4.14-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Chuck Lever <chuck.lever@oracle.com>


    [ Upstream commit d698c4a02ee02053bbebe051322ff427a2dad56a ]

    The backchannel code uses rpcrdma_recv_buffer_put to add new reps
    to the free rep list. This also decrements rb_recv_count, which
    spoofs the receive overrun logic in rpcrdma_buffer_get_rep.

    Commit 9b06688bc3b9 ("xprtrdma: Fix additional uses of
    spin_lock_irqsave(rb_lock)") replaced the original open-coded
    list_add with a call to rpcrdma_recv_buffer_put(), but then a year
    later, commit 05c974669ece ("xprtrdma: Fix receive buffer
    accounting") added rep accounting to rpcrdma_recv_buffer_put.
    It was an oversight to let the backchannel continue to use this
    function.

    The fix this, let's combine the "add to free list" logic with
    rpcrdma_create_rep.

    Also, do not allocate RPCRDMA_MAX_BC_REQUESTS rpcrdma_reps in
    rpcrdma_buffer_create and then allocate additional rpcrdma_reps in
    rpcrdma_bc_setup_reps. Allocating the extra reps during backchannel
    set-up is sufficient.

    Fixes: 05c974669ece ("xprtrdma: Fix receive buffer accounting")
    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
    Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
    Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    net/sunrpc/xprtrdma/backchannel.c | 12 ++----------
    net/sunrpc/xprtrdma/verbs.c | 32 +++++++++++++++++++-------------
    net/sunrpc/xprtrdma/xprt_rdma.h | 2 +-
    3 files changed, 22 insertions(+), 24 deletions(-)

    --- a/net/sunrpc/xprtrdma/backchannel.c
    +++ b/net/sunrpc/xprtrdma/backchannel.c
    @@ -74,21 +74,13 @@ out_fail:
    static int rpcrdma_bc_setup_reps(struct rpcrdma_xprt *r_xprt,
    unsigned int count)
    {
    - struct rpcrdma_rep *rep;
    int rc = 0;

    while (count--) {
    - rep = rpcrdma_create_rep(r_xprt);
    - if (IS_ERR(rep)) {
    - pr_err("RPC: %s: reply buffer alloc failed\n",
    - __func__);
    - rc = PTR_ERR(rep);
    + rc = rpcrdma_create_rep(r_xprt);
    + if (rc)
    break;
    - }
    -
    - rpcrdma_recv_buffer_put(rep);
    }
    -
    return rc;
    }

    --- a/net/sunrpc/xprtrdma/verbs.c
    +++ b/net/sunrpc/xprtrdma/verbs.c
    @@ -951,10 +951,17 @@ rpcrdma_create_req(struct rpcrdma_xprt *
    return req;
    }

    -struct rpcrdma_rep *
    +/**
    + * rpcrdma_create_rep - Allocate an rpcrdma_rep object
    + * @r_xprt: controlling transport
    + *
    + * Returns 0 on success or a negative errno on failure.
    + */
    +int
    rpcrdma_create_rep(struct rpcrdma_xprt *r_xprt)
    {
    struct rpcrdma_create_data_internal *cdata = &r_xprt->rx_data;
    + struct rpcrdma_buffer *buf = &r_xprt->rx_buf;
    struct rpcrdma_rep *rep;
    int rc;

    @@ -979,12 +986,18 @@ rpcrdma_create_rep(struct rpcrdma_xprt *
    rep->rr_recv_wr.wr_cqe = &rep->rr_cqe;
    rep->rr_recv_wr.sg_list = &rep->rr_rdmabuf->rg_iov;
    rep->rr_recv_wr.num_sge = 1;
    - return rep;
    +
    + spin_lock(&buf->rb_lock);
    + list_add(&rep->rr_list, &buf->rb_recv_bufs);
    + spin_unlock(&buf->rb_lock);
    + return 0;

    out_free:
    kfree(rep);
    out:
    - return ERR_PTR(rc);
    + dprintk("RPC: %s: reply buffer %d alloc failed\n",
    + __func__, rc);
    + return rc;
    }

    int
    @@ -1027,17 +1040,10 @@ rpcrdma_buffer_create(struct rpcrdma_xpr
    }

    INIT_LIST_HEAD(&buf->rb_recv_bufs);
    - for (i = 0; i < buf->rb_max_requests + RPCRDMA_MAX_BC_REQUESTS; i++) {
    - struct rpcrdma_rep *rep;
    -
    - rep = rpcrdma_create_rep(r_xprt);
    - if (IS_ERR(rep)) {
    - dprintk("RPC: %s: reply buffer %d alloc failed\n",
    - __func__, i);
    - rc = PTR_ERR(rep);
    + for (i = 0; i <= buf->rb_max_requests; i++) {
    + rc = rpcrdma_create_rep(r_xprt);
    + if (rc)
    goto out;
    - }
    - list_add(&rep->rr_list, &buf->rb_recv_bufs);
    }

    return 0;
    --- a/net/sunrpc/xprtrdma/xprt_rdma.h
    +++ b/net/sunrpc/xprtrdma/xprt_rdma.h
    @@ -550,8 +550,8 @@ int rpcrdma_ep_post_recv(struct rpcrdma_
    * Buffer calls - xprtrdma/verbs.c
    */
    struct rpcrdma_req *rpcrdma_create_req(struct rpcrdma_xprt *);
    -struct rpcrdma_rep *rpcrdma_create_rep(struct rpcrdma_xprt *);
    void rpcrdma_destroy_req(struct rpcrdma_req *);
    +int rpcrdma_create_rep(struct rpcrdma_xprt *r_xprt);
    int rpcrdma_buffer_create(struct rpcrdma_xprt *);
    void rpcrdma_buffer_destroy(struct rpcrdma_buffer *);


    \
     
     \ /
      Last update: 2018-04-25 13:23    [W:4.322 / U:0.008 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site