diff options
author | Jason Wang <jasowang@redhat.com> | 2013-07-03 21:52:57 -0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2013-07-03 21:55:06 -0400 |
commit | 9b9cd8024a2882e896c65222aa421d461354e3f2 (patch) | |
tree | 16d4ce44ff3f326828e32c2b7c2073f12f37d9b1 /drivers/net/virtio_net.c | |
parent | 0d69a65e97fc8090ee83c8639137b4b5c8ece237 (diff) |
virtio-net: fix the race between channels setting and refill
Commit 55257d72bd1c51f25106350f4983ec19f62ed1fa (virtio-net: fill only rx queues
which are being used) tries to refill on demand when changing the number of
channels by call try_refill_recv() directly, this may race:
- the refill work who may do the refill in the same time
- the try_refill_recv() called in bh since napi was not disabled
Which may led guest complain during setting channels:
virtio_net virtio0: input.1:id 0 is not a head!
Solve this issue by scheduling a refill work which can guarantee the
serialization of refill.
Cc: Sasha Levin <sasha.levin@oracle.com>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'drivers/net/virtio_net.c')
-rw-r--r-- | drivers/net/virtio_net.c | 5 |
1 files changed, 1 insertions, 4 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 655bb25eed2b..6ddd77ece5d5 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
@@ -900,7 +900,6 @@ static int virtnet_set_queues(struct virtnet_info *vi, u16 queue_pairs) | |||
900 | struct scatterlist sg; | 900 | struct scatterlist sg; |
901 | struct virtio_net_ctrl_mq s; | 901 | struct virtio_net_ctrl_mq s; |
902 | struct net_device *dev = vi->dev; | 902 | struct net_device *dev = vi->dev; |
903 | int i; | ||
904 | 903 | ||
905 | if (!vi->has_cvq || !virtio_has_feature(vi->vdev, VIRTIO_NET_F_MQ)) | 904 | if (!vi->has_cvq || !virtio_has_feature(vi->vdev, VIRTIO_NET_F_MQ)) |
906 | return 0; | 905 | return 0; |
@@ -914,10 +913,8 @@ static int virtnet_set_queues(struct virtnet_info *vi, u16 queue_pairs) | |||
914 | queue_pairs); | 913 | queue_pairs); |
915 | return -EINVAL; | 914 | return -EINVAL; |
916 | } else { | 915 | } else { |
917 | for (i = vi->curr_queue_pairs; i < queue_pairs; i++) | ||
918 | if (!try_fill_recv(&vi->rq[i], GFP_KERNEL)) | ||
919 | schedule_delayed_work(&vi->refill, 0); | ||
920 | vi->curr_queue_pairs = queue_pairs; | 916 | vi->curr_queue_pairs = queue_pairs; |
917 | schedule_delayed_work(&vi->refill, 0); | ||
921 | } | 918 | } |
922 | 919 | ||
923 | return 0; | 920 | return 0; |