aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorEli Cohen <eli@mellanox.co.il>2006-01-12 17:32:20 -0500
committerRoland Dreier <rolandd@cisco.com>2006-01-12 17:32:20 -0500
commit988bd50300ef2e2d5cb8563e2ac99453dd9acd86 (patch)
tree2ffc52fb4b88a8c9299306880d07062947ce3b32 /drivers/infiniband
parent78bfe0b5b67fe126ed98608e42e42fb6ed9aabd4 (diff)
IPoIB: Fix memory leak of multicast group structures
The current handling of multicast groups in IPoIB ends up never freeing send-only multicast groups. It turns out the logic was much more complicated than it needed to be; we can fix this bug and completely kill ipoib_mcast_dev_down() at the same time. Signed-off-by: Eli Cohen <eli@mellanox.co.il> Signed-off-by: Michael S. Tsirkin <mst@mellanox.co.il> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c13
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c61
2 files changed, 9 insertions, 65 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index 23885801b6d2..f7e848970794 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -453,17 +453,8 @@ int ipoib_ib_dev_down(struct net_device *dev)
453 } 453 }
454 454
455 ipoib_mcast_stop_thread(dev, 1); 455 ipoib_mcast_stop_thread(dev, 1);
456
457 /*
458 * Flush the multicast groups first so we stop any multicast joins. The
459 * completion thread may have already died and we may deadlock waiting
460 * for the completion thread to finish some multicast joins.
461 */
462 ipoib_mcast_dev_flush(dev); 456 ipoib_mcast_dev_flush(dev);
463 457
464 /* Delete broadcast and local addresses since they will be recreated */
465 ipoib_mcast_dev_down(dev);
466
467 ipoib_flush_paths(dev); 458 ipoib_flush_paths(dev);
468 459
469 return 0; 460 return 0;
@@ -624,9 +615,7 @@ void ipoib_ib_dev_cleanup(struct net_device *dev)
624 ipoib_dbg(priv, "cleaning up ib_dev\n"); 615 ipoib_dbg(priv, "cleaning up ib_dev\n");
625 616
626 ipoib_mcast_stop_thread(dev, 1); 617 ipoib_mcast_stop_thread(dev, 1);
627 618 ipoib_mcast_dev_flush(dev);
628 /* Delete the broadcast address and the local address */
629 ipoib_mcast_dev_down(dev);
630 619
631 ipoib_transport_dev_cleanup(dev); 620 ipoib_transport_dev_cleanup(dev);
632} 621}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index bf1c08cca8cb..7403bac1977b 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -742,50 +742,23 @@ void ipoib_mcast_dev_flush(struct net_device *dev)
742{ 742{
743 struct ipoib_dev_priv *priv = netdev_priv(dev); 743 struct ipoib_dev_priv *priv = netdev_priv(dev);
744 LIST_HEAD(remove_list); 744 LIST_HEAD(remove_list);
745 struct ipoib_mcast *mcast, *tmcast, *nmcast; 745 struct ipoib_mcast *mcast, *tmcast;
746 unsigned long flags; 746 unsigned long flags;
747 747
748 ipoib_dbg_mcast(priv, "flushing multicast list\n"); 748 ipoib_dbg_mcast(priv, "flushing multicast list\n");
749 749
750 spin_lock_irqsave(&priv->lock, flags); 750 spin_lock_irqsave(&priv->lock, flags);
751 list_for_each_entry_safe(mcast, tmcast, &priv->multicast_list, list) {
752 nmcast = ipoib_mcast_alloc(dev, 0);
753 if (nmcast) {
754 nmcast->flags =
755 mcast->flags & (1 << IPOIB_MCAST_FLAG_SENDONLY);
756
757 nmcast->mcmember.mgid = mcast->mcmember.mgid;
758
759 /* Add the new group in before the to-be-destroyed group */
760 list_add_tail(&nmcast->list, &mcast->list);
761 list_del_init(&mcast->list);
762 751
763 rb_replace_node(&mcast->rb_node, &nmcast->rb_node, 752 list_for_each_entry_safe(mcast, tmcast, &priv->multicast_list, list) {
764 &priv->multicast_tree); 753 list_del(&mcast->list);
765 754 rb_erase(&mcast->rb_node, &priv->multicast_tree);
766 list_add_tail(&mcast->list, &remove_list); 755 list_add_tail(&mcast->list, &remove_list);
767 } else {
768 ipoib_warn(priv, "could not reallocate multicast group "
769 IPOIB_GID_FMT "\n",
770 IPOIB_GID_ARG(mcast->mcmember.mgid));
771 }
772 } 756 }
773 757
774 if (priv->broadcast) { 758 if (priv->broadcast) {
775 nmcast = ipoib_mcast_alloc(dev, 0); 759 rb_erase(&priv->broadcast->rb_node, &priv->multicast_tree);
776 if (nmcast) { 760 list_add_tail(&priv->broadcast->list, &remove_list);
777 nmcast->mcmember.mgid = priv->broadcast->mcmember.mgid; 761 priv->broadcast = NULL;
778
779 rb_replace_node(&priv->broadcast->rb_node,
780 &nmcast->rb_node,
781 &priv->multicast_tree);
782
783 list_add_tail(&priv->broadcast->list, &remove_list);
784 priv->broadcast = nmcast;
785 } else
786 ipoib_warn(priv, "could not reallocate broadcast group "
787 IPOIB_GID_FMT "\n",
788 IPOIB_GID_ARG(priv->broadcast->mcmember.mgid));
789 } 762 }
790 763
791 spin_unlock_irqrestore(&priv->lock, flags); 764 spin_unlock_irqrestore(&priv->lock, flags);
@@ -796,24 +769,6 @@ void ipoib_mcast_dev_flush(struct net_device *dev)
796 } 769 }
797} 770}
798 771
799void ipoib_mcast_dev_down(struct net_device *dev)
800{
801 struct ipoib_dev_priv *priv = netdev_priv(dev);
802 unsigned long flags;
803
804 /* Delete broadcast since it will be recreated */
805 if (priv->broadcast) {
806 ipoib_dbg_mcast(priv, "deleting broadcast group\n");
807
808 spin_lock_irqsave(&priv->lock, flags);
809 rb_erase(&priv->broadcast->rb_node, &priv->multicast_tree);
810 spin_unlock_irqrestore(&priv->lock, flags);
811 ipoib_mcast_leave(dev, priv->broadcast);
812 ipoib_mcast_free(priv->broadcast);
813 priv->broadcast = NULL;
814 }
815}
816
817void ipoib_mcast_restart_task(void *dev_ptr) 772void ipoib_mcast_restart_task(void *dev_ptr)
818{ 773{
819 struct net_device *dev = dev_ptr; 774 struct net_device *dev = dev_ptr;