*     @priv_destructor:       Called from unregister
  *     @npinfo:                XXX: need comments on this one
  *     @nd_net:                Network namespace this network device is inside
+ *                             protected by @lock
  *
  *     @ml_priv:       Mid-layer private
  *     @ml_priv_type:  Mid-layer private type
 
        bool dismantle;
 
+       /** @moving_ns: device is changing netns, protected by @lock */
+       bool moving_ns;
+
        enum {
                RTNL_LINK_INITIALIZED,
                RTNL_LINK_INITIALIZING,
         *      @net_shaper_hierarchy, @reg_state, @threaded
         *
         * Double protects:
-        *      @up
+        *      @up, @moving_ns, @nd_net
         *
         * Double ops protects:
         *      @real_num_rx_queues, @real_num_tx_queues
 
        dev_hold(dev);
        rcu_read_unlock();
 
-       dev = __netdev_put_lock(dev);
+       dev = __netdev_put_lock(dev, net);
        if (!dev)
                return NULL;
 
  * This helper is intended for locking net_device after it has been looked up
  * using a lockless lookup helper. Lock prevents the instance from going away.
  */
-struct net_device *__netdev_put_lock(struct net_device *dev)
+struct net_device *__netdev_put_lock(struct net_device *dev, struct net *net)
 {
        netdev_lock(dev);
-       if (dev->reg_state > NETREG_REGISTERED) {
+       if (dev->reg_state > NETREG_REGISTERED ||
+           dev->moving_ns || !net_eq(dev_net(dev), net)) {
                netdev_unlock(dev);
                dev_put(dev);
                return NULL;
        if (!dev)
                return NULL;
 
-       return __netdev_put_lock(dev);
+       return __netdev_put_lock(dev, net);
 }
 
 struct net_device *
                dev_hold(dev);
                rcu_read_unlock();
 
-               dev = __netdev_put_lock(dev);
+               dev = __netdev_put_lock(dev, net);
                if (dev)
                        return dev;
 
        netif_close(dev);
        /* And unlink it from device chain */
        unlist_netdevice(dev);
-       netdev_unlock_ops(dev);
+
+       if (!netdev_need_ops_lock(dev))
+               netdev_lock(dev);
+       dev->moving_ns = true;
+       netdev_unlock(dev);
 
        synchronize_net();
 
        move_netdevice_notifiers_dev_net(dev, net);
 
        /* Actually switch the network namespace */
+       netdev_lock(dev);
        dev_net_set(dev, net);
+       netdev_unlock(dev);
        dev->ifindex = new_ifindex;
 
        if (new_name[0]) {
        err = netdev_change_owner(dev, net_old, net);
        WARN_ON(err);
 
-       netdev_lock_ops(dev);
+       netdev_lock(dev);
+       dev->moving_ns = false;
+       if (!netdev_need_ops_lock(dev))
+               netdev_unlock(dev);
+
        /* Add the device back in the hashes */
        list_netdevice(dev);
        /* Notify protocols, that a new device appeared. */
 
 struct net_device *dev_get_by_napi_id(unsigned int napi_id);
 
 struct net_device *netdev_get_by_index_lock(struct net *net, int ifindex);
-struct net_device *__netdev_put_lock(struct net_device *dev);
+struct net_device *__netdev_put_lock(struct net_device *dev, struct net *net);
 struct net_device *
 netdev_xa_find_lock(struct net *net, struct net_device *dev,
                    unsigned long *index);