diff options
author | wangyunjian <wangyunjian@huawei.com> | 2016-05-31 11:52:43 +0800 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-05-31 14:21:09 -0700 |
commit | f00e35e259948b995aa1f3ee7fddb05f34a50157 (patch) | |
tree | e25a6eb51a1b3b1b2c5ff48810b4609c6deee507 /drivers/net/virtio_net.c | |
parent | bae5499cc55d2329ea0fbf09cb22298f4ca2f9bd (diff) | |
download | op-kernel-dev-f00e35e259948b995aa1f3ee7fddb05f34a50157.zip op-kernel-dev-f00e35e259948b995aa1f3ee7fddb05f34a50157.tar.gz |
virtio_net: fix virtnet_open and virtnet_probe competing for try_fill_recv
In function virtnet_open() and virtnet_probe(), func try_fill_recv() may
be executed at the same time. VQ in virtqueue_add() has not been protected
well and BUG_ON will be triggered when virito_net.ko being removed.
Signed-off-by: Yunjian Wang <wangyunjian@huawei.com>
Acked-by: Jason Wang <jasowang@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/virtio_net.c')
-rw-r--r-- | drivers/net/virtio_net.c | 18 |
1 files changed, 2 insertions, 16 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 49d84e5..e0638e5 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -1925,24 +1925,11 @@ static int virtnet_probe(struct virtio_device *vdev) virtio_device_ready(vdev); - /* Last of all, set up some receive buffers. */ - for (i = 0; i < vi->curr_queue_pairs; i++) { - try_fill_recv(vi, &vi->rq[i], GFP_KERNEL); - - /* If we didn't even get one input buffer, we're useless. */ - if (vi->rq[i].vq->num_free == - virtqueue_get_vring_size(vi->rq[i].vq)) { - free_unused_bufs(vi); - err = -ENOMEM; - goto free_recv_bufs; - } - } - vi->nb.notifier_call = &virtnet_cpu_callback; err = register_hotcpu_notifier(&vi->nb); if (err) { pr_debug("virtio_net: registering cpu notifier failed\n"); - goto free_recv_bufs; + goto free_unregister_netdev; } /* Assume link up if device can't report link status, @@ -1960,10 +1947,9 @@ static int virtnet_probe(struct virtio_device *vdev) return 0; -free_recv_bufs: +free_unregister_netdev: vi->vdev->config->reset(vdev); - free_receive_bufs(vi); unregister_netdev(dev); free_vqs: cancel_delayed_work_sync(&vi->refill); |