diff options
author | WANG Cong <xiyou.wangcong@gmail.com> | 2014-09-11 18:35:16 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-09-13 16:38:42 -0400 |
commit | 1691c63ea42d6f57ba769df401b9773664edb936 (patch) | |
tree | 1456a054df7e78b1e4f10fac2041b3673e2b35de | |
parent | f7ed925c1b4d62e82b72d8e99fa4be52fb0c73b6 (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.c | 82 |
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 | ||
644 | static 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 | |||
652 | static void igmp6_group_added(struct ifmcaddr6 *mc) | 644 | static 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 | ||
809 | static void mca_get(struct ifmcaddr6 *mc) | ||
810 | { | ||
811 | atomic_inc(&mc->mca_refcnt); | ||
812 | } | ||
813 | |||
814 | static 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 | |||
822 | static 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); |