lkml.org 
[lkml]   [2021]   [Aug]   [16]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.13 113/151] nbd: Aovid double completion of a request
    Date
    From: Xie Yongji <xieyongji@bytedance.com>

    [ Upstream commit cddce01160582a5f52ada3da9626c052d852ec42 ]

    There is a race between iterating over requests in
    nbd_clear_que() and completing requests in recv_work(),
    which can lead to double completion of a request.

    To fix it, flush the recv worker before iterating over
    the requests and don't abort the completed request
    while iterating.

    Fixes: 96d97e17828f ("nbd: clear_sock on netlink disconnect")
    Reported-by: Jiang Yadong <jiangyadong@bytedance.com>
    Signed-off-by: Xie Yongji <xieyongji@bytedance.com>
    Reviewed-by: Josef Bacik <josef@toxicpanda.com>
    Link: https://lore.kernel.org/r/20210813151330.96-1-xieyongji@bytedance.com
    Signed-off-by: Jens Axboe <axboe@kernel.dk>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/block/nbd.c | 14 +++++++++++---
    1 file changed, 11 insertions(+), 3 deletions(-)

    diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
    index 45d2c28c8fc8..1061894a55df 100644
    --- a/drivers/block/nbd.c
    +++ b/drivers/block/nbd.c
    @@ -805,6 +805,10 @@ static bool nbd_clear_req(struct request *req, void *data, bool reserved)
    {
    struct nbd_cmd *cmd = blk_mq_rq_to_pdu(req);

    + /* don't abort one completed request */
    + if (blk_mq_request_completed(req))
    + return true;
    +
    mutex_lock(&cmd->lock);
    cmd->status = BLK_STS_IOERR;
    mutex_unlock(&cmd->lock);
    @@ -1973,15 +1977,19 @@ static void nbd_disconnect_and_put(struct nbd_device *nbd)
    {
    mutex_lock(&nbd->config_lock);
    nbd_disconnect(nbd);
    - nbd_clear_sock(nbd);
    - mutex_unlock(&nbd->config_lock);
    + sock_shutdown(nbd);
    /*
    * Make sure recv thread has finished, so it does not drop the last
    * config ref and try to destroy the workqueue from inside the work
    - * queue.
    + * queue. And this also ensure that we can safely call nbd_clear_que()
    + * to cancel the inflight I/Os.
    */
    if (nbd->recv_workq)
    flush_workqueue(nbd->recv_workq);
    + nbd_clear_que(nbd);
    + nbd->task_setup = NULL;
    + mutex_unlock(&nbd->config_lock);
    +
    if (test_and_clear_bit(NBD_RT_HAS_CONFIG_REF,
    &nbd->config->runtime_flags))
    nbd_config_put(nbd);
    --
    2.30.2


    \
     
     \ /
      Last update: 2021-08-16 15:31    [W:3.029 / U:0.052 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site