aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWANG Cong <xiyou.wangcong@gmail.com>2014-09-11 18:35:16 -0400
committerDavid S. Miller <davem@davemloft.net>2014-09-13 16:38:42 -0400
commit1691c63ea42d6f57ba769df401b9773664edb936 (patch)
tree1456a054df7e78b1e4f10fac2041b3673e2b35de
parentf7ed925c1b4d62e82b72d8e99fa4be52fb0c73b6 (diff)
ipv6: refactor ipv6_dev_mc_inc()
Refactor out allocation and initialization and make the refcount code more readable. Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/ipv6/mcast.c82
1 files changed, 49 insertions, 33 deletions
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index d64e26366cb8..592eba61e78a 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -641,14 +641,6 @@ bool inet6_mc_check(struct sock *sk, const struct in6_addr *mc_addr,
641 return rv; 641 return rv;
642} 642}
643 643
644static void ma_put(struct ifmcaddr6 *mc)
645{
646 if (atomic_dec_and_test(&mc->mca_refcnt)) {
647 in6_dev_put(mc->idev);
648 kfree(mc);
649 }
650}
651
652static void igmp6_group_added(struct ifmcaddr6 *mc) 644static void igmp6_group_added(struct ifmcaddr6 *mc)
653{ 645{
654 struct net_device *dev = mc->idev->dev; 646 struct net_device *dev = mc->idev->dev;
@@ -814,6 +806,48 @@ static void mld_clear_delrec(struct inet6_dev *idev)
814 read_unlock_bh(&idev->lock); 806 read_unlock_bh(&idev->lock);
815} 807}
816 808
809static void mca_get(struct ifmcaddr6 *mc)
810{
811 atomic_inc(&mc->mca_refcnt);
812}
813
814static void ma_put(struct ifmcaddr6 *mc)
815{
816 if (atomic_dec_and_test(&mc->mca_refcnt)) {
817 in6_dev_put(mc->idev);
818 kfree(mc);
819 }
820}
821
822static struct ifmcaddr6 *mca_alloc(struct inet6_dev *idev,
823 const struct in6_addr *addr)
824{
825 struct ifmcaddr6 *mc;
826
827 mc = kzalloc(sizeof(*mc), GFP_ATOMIC);
828 if (mc == NULL)
829 return NULL;
830
831 setup_timer(&mc->mca_timer, igmp6_timer_handler, (unsigned long)mc);
832
833 mc->mca_addr = *addr;
834 mc->idev = idev; /* reference taken by caller */
835 mc->mca_users = 1;
836 /* mca_stamp should be updated upon changes */
837 mc->mca_cstamp = mc->mca_tstamp = jiffies;
838 atomic_set(&mc->mca_refcnt, 1);
839 spin_lock_init(&mc->mca_lock);
840
841 /* initial mode is (EX, empty) */
842 mc->mca_sfmode = MCAST_EXCLUDE;
843 mc->mca_sfcount[MCAST_EXCLUDE] = 1;
844
845 if (ipv6_addr_is_ll_all_nodes(&mc->mca_addr) ||
846 IPV6_ADDR_MC_SCOPE(&mc->mca_addr) < IPV6_ADDR_SCOPE_LINKLOCAL)
847 mc->mca_flags |= MAF_NOREPORT;
848
849 return mc;
850}
817 851
818/* 852/*
819 * device multicast group inc (add if not found) 853 * device multicast group inc (add if not found)
@@ -849,38 +883,20 @@ int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr)
849 } 883 }
850 } 884 }
851 885
852 /* 886 mc = mca_alloc(idev, addr);
853 * not found: create a new one. 887 if (!mc) {
854 */
855
856 mc = kzalloc(sizeof(struct ifmcaddr6), GFP_ATOMIC);
857
858 if (mc == NULL) {
859 write_unlock_bh(&idev->lock); 888 write_unlock_bh(&idev->lock);
860 in6_dev_put(idev); 889 in6_dev_put(idev);
861 return -ENOMEM; 890 return -ENOMEM;
862 } 891 }
863 892
864 setup_timer(&mc->mca_timer, igmp6_timer_handler, (unsigned long)mc);
865
866 mc->mca_addr = *addr;
867 mc->idev = idev; /* (reference taken) */
868 mc->mca_users = 1;
869 /* mca_stamp should be updated upon changes */
870 mc->mca_cstamp = mc->mca_tstamp = jiffies;
871 atomic_set(&mc->mca_refcnt, 2);
872 spin_lock_init(&mc->mca_lock);
873
874 /* initial mode is (EX, empty) */
875 mc->mca_sfmode = MCAST_EXCLUDE;
876 mc->mca_sfcount[MCAST_EXCLUDE] = 1;
877
878 if (ipv6_addr_is_ll_all_nodes(&mc->mca_addr) ||
879 IPV6_ADDR_MC_SCOPE(&mc->mca_addr) < IPV6_ADDR_SCOPE_LINKLOCAL)
880 mc->mca_flags |= MAF_NOREPORT;
881
882 mc->next = idev->mc_list; 893 mc->next = idev->mc_list;
883 idev->mc_list = mc; 894 idev->mc_list = mc;
895
896 /* Hold this for the code below before we unlock,
897 * it is already exposed via idev->mc_list.
898 */
899 mca_get(mc);
884 write_unlock_bh(&idev->lock); 900 write_unlock_bh(&idev->lock);
885 901
886 mld_del_delrec(idev, &mc->mca_addr); 902 mld_del_delrec(idev, &mc->mca_addr);