net: use synchronize_rcu_expedited()
[deliverable/linux.git] / net / ipv4 / igmp.c
index 1fd3d9ce8398053588a45086ba813adfc7744de4..672e476c8c8a824a98c99fee9c3cabe765411c72 100644 (file)
@@ -149,17 +149,11 @@ static void ip_mc_clear_src(struct ip_mc_list *pmc);
 static int ip_mc_add_src(struct in_device *in_dev, __be32 *pmca, int sfmode,
                         int sfcount, __be32 *psfsrc, int delta);
 
-
-static void ip_mc_list_reclaim(struct rcu_head *head)
-{
-       kfree(container_of(head, struct ip_mc_list, rcu));
-}
-
 static void ip_ma_put(struct ip_mc_list *im)
 {
        if (atomic_dec_and_test(&im->refcnt)) {
                in_dev_put(im->interface);
-               call_rcu(&im->rcu, ip_mc_list_reclaim);
+               kfree_rcu(im, rcu);
        }
 }
 
@@ -309,6 +303,7 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size)
        struct iphdr *pip;
        struct igmpv3_report *pig;
        struct net *net = dev_net(dev);
+       struct flowi4 fl4;
 
        while (1) {
                skb = alloc_skb(size + LL_ALLOCATED_SPACE(dev),
@@ -321,18 +316,13 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size)
        }
        igmp_skb_size(skb) = size;
 
-       rt = ip_route_output_ports(net, NULL, IGMPV3_ALL_MCR, 0,
+       rt = ip_route_output_ports(net, &fl4, NULL, IGMPV3_ALL_MCR, 0,
                                   0, 0,
                                   IPPROTO_IGMP, 0, dev->ifindex);
        if (IS_ERR(rt)) {
                kfree_skb(skb);
                return NULL;
        }
-       if (rt->rt_src == 0) {
-               kfree_skb(skb);
-               ip_rt_put(rt);
-               return NULL;
-       }
 
        skb_dst_set(skb, &rt->dst);
        skb->dev = dev;
@@ -348,8 +338,8 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size)
        pip->tos      = 0xc0;
        pip->frag_off = htons(IP_DF);
        pip->ttl      = 1;
-       pip->daddr    = rt->rt_dst;
-       pip->saddr    = rt->rt_src;
+       pip->daddr    = fl4.daddr;
+       pip->saddr    = fl4.saddr;
        pip->protocol = IPPROTO_IGMP;
        pip->tot_len  = 0;      /* filled in later */
        ip_select_ident(pip, &rt->dst, NULL);
@@ -655,6 +645,7 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc,
        struct net_device *dev = in_dev->dev;
        struct net *net = dev_net(dev);
        __be32  group = pmc ? pmc->multiaddr : 0;
+       struct flowi4 fl4;
        __be32  dst;
 
        if (type == IGMPV3_HOST_MEMBERSHIP_REPORT)
@@ -664,17 +655,12 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc,
        else
                dst = group;
 
-       rt = ip_route_output_ports(net, NULL, dst, 0,
+       rt = ip_route_output_ports(net, &fl4, NULL, dst, 0,
                                   0, 0,
                                   IPPROTO_IGMP, 0, dev->ifindex);
        if (IS_ERR(rt))
                return -1;
 
-       if (rt->rt_src == 0) {
-               ip_rt_put(rt);
-               return -1;
-       }
-
        skb = alloc_skb(IGMP_SIZE+LL_ALLOCATED_SPACE(dev), GFP_ATOMIC);
        if (skb == NULL) {
                ip_rt_put(rt);
@@ -695,7 +681,7 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc,
        iph->frag_off = htons(IP_DF);
        iph->ttl      = 1;
        iph->daddr    = dst;
-       iph->saddr    = rt->rt_src;
+       iph->saddr    = fl4.saddr;
        iph->protocol = IPPROTO_IGMP;
        ip_select_ident(iph, &rt->dst, NULL);
        ((u8*)&iph[1])[0] = IPOPT_RA;
@@ -1836,12 +1822,6 @@ done:
 }
 EXPORT_SYMBOL(ip_mc_join_group);
 
-static void ip_sf_socklist_reclaim(struct rcu_head *rp)
-{
-       kfree(container_of(rp, struct ip_sf_socklist, rcu));
-       /* sk_omem_alloc should have been decreased by the caller*/
-}
-
 static int ip_mc_leave_src(struct sock *sk, struct ip_mc_socklist *iml,
                           struct in_device *in_dev)
 {
@@ -1858,18 +1838,10 @@ static int ip_mc_leave_src(struct sock *sk, struct ip_mc_socklist *iml,
        rcu_assign_pointer(iml->sflist, NULL);
        /* decrease mem now to avoid the memleak warning */
        atomic_sub(IP_SFLSIZE(psf->sl_max), &sk->sk_omem_alloc);
-       call_rcu(&psf->rcu, ip_sf_socklist_reclaim);
+       kfree_rcu(psf, rcu);
        return err;
 }
 
-
-static void ip_mc_socklist_reclaim(struct rcu_head *rp)
-{
-       kfree(container_of(rp, struct ip_mc_socklist, rcu));
-       /* sk_omem_alloc should have been decreased by the caller*/
-}
-
-
 /*
  *     Ask a socket to leave a group.
  */
@@ -1909,7 +1881,7 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)
                rtnl_unlock();
                /* decrease mem now to avoid the memleak warning */
                atomic_sub(sizeof(*iml), &sk->sk_omem_alloc);
-               call_rcu(&iml->rcu, ip_mc_socklist_reclaim);
+               kfree_rcu(iml, rcu);
                return 0;
        }
        if (!in_dev)
@@ -2026,7 +1998,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
                                newpsl->sl_addr[i] = psl->sl_addr[i];
                        /* decrease mem now to avoid the memleak warning */
                        atomic_sub(IP_SFLSIZE(psl->sl_max), &sk->sk_omem_alloc);
-                       call_rcu(&psl->rcu, ip_sf_socklist_reclaim);
+                       kfree_rcu(psl, rcu);
                }
                rcu_assign_pointer(pmc->sflist, newpsl);
                psl = newpsl;
@@ -2127,7 +2099,7 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex)
                        psl->sl_count, psl->sl_addr, 0);
                /* decrease mem now to avoid the memleak warning */
                atomic_sub(IP_SFLSIZE(psl->sl_max), &sk->sk_omem_alloc);
-               call_rcu(&psl->rcu, ip_sf_socklist_reclaim);
+               kfree_rcu(psl, rcu);
        } else
                (void) ip_mc_del_src(in_dev, &msf->imsf_multiaddr, pmc->sfmode,
                        0, NULL, 0);
@@ -2324,7 +2296,7 @@ void ip_mc_drop_socket(struct sock *sk)
                        ip_mc_dec_group(in_dev, iml->multi.imr_multiaddr.s_addr);
                /* decrease mem now to avoid the memleak warning */
                atomic_sub(sizeof(*iml), &sk->sk_omem_alloc);
-               call_rcu(&iml->rcu, ip_mc_socklist_reclaim);
+               kfree_rcu(iml, rcu);
        }
        rtnl_unlock();
 }
This page took 0.0284 seconds and 5 git commands to generate.