Commit cf657269 authored by Santosh Shilimkar's avatar Santosh Shilimkar

RDS: IB: fix panic due to handlers running post teardown

Shutdown code reaping loop takes care of emptying the
CQ's before they being destroyed. And once tasklets are
killed, the hanlders are not expected to run.

But because of core tasklet code issues, tasklet handler could
still run even after tasklet_kill,
RDS IB shutdown code already reaps the CQs before freeing
cq/qp resources so as such the handlers have nothing left
to do post shutdown.

On other hand any handler running after teardown and trying
to access already freed qp/cq resources causes issues
Patch fixes this race by  makes sure that handlers returns
without any action post teardown.
Reviewed-by: default avatarWengang <wen.gang.wang@oracle.com>
Signed-off-by: default avatarSantosh Shilimkar <santosh.shilimkar@oracle.com>
parent 941f8d55
...@@ -185,6 +185,7 @@ struct rds_ib_connection { ...@@ -185,6 +185,7 @@ struct rds_ib_connection {
/* Endpoint role in connection */ /* Endpoint role in connection */
bool i_active_side; bool i_active_side;
atomic_t i_cq_quiesce;
/* Send/Recv vectors */ /* Send/Recv vectors */
int i_scq_vector; int i_scq_vector;
......
...@@ -128,6 +128,8 @@ void rds_ib_cm_connect_complete(struct rds_connection *conn, struct rdma_cm_even ...@@ -128,6 +128,8 @@ void rds_ib_cm_connect_complete(struct rds_connection *conn, struct rdma_cm_even
ic->i_flowctl ? ", flow control" : ""); ic->i_flowctl ? ", flow control" : "");
} }
atomic_set(&ic->i_cq_quiesce, 0);
/* Init rings and fill recv. this needs to wait until protocol /* Init rings and fill recv. this needs to wait until protocol
* negotiation is complete, since ring layout is different * negotiation is complete, since ring layout is different
* from 3.1 to 4.1. * from 3.1 to 4.1.
...@@ -267,6 +269,10 @@ static void rds_ib_tasklet_fn_send(unsigned long data) ...@@ -267,6 +269,10 @@ static void rds_ib_tasklet_fn_send(unsigned long data)
rds_ib_stats_inc(s_ib_tasklet_call); rds_ib_stats_inc(s_ib_tasklet_call);
/* if cq has been already reaped, ignore incoming cq event */
if (atomic_read(&ic->i_cq_quiesce))
return;
poll_scq(ic, ic->i_send_cq, ic->i_send_wc); poll_scq(ic, ic->i_send_cq, ic->i_send_wc);
ib_req_notify_cq(ic->i_send_cq, IB_CQ_NEXT_COMP); ib_req_notify_cq(ic->i_send_cq, IB_CQ_NEXT_COMP);
poll_scq(ic, ic->i_send_cq, ic->i_send_wc); poll_scq(ic, ic->i_send_cq, ic->i_send_wc);
...@@ -308,6 +314,10 @@ static void rds_ib_tasklet_fn_recv(unsigned long data) ...@@ -308,6 +314,10 @@ static void rds_ib_tasklet_fn_recv(unsigned long data)
rds_ib_stats_inc(s_ib_tasklet_call); rds_ib_stats_inc(s_ib_tasklet_call);
/* if cq has been already reaped, ignore incoming cq event */
if (atomic_read(&ic->i_cq_quiesce))
return;
memset(&state, 0, sizeof(state)); memset(&state, 0, sizeof(state));
poll_rcq(ic, ic->i_recv_cq, ic->i_recv_wc, &state); poll_rcq(ic, ic->i_recv_cq, ic->i_recv_wc, &state);
ib_req_notify_cq(ic->i_recv_cq, IB_CQ_SOLICITED); ib_req_notify_cq(ic->i_recv_cq, IB_CQ_SOLICITED);
...@@ -804,6 +814,8 @@ void rds_ib_conn_path_shutdown(struct rds_conn_path *cp) ...@@ -804,6 +814,8 @@ void rds_ib_conn_path_shutdown(struct rds_conn_path *cp)
tasklet_kill(&ic->i_send_tasklet); tasklet_kill(&ic->i_send_tasklet);
tasklet_kill(&ic->i_recv_tasklet); tasklet_kill(&ic->i_recv_tasklet);
atomic_set(&ic->i_cq_quiesce, 1);
/* first destroy the ib state that generates callbacks */ /* first destroy the ib state that generates callbacks */
if (ic->i_cm_id->qp) if (ic->i_cm_id->qp)
rdma_destroy_qp(ic->i_cm_id); rdma_destroy_qp(ic->i_cm_id);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment