Skip to content

Commit b2baed6

Browse files
rustyrusselldavem330
authored andcommitted
virtio_net: set/cancel work on ndo_open/ndo_stop
Michael S. Tsirkin noticed that we could run the refill work after ndo_close, which can re-enable napi - we don't disable it until virtnet_remove. This is clearly wrong, so move the workqueue control to ndo_open and ndo_stop (aka. virtnet_open and virtnet_close). One subtle point: virtnet_probe() could simply fail if it couldn't allocate a receive buffer, but that's less polite in virtnet_open() so we schedule a refill as we do in the normal receive path if we run out of memory. Signed-off-by: Rusty Russell <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 346f870 commit b2baed6

File tree

1 file changed

+13
-4
lines changed

1 file changed

+13
-4
lines changed

drivers/net/virtio_net.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,13 @@ static int add_recvbuf_mergeable(struct virtnet_info *vi, gfp_t gfp)
440440
return err;
441441
}
442442

443-
/* Returns false if we couldn't fill entirely (OOM). */
443+
/*
444+
* Returns false if we couldn't fill entirely (OOM).
445+
*
446+
* Normally run in the receive path, but can also be run from ndo_open
447+
* before we're receiving packets, or from refill_work which is
448+
* careful to disable receiving (using napi_disable).
449+
*/
444450
static bool try_fill_recv(struct virtnet_info *vi, gfp_t gfp)
445451
{
446452
int err;
@@ -721,6 +727,10 @@ static int virtnet_open(struct net_device *dev)
721727
{
722728
struct virtnet_info *vi = netdev_priv(dev);
723729

730+
/* Make sure we have some buffers: if oom use wq. */
731+
if (!try_fill_recv(vi, GFP_KERNEL))
732+
schedule_delayed_work(&vi->refill, 0);
733+
724734
virtnet_napi_enable(vi);
725735
return 0;
726736
}
@@ -774,6 +784,8 @@ static int virtnet_close(struct net_device *dev)
774784
{
775785
struct virtnet_info *vi = netdev_priv(dev);
776786

787+
/* Make sure refill_work doesn't re-enable napi! */
788+
cancel_delayed_work_sync(&vi->refill);
777789
napi_disable(&vi->napi);
778790

779791
return 0;
@@ -1100,7 +1112,6 @@ static int virtnet_probe(struct virtio_device *vdev)
11001112

11011113
unregister:
11021114
unregister_netdev(dev);
1103-
cancel_delayed_work_sync(&vi->refill);
11041115
free_vqs:
11051116
vdev->config->del_vqs(vdev);
11061117
free_stats:
@@ -1139,9 +1150,7 @@ static void __devexit virtnet_remove(struct virtio_device *vdev)
11391150
/* Stop all the virtqueues. */
11401151
vdev->config->reset(vdev);
11411152

1142-
11431153
unregister_netdev(vi->dev);
1144-
cancel_delayed_work_sync(&vi->refill);
11451154

11461155
/* Free unused buffers in both send and recv, if any. */
11471156
free_unused_bufs(vi);

0 commit comments

Comments
 (0)