From d34f2d77a1ad133aa0fca0c82cbea912e13351b6 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 8 Aug 2011 20:56:14 +0000 Subject: [PATCH] --- yaml --- r: 265197 b: refs/heads/master c: 9de79c127cccecb11ae6a21ab1499e87aa222880 h: refs/heads/master i: 265195: a665014422b0e5793c2b27b99fb0d574ebda8f7f v: v3 --- [refs] | 2 +- trunk/net/core/dst.c | 15 ++++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/[refs] b/[refs] index dccf07fae8e6..b2141a09a1b8 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 19fd61785a580c60cba900c5171bfadb57dd5056 +refs/heads/master: 9de79c127cccecb11ae6a21ab1499e87aa222880 diff --git a/trunk/net/core/dst.c b/trunk/net/core/dst.c index 14b33baf0733..d5e2c4c09107 100644 --- a/trunk/net/core/dst.c +++ b/trunk/net/core/dst.c @@ -171,7 +171,7 @@ void *dst_alloc(struct dst_ops *ops, struct net_device *dev, dst_init_metrics(dst, dst_default_metrics, true); dst->expires = 0UL; dst->path = dst; - dst->_neighbour = NULL; + RCU_INIT_POINTER(dst->_neighbour, NULL); #ifdef CONFIG_XFRM dst->xfrm = NULL; #endif @@ -229,11 +229,11 @@ struct dst_entry *dst_destroy(struct dst_entry * dst) smp_rmb(); again: - neigh = dst->_neighbour; + neigh = rcu_dereference_protected(dst->_neighbour, 1); child = dst->child; if (neigh) { - dst->_neighbour = NULL; + RCU_INIT_POINTER(dst->_neighbour, NULL); neigh_release(neigh); } @@ -360,14 +360,19 @@ static void dst_ifdown(struct dst_entry *dst, struct net_device *dev, if (!unregister) { dst->input = dst->output = dst_discard; } else { + struct neighbour *neigh; + dst->dev = dev_net(dst->dev)->loopback_dev; dev_hold(dst->dev); dev_put(dev); - if (dst->_neighbour && dst->_neighbour->dev == dev) { - dst->_neighbour->dev = dst->dev; + rcu_read_lock(); + neigh = dst_get_neighbour(dst); + if (neigh && neigh->dev == dev) { + neigh->dev = dst->dev; dev_hold(dst->dev); dev_put(dev); } + rcu_read_unlock(); } }