diff options
author | Eli Cohen <eli@mellanox.co.il> | 2006-01-12 17:32:20 -0500 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2006-01-12 17:32:20 -0500 |
commit | 988bd50300ef2e2d5cb8563e2ac99453dd9acd86 (patch) | |
tree | 2ffc52fb4b88a8c9299306880d07062947ce3b32 /drivers/infiniband | |
parent | 78bfe0b5b67fe126ed98608e42e42fb6ed9aabd4 (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.c | 13 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 61 |
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 | ||
799 | void 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 | |||
817 | void ipoib_mcast_restart_task(void *dev_ptr) | 772 | void ipoib_mcast_restart_task(void *dev_ptr) |
818 | { | 773 | { |
819 | struct net_device *dev = dev_ptr; | 774 | struct net_device *dev = dev_ptr; |