diff options
author | Faisal Latif <faisal.latif@intel.com> | 2009-12-09 18:54:18 -0500 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2009-12-09 18:54:18 -0500 |
commit | 886f98a31586fd560fe83c44ad72e3ebe62f8e2e (patch) | |
tree | c0579b102cd6814f6aaa4f0bde6ba204bfeb03f1 /drivers/infiniband | |
parent | f9f3f1e08b4d66bfda2a0c2d49a26c80489a0725 (diff) |
RDMA/nes: Fix Xansation test crash on cm_node ref_count
While running a Xansation test, an active side node crashed. The
problem started on the passive side, which generated an STtag that was
0. The passive side sent a TERMINATE instead of an MPA REJECT msg.
The active side, receives TERMINATE and sends connect_err() and set
the cm_node state to CLOSED. The passive side sends FIN + ACK after
TERMINATE. Active side ends up in handle_ack_pkt() and send_reset().
send_reset() consumes 1 cm_node's ref_count. Because the cm_node is
in CLOSED state, which means that cm_node will be destroyed after
completion of the connect_err() indication, CM will crash after
send_reset().
Signed-off-by: Faisal Latif <faisal.latif@intel.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/hw/nes/nes_cm.c | 17 |
1 files changed, 16 insertions, 1 deletions
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index 20e21f1a18b9..a25816812ced 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c | |||
@@ -1610,6 +1610,7 @@ static void handle_syn_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1610 | break; | 1610 | break; |
1611 | case NES_CM_STATE_CLOSED: | 1611 | case NES_CM_STATE_CLOSED: |
1612 | cleanup_retrans_entry(cm_node); | 1612 | cleanup_retrans_entry(cm_node); |
1613 | add_ref_cm_node(cm_node); | ||
1613 | send_reset(cm_node, skb); | 1614 | send_reset(cm_node, skb); |
1614 | break; | 1615 | break; |
1615 | case NES_CM_STATE_TSA: | 1616 | case NES_CM_STATE_TSA: |
@@ -1661,9 +1662,15 @@ static void handle_synack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1661 | passive_open_err(cm_node, skb, 1); | 1662 | passive_open_err(cm_node, skb, 1); |
1662 | break; | 1663 | break; |
1663 | case NES_CM_STATE_LISTENING: | 1664 | case NES_CM_STATE_LISTENING: |
1665 | cm_node->tcp_cntxt.loc_seq_num = ntohl(tcph->ack_seq); | ||
1666 | cleanup_retrans_entry(cm_node); | ||
1667 | cm_node->state = NES_CM_STATE_CLOSED; | ||
1668 | send_reset(cm_node, skb); | ||
1669 | break; | ||
1664 | case NES_CM_STATE_CLOSED: | 1670 | case NES_CM_STATE_CLOSED: |
1665 | cm_node->tcp_cntxt.loc_seq_num = ntohl(tcph->ack_seq); | 1671 | cm_node->tcp_cntxt.loc_seq_num = ntohl(tcph->ack_seq); |
1666 | cleanup_retrans_entry(cm_node); | 1672 | cleanup_retrans_entry(cm_node); |
1673 | add_ref_cm_node(cm_node); | ||
1667 | send_reset(cm_node, skb); | 1674 | send_reset(cm_node, skb); |
1668 | break; | 1675 | break; |
1669 | case NES_CM_STATE_ESTABLISHED: | 1676 | case NES_CM_STATE_ESTABLISHED: |
@@ -1732,8 +1739,13 @@ static int handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1732 | dev_kfree_skb_any(skb); | 1739 | dev_kfree_skb_any(skb); |
1733 | break; | 1740 | break; |
1734 | case NES_CM_STATE_LISTENING: | 1741 | case NES_CM_STATE_LISTENING: |
1742 | cleanup_retrans_entry(cm_node); | ||
1743 | cm_node->state = NES_CM_STATE_CLOSED; | ||
1744 | send_reset(cm_node, skb); | ||
1745 | break; | ||
1735 | case NES_CM_STATE_CLOSED: | 1746 | case NES_CM_STATE_CLOSED: |
1736 | cleanup_retrans_entry(cm_node); | 1747 | cleanup_retrans_entry(cm_node); |
1748 | add_ref_cm_node(cm_node); | ||
1737 | send_reset(cm_node, skb); | 1749 | send_reset(cm_node, skb); |
1738 | break; | 1750 | break; |
1739 | case NES_CM_STATE_LAST_ACK: | 1751 | case NES_CM_STATE_LAST_ACK: |
@@ -2193,8 +2205,11 @@ static int mini_cm_close(struct nes_cm_core *cm_core, struct nes_cm_node *cm_nod | |||
2193 | case NES_CM_STATE_CLOSING: | 2205 | case NES_CM_STATE_CLOSING: |
2194 | ret = -1; | 2206 | ret = -1; |
2195 | break; | 2207 | break; |
2196 | case NES_CM_STATE_MPAREJ_RCVD: | ||
2197 | case NES_CM_STATE_LISTENING: | 2208 | case NES_CM_STATE_LISTENING: |
2209 | cleanup_retrans_entry(cm_node); | ||
2210 | send_reset(cm_node, NULL); | ||
2211 | break; | ||
2212 | case NES_CM_STATE_MPAREJ_RCVD: | ||
2198 | case NES_CM_STATE_UNKNOWN: | 2213 | case NES_CM_STATE_UNKNOWN: |
2199 | case NES_CM_STATE_INITED: | 2214 | case NES_CM_STATE_INITED: |
2200 | case NES_CM_STATE_CLOSED: | 2215 | case NES_CM_STATE_CLOSED: |