Commit bbe165da authored by Junxian Huang's avatar Junxian Huang Committed by ZhouJuan
Browse files

RDMA/hns: Fix missing cleanup when bond_grp becomes invalid

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: e62a2027 ("RDMA/hns: support RoCE bonding")
Signed-off-by: default avatarJunxian Huang <huangjunxian6@hisilicon.com>
parent 007ae199
Loading
Loading
Loading
Loading
+21 −6
Original line number Diff line number Diff line
@@ -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)