Skip to content

Commit

Permalink
hv_netvsc: synchronize netvsc_change_mtu()/netvsc_set_channels() with…
Browse files Browse the repository at this point in the history
… netvsc_remove()

When netvsc device is removed during mtu change or channels setup we get
into troubles as both paths are trying to remove the device. Synchronize
them with start_remove flag and rtnl lock.

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Vitaly Kuznetsov authored and David S. Miller committed May 16, 2016
1 parent 0a1275c commit 6da7225
Showing 1 changed file with 7 additions and 2 deletions.
9 changes: 7 additions & 2 deletions drivers/net/hyperv/netvsc_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -759,7 +759,7 @@ static int netvsc_set_channels(struct net_device *net,
int ret = 0;
bool recovering = false;

if (!nvdev || nvdev->destroy)
if (net_device_ctx->start_remove || !nvdev || nvdev->destroy)
return -ENODEV;

num_chn = nvdev->num_chn;
Expand Down Expand Up @@ -907,7 +907,7 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
u32 num_chn;
int ret = 0;

if (nvdev == NULL || nvdev->destroy)
if (ndevctx->start_remove || !nvdev || nvdev->destroy)
return -ENODEV;

if (nvdev->nvsp_version >= NVSP_PROTOCOL_VERSION_2)
Expand Down Expand Up @@ -1445,7 +1445,12 @@ static int netvsc_remove(struct hv_device *dev)
ndev_ctx = netdev_priv(net);
net_device = ndev_ctx->nvdev;

/* Avoid racing with netvsc_change_mtu()/netvsc_set_channels()
* removing the device.
*/
rtnl_lock();
ndev_ctx->start_remove = true;
rtnl_unlock();

cancel_delayed_work_sync(&ndev_ctx->dwork);
cancel_work_sync(&ndev_ctx->work);
Expand Down

0 comments on commit 6da7225

Please sign in to comment.