aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Wang2014-03-26 00:03:00 -0500
committerDavid S. Miller2014-03-27 12:13:21 -0500
commit681daee2443291419c57cccb0671f5f94a839005 (patch)
treee6c47044894798c2b838e535bbca0d412a4ce3c6
parentde1443916791d75fdd26becb116898277bb0273f (diff)
downloadkernel-common-681daee2443291419c57cccb0671f5f94a839005.tar.gz
kernel-common-681daee2443291419c57cccb0671f5f94a839005.tar.xz
kernel-common-681daee2443291419c57cccb0671f5f94a839005.zip
virtio-net: correct error handling of virtqueue_kick()
Current error handling of virtqueue_kick() was wrong in two places: - The skb were freed immediately when virtqueue_kick() fail during xmit. This may lead double free since the skb was not detached from the virtqueue. - try_fill_recv() returns false when virtqueue_kick() fail. This will lead unnecessary rescheduling of refill work. Actually, it's safe to just ignore the kick failure in those two places. So this patch fixes this by partially revert commit 67975901183799af8e93ec60e322f9e2a1940b9b. Fixes 67975901183799af8e93ec60e322f9e2a1940b9b (virtio_net: verify if virtqueue_kick() succeeded). Cc: Heinz Graalfs <graalfs@linux.vnet.ibm.com> Cc: Rusty Russell <rusty@rustcorp.com.au> Cc: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Jason Wang <jasowang@redhat.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/virtio_net.c6
1 files changed, 3 insertions, 3 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 5632a99cbbd..841b60831df 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -671,8 +671,7 @@ static bool try_fill_recv(struct receive_queue *rq, gfp_t gfp)
671 if (err) 671 if (err)
672 break; 672 break;
673 } while (rq->vq->num_free); 673 } while (rq->vq->num_free);
674 if (unlikely(!virtqueue_kick(rq->vq))) 674 virtqueue_kick(rq->vq);
675 return false;
676 return !oom; 675 return !oom;
677} 676}
678 677
@@ -877,7 +876,7 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
877 err = xmit_skb(sq, skb); 876 err = xmit_skb(sq, skb);
878 877
879 /* This should not happen! */ 878 /* This should not happen! */
880 if (unlikely(err) || unlikely(!virtqueue_kick(sq->vq))) { 879 if (unlikely(err)) {
881 dev->stats.tx_fifo_errors++; 880 dev->stats.tx_fifo_errors++;
882 if (net_ratelimit()) 881 if (net_ratelimit())
883 dev_warn(&dev->dev, 882 dev_warn(&dev->dev,
@@ -886,6 +885,7 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
886 kfree_skb(skb); 885 kfree_skb(skb);
887 return NETDEV_TX_OK; 886 return NETDEV_TX_OK;
888 } 887 }
888 virtqueue_kick(sq->vq);
889 889
890 /* Don't wait up for transmitted skbs to be freed. */ 890 /* Don't wait up for transmitted skbs to be freed. */
891 skb_orphan(skb); 891 skb_orphan(skb);