Commit 681daee2 authored by Jason Wang's avatar Jason Wang Committed by David S. Miller

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
67975901.

Fixes 67975901
(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: default avatarJason Wang <jasowang@redhat.com>
Acked-by: default avatarMichael S. Tsirkin <mst@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent de144391
...@@ -671,8 +671,7 @@ static bool try_fill_recv(struct receive_queue *rq, gfp_t gfp) ...@@ -671,8 +671,7 @@ static bool try_fill_recv(struct receive_queue *rq, gfp_t gfp)
if (err) if (err)
break; break;
} while (rq->vq->num_free); } while (rq->vq->num_free);
if (unlikely(!virtqueue_kick(rq->vq))) virtqueue_kick(rq->vq);
return false;
return !oom; return !oom;
} }
...@@ -877,7 +876,7 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -877,7 +876,7 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
err = xmit_skb(sq, skb); err = xmit_skb(sq, skb);
/* This should not happen! */ /* This should not happen! */
if (unlikely(err) || unlikely(!virtqueue_kick(sq->vq))) { if (unlikely(err)) {
dev->stats.tx_fifo_errors++; dev->stats.tx_fifo_errors++;
if (net_ratelimit()) if (net_ratelimit())
dev_warn(&dev->dev, dev_warn(&dev->dev,
...@@ -886,6 +885,7 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -886,6 +885,7 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
kfree_skb(skb); kfree_skb(skb);
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }
virtqueue_kick(sq->vq);
/* Don't wait up for transmitted skbs to be freed. */ /* Don't wait up for transmitted skbs to be freed. */
skb_orphan(skb); skb_orphan(skb);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment