aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2010-05-18 18:36:06 -0400
committerDavid S. Miller <davem@davemloft.net>2010-05-18 18:36:06 -0400
commite9d3e084975869754d16f639378675c353560be9 (patch)
tree3f933fea12746b24247ccec79cb4a1fbdf50833b /net
parente29f5dbc9e9719af158a960e5c1d16f32740ebc3 (diff)
ipv6: Replace inet6_ifaddr->dead with state
This patch replaces the boolean dead flag on inet6_ifaddr with a state enum. This allows us to roll back changes when deleting an address according to whether DAD has completed or not. This patch only adds the state field and does not change the logic. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/ipv6/addrconf.c16
1 files changed, 9 insertions, 7 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 75d3b8c1e856..4e5ad9de1679 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -553,7 +553,7 @@ void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp)
553 if (del_timer(&ifp->timer)) 553 if (del_timer(&ifp->timer))
554 pr_notice("Timer is still running, when freeing ifa=%p\n", ifp); 554 pr_notice("Timer is still running, when freeing ifa=%p\n", ifp);
555 555
556 if (!ifp->dead) { 556 if (ifp->state != INET6_IFADDR_STATE_DEAD) {
557 pr_warning("Freeing alive inet6 address %p\n", ifp); 557 pr_warning("Freeing alive inet6 address %p\n", ifp);
558 return; 558 return;
559 } 559 }
@@ -648,6 +648,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
648 ipv6_addr_copy(&ifa->addr, addr); 648 ipv6_addr_copy(&ifa->addr, addr);
649 649
650 spin_lock_init(&ifa->lock); 650 spin_lock_init(&ifa->lock);
651 spin_lock_init(&ifa->state_lock);
651 init_timer(&ifa->timer); 652 init_timer(&ifa->timer);
652 INIT_HLIST_NODE(&ifa->addr_lst); 653 INIT_HLIST_NODE(&ifa->addr_lst);
653 ifa->timer.data = (unsigned long) ifa; 654 ifa->timer.data = (unsigned long) ifa;
@@ -720,7 +721,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
720 721
721 hash = ipv6_addr_hash(&ifp->addr); 722 hash = ipv6_addr_hash(&ifp->addr);
722 723
723 ifp->dead = 1; 724 ifp->state = INET6_IFADDR_STATE_DEAD;
724 725
725 spin_lock_bh(&addrconf_hash_lock); 726 spin_lock_bh(&addrconf_hash_lock);
726 hlist_del_init_rcu(&ifp->addr_lst); 727 hlist_del_init_rcu(&ifp->addr_lst);
@@ -2665,7 +2666,7 @@ static int addrconf_ifdown(struct net_device *dev, int how)
2665 ifa = list_first_entry(&idev->tempaddr_list, 2666 ifa = list_first_entry(&idev->tempaddr_list,
2666 struct inet6_ifaddr, tmp_list); 2667 struct inet6_ifaddr, tmp_list);
2667 list_del(&ifa->tmp_list); 2668 list_del(&ifa->tmp_list);
2668 ifa->dead = 1; 2669 ifa->state = INET6_IFADDR_STATE_DEAD;
2669 write_unlock_bh(&idev->lock); 2670 write_unlock_bh(&idev->lock);
2670 spin_lock_bh(&ifa->lock); 2671 spin_lock_bh(&ifa->lock);
2671 2672
@@ -2707,7 +2708,7 @@ static int addrconf_ifdown(struct net_device *dev, int how)
2707 write_unlock_bh(&idev->lock); 2708 write_unlock_bh(&idev->lock);
2708 } else { 2709 } else {
2709 list_del(&ifa->if_list); 2710 list_del(&ifa->if_list);
2710 ifa->dead = 1; 2711 ifa->state = INET6_IFADDR_STATE_DEAD;
2711 write_unlock_bh(&idev->lock); 2712 write_unlock_bh(&idev->lock);
2712 2713
2713 /* clear hash table */ 2714 /* clear hash table */
@@ -2717,7 +2718,7 @@ static int addrconf_ifdown(struct net_device *dev, int how)
2717 } 2718 }
2718 2719
2719 __ipv6_ifa_notify(RTM_DELADDR, ifa); 2720 __ipv6_ifa_notify(RTM_DELADDR, ifa);
2720 if (ifa->dead) 2721 if (ifa->state == INET6_IFADDR_STATE_DEAD)
2721 atomic_notifier_call_chain(&inet6addr_chain, 2722 atomic_notifier_call_chain(&inet6addr_chain,
2722 NETDEV_DOWN, ifa); 2723 NETDEV_DOWN, ifa);
2723 in6_ifa_put(ifa); 2724 in6_ifa_put(ifa);
@@ -2815,7 +2816,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags)
2815 net_srandom(ifp->addr.s6_addr32[3]); 2816 net_srandom(ifp->addr.s6_addr32[3]);
2816 2817
2817 read_lock_bh(&idev->lock); 2818 read_lock_bh(&idev->lock);
2818 if (ifp->dead) 2819 if (ifp->state == INET6_IFADDR_STATE_DEAD)
2819 goto out; 2820 goto out;
2820 2821
2821 spin_lock(&ifp->lock); 2822 spin_lock(&ifp->lock);
@@ -4050,7 +4051,8 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
4050 addrconf_leave_solict(ifp->idev, &ifp->addr); 4051 addrconf_leave_solict(ifp->idev, &ifp->addr);
4051 dst_hold(&ifp->rt->u.dst); 4052 dst_hold(&ifp->rt->u.dst);
4052 4053
4053 if (ifp->dead && ip6_del_rt(ifp->rt)) 4054 if (ifp->state == INET6_IFADDR_STATE_DEAD &&
4055 ip6_del_rt(ifp->rt))
4054 dst_free(&ifp->rt->u.dst); 4056 dst_free(&ifp->rt->u.dst);
4055 break; 4057 break;
4056 } 4058 }