RDMA/nes: Abnormal listener exit causes loopback node crash

When the listener is destroyed for a loopback connection, the listener
node gets a reset event.  This causes a crash as the listener is not
expecting a reset event.  Code review of cm_event_reset() during
debugging showed the cm_id ref count is incremented after calling its
event handler and not before.

Signed-off-by: Faisal Latif <faisal.latif@intel.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
This commit is contained in:
Faisal Latif 2009-12-09 15:54:14 -08:00 committed by Roland Dreier
parent c5a7d48971
commit f9f3f1e08b
1 changed files with 3 additions and 13 deletions

View File

@ -1014,18 +1014,6 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,
cm_node->state = NES_CM_STATE_LISTENER_DESTROYED; cm_node->state = NES_CM_STATE_LISTENER_DESTROYED;
loopback->state = NES_CM_STATE_CLOSED; loopback->state = NES_CM_STATE_CLOSED;
event.cm_node = cm_node;
event.cm_info.rem_addr =
cm_node->rem_addr;
event.cm_info.loc_addr =
cm_node->loc_addr;
event.cm_info.rem_port =
cm_node->rem_port;
event.cm_info.loc_port =
cm_node->loc_port;
event.cm_info.cm_id = cm_node->cm_id;
cm_event_reset(&event);
rem_ref_cm_node(cm_node->cm_core, rem_ref_cm_node(cm_node->cm_core,
cm_node); cm_node);
@ -3440,6 +3428,8 @@ static void cm_event_reset(struct nes_cm_event *event)
nes_debug(NES_DBG_CM, "%p - cm_id = %p\n", event->cm_node, cm_id); nes_debug(NES_DBG_CM, "%p - cm_id = %p\n", event->cm_node, cm_id);
nesqp = cm_id->provider_data; nesqp = cm_id->provider_data;
if (!nesqp)
return;
nesqp->cm_id = NULL; nesqp->cm_id = NULL;
/* cm_id->provider_data = NULL; */ /* cm_id->provider_data = NULL; */
@ -3451,8 +3441,8 @@ static void cm_event_reset(struct nes_cm_event *event)
cm_event.private_data = NULL; cm_event.private_data = NULL;
cm_event.private_data_len = 0; cm_event.private_data_len = 0;
ret = cm_id->event_handler(cm_id, &cm_event);
cm_id->add_ref(cm_id); cm_id->add_ref(cm_id);
ret = cm_id->event_handler(cm_id, &cm_event);
atomic_inc(&cm_closes); atomic_inc(&cm_closes);
cm_event.event = IW_CM_EVENT_CLOSE; cm_event.event = IW_CM_EVENT_CLOSE;
cm_event.status = IW_CM_EVENT_STATUS_OK; cm_event.status = IW_CM_EVENT_STATUS_OK;