Loading net/ipv6/anycast.c +39 −23 Original line number Diff line number Diff line Loading @@ -203,6 +203,11 @@ void ipv6_sock_ac_close(struct sock *sk) rtnl_unlock(); } static void aca_get(struct ifacaddr6 *aca) { atomic_inc(&aca->aca_refcnt); } static void aca_put(struct ifacaddr6 *ac) { if (atomic_dec_and_test(&ac->aca_refcnt)) { Loading @@ -212,6 +217,29 @@ static void aca_put(struct ifacaddr6 *ac) } } static struct ifacaddr6 *aca_alloc(struct rt6_info *rt, const struct in6_addr *addr) { struct inet6_dev *idev = rt->rt6i_idev; struct ifacaddr6 *aca; aca = kzalloc(sizeof(*aca), GFP_ATOMIC); if (aca == NULL) return NULL; aca->aca_addr = *addr; in6_dev_hold(idev); aca->aca_idev = idev; aca->aca_rt = rt; aca->aca_users = 1; /* aca_tstamp should be updated upon changes */ aca->aca_cstamp = aca->aca_tstamp = jiffies; atomic_set(&aca->aca_refcnt, 1); spin_lock_init(&aca->aca_lock); return aca; } /* * device anycast group inc (add if not found) */ Loading @@ -223,7 +251,6 @@ int __ipv6_dev_ac_inc(struct inet6_dev *idev, const struct in6_addr *addr) ASSERT_RTNL(); in6_dev_hold(idev); write_lock_bh(&idev->lock); if (idev->dead) { err = -ENODEV; Loading @@ -238,35 +265,25 @@ int __ipv6_dev_ac_inc(struct inet6_dev *idev, const struct in6_addr *addr) } } /* * not found: create a new one. */ aca = kzalloc(sizeof(struct ifacaddr6), GFP_ATOMIC); if (aca == NULL) { err = -ENOMEM; goto out; } rt = addrconf_dst_alloc(idev, addr, true); if (IS_ERR(rt)) { kfree(aca); err = PTR_ERR(rt); goto out; } aca->aca_addr = *addr; aca->aca_idev = idev; aca->aca_rt = rt; aca->aca_users = 1; /* aca_tstamp should be updated upon changes */ aca->aca_cstamp = aca->aca_tstamp = jiffies; atomic_set(&aca->aca_refcnt, 2); spin_lock_init(&aca->aca_lock); aca = aca_alloc(rt, addr); if (aca == NULL) { ip6_rt_put(rt); err = -ENOMEM; goto out; } aca->aca_next = idev->ac_list; idev->ac_list = aca; /* Hold this for addrconf_join_solict() below before we unlock, * it is already exposed via idev->ac_list. */ aca_get(aca); write_unlock_bh(&idev->lock); ip6_ins_rt(rt); Loading @@ -277,7 +294,6 @@ int __ipv6_dev_ac_inc(struct inet6_dev *idev, const struct in6_addr *addr) return 0; out: write_unlock_bh(&idev->lock); in6_dev_put(idev); return err; } Loading Loading
net/ipv6/anycast.c +39 −23 Original line number Diff line number Diff line Loading @@ -203,6 +203,11 @@ void ipv6_sock_ac_close(struct sock *sk) rtnl_unlock(); } static void aca_get(struct ifacaddr6 *aca) { atomic_inc(&aca->aca_refcnt); } static void aca_put(struct ifacaddr6 *ac) { if (atomic_dec_and_test(&ac->aca_refcnt)) { Loading @@ -212,6 +217,29 @@ static void aca_put(struct ifacaddr6 *ac) } } static struct ifacaddr6 *aca_alloc(struct rt6_info *rt, const struct in6_addr *addr) { struct inet6_dev *idev = rt->rt6i_idev; struct ifacaddr6 *aca; aca = kzalloc(sizeof(*aca), GFP_ATOMIC); if (aca == NULL) return NULL; aca->aca_addr = *addr; in6_dev_hold(idev); aca->aca_idev = idev; aca->aca_rt = rt; aca->aca_users = 1; /* aca_tstamp should be updated upon changes */ aca->aca_cstamp = aca->aca_tstamp = jiffies; atomic_set(&aca->aca_refcnt, 1); spin_lock_init(&aca->aca_lock); return aca; } /* * device anycast group inc (add if not found) */ Loading @@ -223,7 +251,6 @@ int __ipv6_dev_ac_inc(struct inet6_dev *idev, const struct in6_addr *addr) ASSERT_RTNL(); in6_dev_hold(idev); write_lock_bh(&idev->lock); if (idev->dead) { err = -ENODEV; Loading @@ -238,35 +265,25 @@ int __ipv6_dev_ac_inc(struct inet6_dev *idev, const struct in6_addr *addr) } } /* * not found: create a new one. */ aca = kzalloc(sizeof(struct ifacaddr6), GFP_ATOMIC); if (aca == NULL) { err = -ENOMEM; goto out; } rt = addrconf_dst_alloc(idev, addr, true); if (IS_ERR(rt)) { kfree(aca); err = PTR_ERR(rt); goto out; } aca->aca_addr = *addr; aca->aca_idev = idev; aca->aca_rt = rt; aca->aca_users = 1; /* aca_tstamp should be updated upon changes */ aca->aca_cstamp = aca->aca_tstamp = jiffies; atomic_set(&aca->aca_refcnt, 2); spin_lock_init(&aca->aca_lock); aca = aca_alloc(rt, addr); if (aca == NULL) { ip6_rt_put(rt); err = -ENOMEM; goto out; } aca->aca_next = idev->ac_list; idev->ac_list = aca; /* Hold this for addrconf_join_solict() below before we unlock, * it is already exposed via idev->ac_list. */ aca_get(aca); write_unlock_bh(&idev->lock); ip6_ins_rt(rt); Loading @@ -277,7 +294,6 @@ int __ipv6_dev_ac_inc(struct inet6_dev *idev, const struct in6_addr *addr) return 0; out: write_unlock_bh(&idev->lock); in6_dev_put(idev); return err; } Loading