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 | ||
