Skip to content

Commit 7e5a90c

Browse files
shlomopongratzrolandd
authored andcommitted
IPoIB: Fix crash due to skb double destruct
After commit b13912b ("IPoIB: Call skb_dst_drop() once skb is enqueued for sending"), using connected mode and running multithreaded iperf for long time, ie iperf -c <IP> -P 16 -t 3600 results in a crash. After the above-mentioned patch, the driver is calling skb_orphan() and skb_dst_drop() after calling post_send() in ipoib_cm.c::ipoib_cm_send() (also in ipoib_ib.c::ipoib_send()) The problem with this is, as is written in a comment in both routines, "it's entirely possible that the completion handler will run before we execute anything after the post_send()." This leads to running the skb cleanup routines simultaneously in two different contexts. The solution is to always perform the skb_orphan() and skb_dst_drop() before queueing the send work request. If an error occurs, then it will be no different than the regular case where dev_free_skb_any() in the completion path, which is assumed to be after these two routines. Signed-off-by: Shlomo Pongratz <shlomop@mellanox.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
1 parent 949db15 commit 7e5a90c

File tree

2 files changed

+6
-6
lines changed

2 files changed

+6
-6
lines changed

drivers/infiniband/ulp/ipoib/ipoib_cm.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,9 @@ void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_
741741

742742
tx_req->mapping = addr;
743743

744+
skb_orphan(skb);
745+
skb_dst_drop(skb);
746+
744747
rc = post_send(priv, tx, tx->tx_head & (ipoib_sendq_size - 1),
745748
addr, skb->len);
746749
if (unlikely(rc)) {
@@ -752,9 +755,6 @@ void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_
752755
dev->trans_start = jiffies;
753756
++tx->tx_head;
754757

755-
skb_orphan(skb);
756-
skb_dst_drop(skb);
757-
758758
if (++priv->tx_outstanding == ipoib_sendq_size) {
759759
ipoib_dbg(priv, "TX ring 0x%x full, stopping kernel net queue\n",
760760
tx->qp->qp_num);

drivers/infiniband/ulp/ipoib/ipoib_ib.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,9 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,
600600
netif_stop_queue(dev);
601601
}
602602

603+
skb_orphan(skb);
604+
skb_dst_drop(skb);
605+
603606
rc = post_send(priv, priv->tx_head & (ipoib_sendq_size - 1),
604607
address->ah, qpn, tx_req, phead, hlen);
605608
if (unlikely(rc)) {
@@ -615,9 +618,6 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,
615618

616619
address->last_send = priv->tx_head;
617620
++priv->tx_head;
618-
619-
skb_orphan(skb);
620-
skb_dst_drop(skb);
621621
}
622622

623623
if (unlikely(priv->tx_outstanding > MAX_SEND_CQE))

0 commit comments

Comments
 (0)