diff options
| author | Roland Dreier <roland@purestorage.com> | 2012-12-19 12:16:43 -0500 |
|---|---|---|
| committer | Roland Dreier <roland@purestorage.com> | 2012-12-19 12:16:43 -0500 |
| commit | b13912bbb4a2d445c35db24586eb6ecf4707d52d (patch) | |
| tree | 1cd9be4af43845b21861384e66d93e9d71f690b2 | |
| parent | 5bd665f28db2b04a8d6fe277342479906fc60b62 (diff) | |
IPoIB: Call skb_dst_drop() once skb is enqueued for sending
Currently, IPoIB delays collecting send completions for TX packets in
order to batch work more efficiently. It does skb_orphan() right after
queuing the packets so that destructors run early, to avoid problems
like holding socket send buffers for too long (since we might not
collect a send completion until a long time after the packet is
actually sent).
However, IPoIB clears IFF_XMIT_DST_RELEASE because it actually looks
at skb_dst() to update the PMTU when it gets a too-long packet. This
means that the packets sitting in the TX ring with uncollected send
completions are holding a reference on the dst. We've seen this lead
to pathological behavior with respect to route and neighbour GC. The
easy fix for this is to call skb_dst_drop() when we call skb_orphan().
Also, give packets sent via connected mode (CM) the same skb_orphan()
/ skb_dst_drop() treatment that packets sent via datagram mode get.
Signed-off-by: Roland Dreier <roland@purestorage.com>
| -rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_cm.c | 3 | ||||
| -rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_ib.c | 3 |
2 files changed, 5 insertions, 1 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 72ae63f0072d..03103d2bd641 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c | |||
| @@ -752,6 +752,9 @@ void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_ | |||
| 752 | dev->trans_start = jiffies; | 752 | dev->trans_start = jiffies; |
| 753 | ++tx->tx_head; | 753 | ++tx->tx_head; |
| 754 | 754 | ||
| 755 | skb_orphan(skb); | ||
| 756 | skb_dst_drop(skb); | ||
| 757 | |||
| 755 | if (++priv->tx_outstanding == ipoib_sendq_size) { | 758 | if (++priv->tx_outstanding == ipoib_sendq_size) { |
| 756 | ipoib_dbg(priv, "TX ring 0x%x full, stopping kernel net queue\n", | 759 | ipoib_dbg(priv, "TX ring 0x%x full, stopping kernel net queue\n", |
| 757 | tx->qp->qp_num); | 760 | tx->qp->qp_num); |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index f10221f40803..a1bca70e20aa 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c | |||
| @@ -615,8 +615,9 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb, | |||
| 615 | 615 | ||
| 616 | address->last_send = priv->tx_head; | 616 | address->last_send = priv->tx_head; |
| 617 | ++priv->tx_head; | 617 | ++priv->tx_head; |
| 618 | skb_orphan(skb); | ||
| 619 | 618 | ||
| 619 | skb_orphan(skb); | ||
| 620 | skb_dst_drop(skb); | ||
| 620 | } | 621 | } |
| 621 | 622 | ||
| 622 | if (unlikely(priv->tx_outstanding > MAX_SEND_CQE)) | 623 | if (unlikely(priv->tx_outstanding > MAX_SEND_CQE)) |
