提交 e9d3e084 编写于 作者: H Herbert Xu 提交者: David S. Miller

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: NHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 e29f5dbc
...@@ -32,6 +32,13 @@ ...@@ -32,6 +32,13 @@
#ifdef __KERNEL__ #ifdef __KERNEL__
enum {
INET6_IFADDR_STATE_DAD,
INET6_IFADDR_STATE_POSTDAD,
INET6_IFADDR_STATE_UP,
INET6_IFADDR_STATE_DEAD,
};
struct inet6_ifaddr { struct inet6_ifaddr {
struct in6_addr addr; struct in6_addr addr;
__u32 prefix_len; __u32 prefix_len;
...@@ -40,6 +47,9 @@ struct inet6_ifaddr { ...@@ -40,6 +47,9 @@ struct inet6_ifaddr {
__u32 prefered_lft; __u32 prefered_lft;
atomic_t refcnt; atomic_t refcnt;
spinlock_t lock; spinlock_t lock;
spinlock_t state_lock;
int state;
__u8 probes; __u8 probes;
__u8 flags; __u8 flags;
...@@ -62,8 +72,6 @@ struct inet6_ifaddr { ...@@ -62,8 +72,6 @@ struct inet6_ifaddr {
struct inet6_ifaddr *ifpub; struct inet6_ifaddr *ifpub;
int regen_count; int regen_count;
#endif #endif
int dead;
struct rcu_head rcu; struct rcu_head rcu;
}; };
......
...@@ -553,7 +553,7 @@ void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp) ...@@ -553,7 +553,7 @@ void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp)
if (del_timer(&ifp->timer)) if (del_timer(&ifp->timer))
pr_notice("Timer is still running, when freeing ifa=%p\n", ifp); pr_notice("Timer is still running, when freeing ifa=%p\n", ifp);
if (!ifp->dead) { if (ifp->state != INET6_IFADDR_STATE_DEAD) {
pr_warning("Freeing alive inet6 address %p\n", ifp); pr_warning("Freeing alive inet6 address %p\n", ifp);
return; return;
} }
...@@ -648,6 +648,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, ...@@ -648,6 +648,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
ipv6_addr_copy(&ifa->addr, addr); ipv6_addr_copy(&ifa->addr, addr);
spin_lock_init(&ifa->lock); spin_lock_init(&ifa->lock);
spin_lock_init(&ifa->state_lock);
init_timer(&ifa->timer); init_timer(&ifa->timer);
INIT_HLIST_NODE(&ifa->addr_lst); INIT_HLIST_NODE(&ifa->addr_lst);
ifa->timer.data = (unsigned long) ifa; ifa->timer.data = (unsigned long) ifa;
...@@ -720,7 +721,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) ...@@ -720,7 +721,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
hash = ipv6_addr_hash(&ifp->addr); hash = ipv6_addr_hash(&ifp->addr);
ifp->dead = 1; ifp->state = INET6_IFADDR_STATE_DEAD;
spin_lock_bh(&addrconf_hash_lock); spin_lock_bh(&addrconf_hash_lock);
hlist_del_init_rcu(&ifp->addr_lst); hlist_del_init_rcu(&ifp->addr_lst);
...@@ -2665,7 +2666,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) ...@@ -2665,7 +2666,7 @@ static int addrconf_ifdown(struct net_device *dev, int how)
ifa = list_first_entry(&idev->tempaddr_list, ifa = list_first_entry(&idev->tempaddr_list,
struct inet6_ifaddr, tmp_list); struct inet6_ifaddr, tmp_list);
list_del(&ifa->tmp_list); list_del(&ifa->tmp_list);
ifa->dead = 1; ifa->state = INET6_IFADDR_STATE_DEAD;
write_unlock_bh(&idev->lock); write_unlock_bh(&idev->lock);
spin_lock_bh(&ifa->lock); spin_lock_bh(&ifa->lock);
...@@ -2707,7 +2708,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) ...@@ -2707,7 +2708,7 @@ static int addrconf_ifdown(struct net_device *dev, int how)
write_unlock_bh(&idev->lock); write_unlock_bh(&idev->lock);
} else { } else {
list_del(&ifa->if_list); list_del(&ifa->if_list);
ifa->dead = 1; ifa->state = INET6_IFADDR_STATE_DEAD;
write_unlock_bh(&idev->lock); write_unlock_bh(&idev->lock);
/* clear hash table */ /* clear hash table */
...@@ -2717,7 +2718,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) ...@@ -2717,7 +2718,7 @@ static int addrconf_ifdown(struct net_device *dev, int how)
} }
__ipv6_ifa_notify(RTM_DELADDR, ifa); __ipv6_ifa_notify(RTM_DELADDR, ifa);
if (ifa->dead) if (ifa->state == INET6_IFADDR_STATE_DEAD)
atomic_notifier_call_chain(&inet6addr_chain, atomic_notifier_call_chain(&inet6addr_chain,
NETDEV_DOWN, ifa); NETDEV_DOWN, ifa);
in6_ifa_put(ifa); in6_ifa_put(ifa);
...@@ -2815,7 +2816,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) ...@@ -2815,7 +2816,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags)
net_srandom(ifp->addr.s6_addr32[3]); net_srandom(ifp->addr.s6_addr32[3]);
read_lock_bh(&idev->lock); read_lock_bh(&idev->lock);
if (ifp->dead) if (ifp->state == INET6_IFADDR_STATE_DEAD)
goto out; goto out;
spin_lock(&ifp->lock); spin_lock(&ifp->lock);
...@@ -4050,7 +4051,8 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) ...@@ -4050,7 +4051,8 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
addrconf_leave_solict(ifp->idev, &ifp->addr); addrconf_leave_solict(ifp->idev, &ifp->addr);
dst_hold(&ifp->rt->u.dst); dst_hold(&ifp->rt->u.dst);
if (ifp->dead && ip6_del_rt(ifp->rt)) if (ifp->state == INET6_IFADDR_STATE_DEAD &&
ip6_del_rt(ifp->rt))
dst_free(&ifp->rt->u.dst); dst_free(&ifp->rt->u.dst);
break; break;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册