Commit f4c6318f authored by D. Wythe's avatar D. Wythe Committed by Litao Jiao
Browse files

anolis: net/smc: fix deadlock when lgr terminating

anolis inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I79GVV
CVE: NA

Reference: https://gitee.com/anolis/cloud-kernel/commit/a3dbfaa26d95e1e9775869699663dbf2ff6e60e7



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

ANBZ: #1742

A potential deadlock may occur in the following scenarios:

				smc_close
__smc_lgr_terminate
				lock_sock
lock_sock

smc_conn_kill

smc_cdc_wait_pend_tx_wr

wait_event(cdc_pend_tx_wq)

Once SMC link is not available, pending CDC may not receive
their corresponding cqe. Hence, a potential deadlock has occurred.

Signed-off-by: default avatarD. Wythe <alibuda@linux.alibaba.com>
Acked-by: default avatarTony Lu <tonylu@linux.alibaba.com>
Link: https://gitee.com/anolis/cloud-kernel/pulls/577


Signed-off-by: default avatarGengbiao Shen <shengengbiao@sangfor.com.cn>
parent 7dad816c
Loading
Loading
Loading
Loading
+8 −4
Original line number Diff line number Diff line
@@ -133,7 +133,8 @@ int smc_cdc_msg_send(struct smc_connection *conn,
	} else {
		conn->tx_cdc_seq--;
		conn->local_tx_ctrl.seqno = conn->tx_cdc_seq;
		atomic_dec(&conn->cdc_pend_tx_wr);
		if (atomic_dec_and_test(&conn->cdc_pend_tx_wr) || smc_link_usable(conn->lnk))
			wake_up(&conn->cdc_pend_tx_wq);
	}

	return rc;
@@ -165,8 +166,10 @@ int smcr_cdc_msg_send_validation(struct smc_connection *conn,
	smp_mb__after_atomic(); /* Make sure cdc_pend_tx_wr added before post */

	rc = smc_wr_tx_send(link, (struct smc_wr_tx_pend_priv *)pend);
	if (unlikely(rc))
		atomic_dec(&conn->cdc_pend_tx_wr);
	if (unlikely(rc)) {
		if (atomic_dec_and_test(&conn->cdc_pend_tx_wr) || smc_link_usable(conn->lnk))
			wake_up(&conn->cdc_pend_tx_wq);
	}

	return rc;
}
@@ -226,7 +229,8 @@ int smc_cdc_get_slot_and_msg_send(struct smc_connection *conn)

void smc_cdc_wait_pend_tx_wr(struct smc_connection *conn)
{
	wait_event(conn->cdc_pend_tx_wq, !atomic_read(&conn->cdc_pend_tx_wr));
	wait_event(conn->cdc_pend_tx_wq, !atomic_read(&conn->cdc_pend_tx_wr) ||
		   !smc_link_usable(conn->lnk) || conn->lgr->terminating);
}

/* Send a SMC-D CDC header.
+4 −0
Original line number Diff line number Diff line
@@ -994,6 +994,8 @@ static void __smc_lgr_terminate(struct smc_link_group *lgr, bool soft)
	/* cancel free_work sync, will terminate when lgr->freeing is set */
	cancel_delayed_work(&lgr->free_work);
	lgr->terminating = 1;
	/* memory barrier */
	smp_wmb();

	/* kill remaining link group connections */
	read_lock_bh(&lgr->conns_lock);
@@ -1003,6 +1005,8 @@ static void __smc_lgr_terminate(struct smc_link_group *lgr, bool soft)
		conn = rb_entry(node, struct smc_connection, alert_node);
		smc = container_of(conn, struct smc_sock, conn);
		sock_hold(&smc->sk); /* sock_put below */
		/* try wakeup all */
		wake_up_all(&conn->cdc_pend_tx_wq);
		lock_sock(&smc->sk);
		smc_conn_kill(conn, soft);
		release_sock(&smc->sk);