diff options
Diffstat (limited to 'net/core/dst.c')
-rw-r--r-- | net/core/dst.c | 25 |
1 files changed, 4 insertions, 21 deletions
diff --git a/net/core/dst.c b/net/core/dst.c index 43d94cedbf7c..069d51d29414 100644 --- a/net/core/dst.c +++ b/net/core/dst.c | |||
@@ -94,7 +94,7 @@ loop: | |||
94 | * But we do not have state "obsoleted, but | 94 | * But we do not have state "obsoleted, but |
95 | * referenced by parent", so it is right. | 95 | * referenced by parent", so it is right. |
96 | */ | 96 | */ |
97 | if (dst->obsolete > 1) | 97 | if (dst->obsolete > 0) |
98 | continue; | 98 | continue; |
99 | 99 | ||
100 | ___dst_free(dst); | 100 | ___dst_free(dst); |
@@ -152,7 +152,7 @@ EXPORT_SYMBOL(dst_discard); | |||
152 | const u32 dst_default_metrics[RTAX_MAX]; | 152 | const u32 dst_default_metrics[RTAX_MAX]; |
153 | 153 | ||
154 | void *dst_alloc(struct dst_ops *ops, struct net_device *dev, | 154 | void *dst_alloc(struct dst_ops *ops, struct net_device *dev, |
155 | int initial_ref, int initial_obsolete, int flags) | 155 | int initial_ref, int initial_obsolete, unsigned short flags) |
156 | { | 156 | { |
157 | struct dst_entry *dst; | 157 | struct dst_entry *dst; |
158 | 158 | ||
@@ -171,7 +171,6 @@ void *dst_alloc(struct dst_ops *ops, struct net_device *dev, | |||
171 | dst_init_metrics(dst, dst_default_metrics, true); | 171 | dst_init_metrics(dst, dst_default_metrics, true); |
172 | dst->expires = 0UL; | 172 | dst->expires = 0UL; |
173 | dst->path = dst; | 173 | dst->path = dst; |
174 | RCU_INIT_POINTER(dst->_neighbour, NULL); | ||
175 | #ifdef CONFIG_XFRM | 174 | #ifdef CONFIG_XFRM |
176 | dst->xfrm = NULL; | 175 | dst->xfrm = NULL; |
177 | #endif | 176 | #endif |
@@ -188,6 +187,7 @@ void *dst_alloc(struct dst_ops *ops, struct net_device *dev, | |||
188 | dst->__use = 0; | 187 | dst->__use = 0; |
189 | dst->lastuse = jiffies; | 188 | dst->lastuse = jiffies; |
190 | dst->flags = flags; | 189 | dst->flags = flags; |
190 | dst->pending_confirm = 0; | ||
191 | dst->next = NULL; | 191 | dst->next = NULL; |
192 | if (!(flags & DST_NOCOUNT)) | 192 | if (!(flags & DST_NOCOUNT)) |
193 | dst_entries_add(ops, 1); | 193 | dst_entries_add(ops, 1); |
@@ -202,7 +202,7 @@ static void ___dst_free(struct dst_entry *dst) | |||
202 | */ | 202 | */ |
203 | if (dst->dev == NULL || !(dst->dev->flags&IFF_UP)) | 203 | if (dst->dev == NULL || !(dst->dev->flags&IFF_UP)) |
204 | dst->input = dst->output = dst_discard; | 204 | dst->input = dst->output = dst_discard; |
205 | dst->obsolete = 2; | 205 | dst->obsolete = DST_OBSOLETE_DEAD; |
206 | } | 206 | } |
207 | 207 | ||
208 | void __dst_free(struct dst_entry *dst) | 208 | void __dst_free(struct dst_entry *dst) |
@@ -224,19 +224,12 @@ EXPORT_SYMBOL(__dst_free); | |||
224 | struct dst_entry *dst_destroy(struct dst_entry * dst) | 224 | struct dst_entry *dst_destroy(struct dst_entry * dst) |
225 | { | 225 | { |
226 | struct dst_entry *child; | 226 | struct dst_entry *child; |
227 | struct neighbour *neigh; | ||
228 | 227 | ||
229 | smp_rmb(); | 228 | smp_rmb(); |
230 | 229 | ||
231 | again: | 230 | again: |
232 | neigh = rcu_dereference_protected(dst->_neighbour, 1); | ||
233 | child = dst->child; | 231 | child = dst->child; |
234 | 232 | ||
235 | if (neigh) { | ||
236 | RCU_INIT_POINTER(dst->_neighbour, NULL); | ||
237 | neigh_release(neigh); | ||
238 | } | ||
239 | |||
240 | if (!(dst->flags & DST_NOCOUNT)) | 233 | if (!(dst->flags & DST_NOCOUNT)) |
241 | dst_entries_add(dst->ops, -1); | 234 | dst_entries_add(dst->ops, -1); |
242 | 235 | ||
@@ -360,19 +353,9 @@ static void dst_ifdown(struct dst_entry *dst, struct net_device *dev, | |||
360 | if (!unregister) { | 353 | if (!unregister) { |
361 | dst->input = dst->output = dst_discard; | 354 | dst->input = dst->output = dst_discard; |
362 | } else { | 355 | } else { |
363 | struct neighbour *neigh; | ||
364 | |||
365 | dst->dev = dev_net(dst->dev)->loopback_dev; | 356 | dst->dev = dev_net(dst->dev)->loopback_dev; |
366 | dev_hold(dst->dev); | 357 | dev_hold(dst->dev); |
367 | dev_put(dev); | 358 | dev_put(dev); |
368 | rcu_read_lock(); | ||
369 | neigh = dst_get_neighbour_noref(dst); | ||
370 | if (neigh && neigh->dev == dev) { | ||
371 | neigh->dev = dst->dev; | ||
372 | dev_hold(dst->dev); | ||
373 | dev_put(dev); | ||
374 | } | ||
375 | rcu_read_unlock(); | ||
376 | } | 359 | } |
377 | } | 360 | } |
378 | 361 | ||