diff options
author | Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> | 2007-03-24 15:52:16 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-03-25 21:48:01 -0400 |
commit | ecbb416939da77c0d107409976499724baddce7b (patch) | |
tree | 313f786f9f4d5fec3f016c292dea1705924fa9b6 /net | |
parent | e1701c68c1d1aeb3213d7016593ea9a1d4309417 (diff) |
[NET]: Fix neighbour destructor handling.
->neigh_destructor() is killed (not used), replaced with
->neigh_cleanup(), which is called when neighbor entry goes to dead
state. At this point everything is still valid: neigh->dev,
neigh->parms etc.
The device should guarantee that dead neighbor entries (neigh->dead !=
0) do not get private part initialized, otherwise nobody will cleanup
it.
I think this is enough for ipoib which is the only user of this thing.
Initialization private part of neighbor entries happens in ipib
start_xmit routine, which is not reached when device is down. But it
would be better to add explicit test for neigh->dead in any case.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/atm/clip.c | 9 | ||||
-rw-r--r-- | net/core/neighbour.c | 14 |
2 files changed, 10 insertions, 13 deletions
diff --git a/net/atm/clip.c b/net/atm/clip.c index ebb5d0ce8b6f..8c3825816085 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c | |||
@@ -261,14 +261,6 @@ static void clip_pop(struct atm_vcc *vcc, struct sk_buff *skb) | |||
261 | spin_unlock_irqrestore(&PRIV(dev)->xoff_lock, flags); | 261 | spin_unlock_irqrestore(&PRIV(dev)->xoff_lock, flags); |
262 | } | 262 | } |
263 | 263 | ||
264 | static void clip_neigh_destroy(struct neighbour *neigh) | ||
265 | { | ||
266 | DPRINTK("clip_neigh_destroy (neigh %p)\n", neigh); | ||
267 | if (NEIGH2ENTRY(neigh)->vccs) | ||
268 | printk(KERN_CRIT "clip_neigh_destroy: vccs != NULL !!!\n"); | ||
269 | NEIGH2ENTRY(neigh)->vccs = (void *) NEIGHBOR_DEAD; | ||
270 | } | ||
271 | |||
272 | static void clip_neigh_solicit(struct neighbour *neigh, struct sk_buff *skb) | 264 | static void clip_neigh_solicit(struct neighbour *neigh, struct sk_buff *skb) |
273 | { | 265 | { |
274 | DPRINTK("clip_neigh_solicit (neigh %p, skb %p)\n", neigh, skb); | 266 | DPRINTK("clip_neigh_solicit (neigh %p, skb %p)\n", neigh, skb); |
@@ -342,7 +334,6 @@ static struct neigh_table clip_tbl = { | |||
342 | /* parameters are copied from ARP ... */ | 334 | /* parameters are copied from ARP ... */ |
343 | .parms = { | 335 | .parms = { |
344 | .tbl = &clip_tbl, | 336 | .tbl = &clip_tbl, |
345 | .neigh_destructor = clip_neigh_destroy, | ||
346 | .base_reachable_time = 30 * HZ, | 337 | .base_reachable_time = 30 * HZ, |
347 | .retrans_time = 1 * HZ, | 338 | .retrans_time = 1 * HZ, |
348 | .gc_staletime = 60 * HZ, | 339 | .gc_staletime = 60 * HZ, |
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 3183142c6044..cfc60019cf92 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
@@ -140,6 +140,8 @@ static int neigh_forced_gc(struct neigh_table *tbl) | |||
140 | n->dead = 1; | 140 | n->dead = 1; |
141 | shrunk = 1; | 141 | shrunk = 1; |
142 | write_unlock(&n->lock); | 142 | write_unlock(&n->lock); |
143 | if (n->parms->neigh_cleanup) | ||
144 | n->parms->neigh_cleanup(n); | ||
143 | neigh_release(n); | 145 | neigh_release(n); |
144 | continue; | 146 | continue; |
145 | } | 147 | } |
@@ -211,6 +213,8 @@ static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev) | |||
211 | NEIGH_PRINTK2("neigh %p is stray.\n", n); | 213 | NEIGH_PRINTK2("neigh %p is stray.\n", n); |
212 | } | 214 | } |
213 | write_unlock(&n->lock); | 215 | write_unlock(&n->lock); |
216 | if (n->parms->neigh_cleanup) | ||
217 | n->parms->neigh_cleanup(n); | ||
214 | neigh_release(n); | 218 | neigh_release(n); |
215 | } | 219 | } |
216 | } | 220 | } |
@@ -582,9 +586,6 @@ void neigh_destroy(struct neighbour *neigh) | |||
582 | kfree(hh); | 586 | kfree(hh); |
583 | } | 587 | } |
584 | 588 | ||
585 | if (neigh->parms->neigh_destructor) | ||
586 | (neigh->parms->neigh_destructor)(neigh); | ||
587 | |||
588 | skb_queue_purge(&neigh->arp_queue); | 589 | skb_queue_purge(&neigh->arp_queue); |
589 | 590 | ||
590 | dev_put(neigh->dev); | 591 | dev_put(neigh->dev); |
@@ -675,6 +676,8 @@ static void neigh_periodic_timer(unsigned long arg) | |||
675 | *np = n->next; | 676 | *np = n->next; |
676 | n->dead = 1; | 677 | n->dead = 1; |
677 | write_unlock(&n->lock); | 678 | write_unlock(&n->lock); |
679 | if (n->parms->neigh_cleanup) | ||
680 | n->parms->neigh_cleanup(n); | ||
678 | neigh_release(n); | 681 | neigh_release(n); |
679 | continue; | 682 | continue; |
680 | } | 683 | } |
@@ -2088,8 +2091,11 @@ void __neigh_for_each_release(struct neigh_table *tbl, | |||
2088 | } else | 2091 | } else |
2089 | np = &n->next; | 2092 | np = &n->next; |
2090 | write_unlock(&n->lock); | 2093 | write_unlock(&n->lock); |
2091 | if (release) | 2094 | if (release) { |
2095 | if (n->parms->neigh_cleanup) | ||
2096 | n->parms->neigh_cleanup(n); | ||
2092 | neigh_release(n); | 2097 | neigh_release(n); |
2098 | } | ||
2093 | } | 2099 | } |
2094 | } | 2100 | } |
2095 | } | 2101 | } |