lkml.org 
[lkml]   [2018]   [Feb]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.15 011/163] RDMA/rxe: Fix a race condition in rxe_requester()
    Date
    4.15-stable review patch.  If anyone has any objections, please let me know.

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

    From: Bart Van Assche <bart.vanassche@wdc.com>

    commit 65567e41219888feec72fee1de98ccf1efbbc16d upstream.

    The rxe driver works as follows:
    * The send queue, receive queue and completion queues are implemented as
    circular buffers.
    * ib_post_send() and ib_post_recv() calls are serialized through a spinlock.
    * Removing elements from various queues happens from tasklet
    context. Tasklets are guaranteed to run on at most one CPU. This serializes
    access to these queues. See also rxe_completer(), rxe_requester() and
    rxe_responder().
    * rxe_completer() processes the skbs queued onto qp->resp_pkts.
    * rxe_requester() handles the send queue (qp->sq.queue).
    * rxe_responder() processes the skbs queued onto qp->req_pkts.

    Since rxe_drain_req_pkts() processes qp->req_pkts, calling
    rxe_drain_req_pkts() from rxe_requester() is racy. Hence this patch.

    Reported-by: Moni Shoua <monis@mellanox.com>
    Signed-off-by: Bart Van Assche <bart.vanassche@wdc.com>
    Cc: stable@vger.kernel.org
    Signed-off-by: Doug Ledford <dledford@redhat.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/infiniband/sw/rxe/rxe_loc.h | 1 -
    drivers/infiniband/sw/rxe/rxe_req.c | 9 +--------
    drivers/infiniband/sw/rxe/rxe_resp.c | 2 +-
    3 files changed, 2 insertions(+), 10 deletions(-)

    --- a/drivers/infiniband/sw/rxe/rxe_loc.h
    +++ b/drivers/infiniband/sw/rxe/rxe_loc.h
    @@ -237,7 +237,6 @@ int rxe_srq_from_attr(struct rxe_dev *rx

    void rxe_release(struct kref *kref);

    -void rxe_drain_req_pkts(struct rxe_qp *qp, bool notify);
    int rxe_completer(void *arg);
    int rxe_requester(void *arg);
    int rxe_responder(void *arg);
    --- a/drivers/infiniband/sw/rxe/rxe_req.c
    +++ b/drivers/infiniband/sw/rxe/rxe_req.c
    @@ -594,15 +594,8 @@ int rxe_requester(void *arg)
    rxe_add_ref(qp);

    next_wqe:
    - if (unlikely(!qp->valid)) {
    - rxe_drain_req_pkts(qp, true);
    + if (unlikely(!qp->valid || qp->req.state == QP_STATE_ERROR))
    goto exit;
    - }
    -
    - if (unlikely(qp->req.state == QP_STATE_ERROR)) {
    - rxe_drain_req_pkts(qp, true);
    - goto exit;
    - }

    if (unlikely(qp->req.state == QP_STATE_RESET)) {
    qp->req.wqe_index = consumer_index(qp->sq.queue);
    --- a/drivers/infiniband/sw/rxe/rxe_resp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_resp.c
    @@ -1210,7 +1210,7 @@ static enum resp_states do_class_d1e_err
    }
    }

    -void rxe_drain_req_pkts(struct rxe_qp *qp, bool notify)
    +static void rxe_drain_req_pkts(struct rxe_qp *qp, bool notify)
    {
    struct sk_buff *skb;


    \
     
     \ /
      Last update: 2018-02-21 14:50    [W:2.694 / U:0.028 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site