lkml.org 
[lkml]   [2022]   [Jan]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.16 0966/1039] net/smc: Fix hung_task when removing SMC-R devices
    Date
    From: Wen Gu <guwen@linux.alibaba.com>

    commit 56d99e81ecbc997a5f984684d0eeb583992b2072 upstream.

    A hung_task is observed when removing SMC-R devices. Suppose that
    a link group has two active links(lnk_A, lnk_B) associated with two
    different SMC-R devices(dev_A, dev_B). When dev_A is removed, the
    link group will be removed from smc_lgr_list and added into
    lgr_linkdown_list. lnk_A will be cleared and smcibdev(A)->lnk_cnt
    will reach to zero. However, when dev_B is removed then, the link
    group can't be found in smc_lgr_list and lnk_B won't be cleared,
    making smcibdev->lnk_cnt never reaches zero, which causes a hung_task.

    This patch fixes this issue by restoring the implementation of
    smc_smcr_terminate_all() to what it was before commit 349d43127dac
    ("net/smc: fix kernel panic caused by race of smc_sock"). The original
    implementation also satisfies the intention that make sure QP destroy
    earlier than CQ destroy because we will always wait for smcibdev->lnk_cnt
    reaches zero, which guarantees QP has been destroyed.

    Fixes: 349d43127dac ("net/smc: fix kernel panic caused by race of smc_sock")
    Signed-off-by: Wen Gu <guwen@linux.alibaba.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    net/smc/smc_core.c | 17 +----------------
    1 file changed, 1 insertion(+), 16 deletions(-)

    --- a/net/smc/smc_core.c
    +++ b/net/smc/smc_core.c
    @@ -1459,16 +1459,11 @@ void smc_smcd_terminate_all(struct smcd_
    /* Called when an SMCR device is removed or the smc module is unloaded.
    * If smcibdev is given, all SMCR link groups using this device are terminated.
    * If smcibdev is NULL, all SMCR link groups are terminated.
    - *
    - * We must wait here for QPs been destroyed before we destroy the CQs,
    - * or we won't received any CQEs and cdc_pend_tx_wr cannot reach 0 thus
    - * smc_sock cannot be released.
    */
    void smc_smcr_terminate_all(struct smc_ib_device *smcibdev)
    {
    struct smc_link_group *lgr, *lg;
    LIST_HEAD(lgr_free_list);
    - LIST_HEAD(lgr_linkdown_list);
    int i;

    spin_lock_bh(&smc_lgr_list.lock);
    @@ -1480,7 +1475,7 @@ void smc_smcr_terminate_all(struct smc_i
    list_for_each_entry_safe(lgr, lg, &smc_lgr_list.list, list) {
    for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
    if (lgr->lnk[i].smcibdev == smcibdev)
    - list_move_tail(&lgr->list, &lgr_linkdown_list);
    + smcr_link_down_cond_sched(&lgr->lnk[i]);
    }
    }
    }
    @@ -1492,16 +1487,6 @@ void smc_smcr_terminate_all(struct smc_i
    __smc_lgr_terminate(lgr, false);
    }

    - list_for_each_entry_safe(lgr, lg, &lgr_linkdown_list, list) {
    - for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
    - if (lgr->lnk[i].smcibdev == smcibdev) {
    - mutex_lock(&lgr->llc_conf_mutex);
    - smcr_link_down_cond(&lgr->lnk[i]);
    - mutex_unlock(&lgr->llc_conf_mutex);
    - }
    - }
    - }
    -
    if (smcibdev) {
    if (atomic_read(&smcibdev->lnk_cnt))
    wait_event(smcibdev->lnks_deleted,

    \
     
     \ /
      Last update: 2022-01-24 23:48    [W:4.596 / U:0.092 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site