From: Junxian Huang huangjunxian6@hisilicon.com
driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I7WHE3
--------------------------------------------------------------------------
Consider running such a cmd: "ifenslave bond0 eth1 eth2; ifenslave -d bond0 eth1" The bonding condition becomes invalid right after bond_grp is allocated before the bond delayed work is scheduled.
When the bond delayed work is scheduled, as the bonding condition is invalid, the function will just do nothing but return directly, remaining the allocated bond_grp unfreed.
Currently, two flags, bond_ready and bond_state, are parsed to decide which bond work procedure will be executed. In the above problem, bond_ready is false(since the bonding condition is invalid) and bond_state is NOT_BONDED. Clean up bond_grp resource for this situation.
Fixes: e62a20278f18 ("RDMA/hns: support RoCE bonding") Signed-off-by: Junxian Huang huangjunxian6@hisilicon.com --- drivers/infiniband/hw/hns/hns_roce_bond.c | 27 ++++++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-)
diff --git a/drivers/infiniband/hw/hns/hns_roce_bond.c b/drivers/infiniband/hw/hns/hns_roce_bond.c index 1f6c6f3b738e..2f92ed730b78 100644 --- a/drivers/infiniband/hw/hns/hns_roce_bond.c +++ b/drivers/infiniband/hw/hns/hns_roce_bond.c @@ -253,6 +253,9 @@ static void hns_roce_clear_bond(struct hns_roce_bond_group *bond_grp) struct net_device *net_dev; int i, ret;
+ if (bond_grp->bond_state == HNS_ROCE_BOND_NOT_BONDED) + goto out; + bond_grp->bond_state = HNS_ROCE_BOND_NOT_BONDED; bond_grp->main_hr_dev = NULL;
@@ -267,6 +270,7 @@ static void hns_roce_clear_bond(struct hns_roce_bond_group *bond_grp) } }
+out: ret = hns_roce_cleanup_bond(bond_grp); if (!ret) ibdev_info(&bond_grp->main_hr_dev->ib_dev, @@ -388,16 +392,27 @@ static void hns_roce_do_bond(struct hns_roce_bond_group *bond_grp)
reinit_completion(&bond_grp->bond_work_done);
- if (bond_ready && bond_state == HNS_ROCE_BOND_NOT_BONDED) + if (!bond_ready) { + hns_roce_clear_bond(bond_grp); + return; + } + + switch (bond_state) { + case HNS_ROCE_BOND_NOT_BONDED: hns_roce_set_bond(bond_grp); - else if (bond_ready && bond_state == HNS_ROCE_BOND_SLAVE_CHANGESTATE) + return; + case HNS_ROCE_BOND_SLAVE_CHANGESTATE: hns_roce_slave_changestate(bond_grp); - else if (bond_ready && bond_state == HNS_ROCE_BOND_SLAVE_INC) + return; + case HNS_ROCE_BOND_SLAVE_INC: hns_roce_slave_inc(bond_grp); - else if (bond_ready && bond_state == HNS_ROCE_BOND_SLAVE_DEC) + return; + case HNS_ROCE_BOND_SLAVE_DEC: hns_roce_slave_dec(bond_grp); - else if (!bond_ready && bond_state != HNS_ROCE_BOND_NOT_BONDED) - hns_roce_clear_bond(bond_grp); + return; + default: + return; + } }
void hns_roce_do_bond_work(struct work_struct *work)