Skip to content

Commit

Permalink
IPoIB: Lock accesses to multicast packet queues
Browse files Browse the repository at this point in the history
Avoid corrupting mcast->pkt_queue by serializing access with
priv->tx_lock.  Also, update dropped packet statistics to count
multicast packets removed from pkt_queue as dropped.

Signed-off-by: Michael S. Tsirkin <mst@mellanox.co.il>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
  • Loading branch information
Michael S. Tsirkin authored and Roland Dreier committed Jan 17, 2006
1 parent 0f47ae0 commit b36f170
Showing 1 changed file with 22 additions and 3 deletions.
25 changes: 22 additions & 3 deletions drivers/infiniband/ulp/ipoib/ipoib_multicast.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast)
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ipoib_neigh *neigh, *tmp;
unsigned long flags;
int tx_dropped = 0;

ipoib_dbg_mcast(netdev_priv(dev),
"deleting multicast group " IPOIB_GID_FMT "\n",
Expand All @@ -123,8 +124,14 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast)
if (mcast->ah)
ipoib_put_ah(mcast->ah);

while (!skb_queue_empty(&mcast->pkt_queue))
while (!skb_queue_empty(&mcast->pkt_queue)) {
++tx_dropped;
dev_kfree_skb_any(skb_dequeue(&mcast->pkt_queue));
}

spin_lock_irqsave(&priv->tx_lock, flags);
priv->stats.tx_dropped += tx_dropped;
spin_unlock_irqrestore(&priv->tx_lock, flags);

kfree(mcast);
}
Expand Down Expand Up @@ -276,8 +283,10 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
}

/* actually send any queued packets */
spin_lock_irq(&priv->tx_lock);
while (!skb_queue_empty(&mcast->pkt_queue)) {
struct sk_buff *skb = skb_dequeue(&mcast->pkt_queue);
spin_unlock_irq(&priv->tx_lock);

skb->dev = dev;

Expand All @@ -288,7 +297,9 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,

if (dev_queue_xmit(skb))
ipoib_warn(priv, "dev_queue_xmit failed to requeue packet\n");
spin_lock_irq(&priv->tx_lock);
}
spin_unlock_irq(&priv->tx_lock);

return 0;
}
Expand All @@ -300,6 +311,7 @@ ipoib_mcast_sendonly_join_complete(int status,
{
struct ipoib_mcast *mcast = mcast_ptr;
struct net_device *dev = mcast->dev;
struct ipoib_dev_priv *priv = netdev_priv(dev);

if (!status)
ipoib_mcast_join_finish(mcast, mcmember);
Expand All @@ -310,8 +322,12 @@ ipoib_mcast_sendonly_join_complete(int status,
IPOIB_GID_ARG(mcast->mcmember.mgid), status);

/* Flush out any queued packets */
while (!skb_queue_empty(&mcast->pkt_queue))
spin_lock_irq(&priv->tx_lock);
while (!skb_queue_empty(&mcast->pkt_queue)) {
++priv->stats.tx_dropped;
dev_kfree_skb_any(skb_dequeue(&mcast->pkt_queue));
}
spin_unlock_irq(&priv->tx_lock);

/* Clear the busy flag so we try again */
clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
Expand Down Expand Up @@ -687,6 +703,7 @@ void ipoib_mcast_send(struct net_device *dev, union ib_gid *mgid,
if (!mcast) {
ipoib_warn(priv, "unable to allocate memory for "
"multicast structure\n");
++priv->stats.tx_dropped;
dev_kfree_skb_any(skb);
goto out;
}
Expand All @@ -700,8 +717,10 @@ void ipoib_mcast_send(struct net_device *dev, union ib_gid *mgid,
if (!mcast->ah) {
if (skb_queue_len(&mcast->pkt_queue) < IPOIB_MAX_MCAST_QUEUE)
skb_queue_tail(&mcast->pkt_queue, skb);
else
else {
++priv->stats.tx_dropped;
dev_kfree_skb_any(skb);
}

if (mcast->query)
ipoib_dbg_mcast(priv, "no address vector, "
Expand Down

0 comments on commit b36f170

Please sign in to comment.