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
        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);
        }
 
        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();
        }
 }