Skip to content

Commit

Permalink
virtio_net: fix oom handling on tx
Browse files Browse the repository at this point in the history
virtio net will never try to overflow the TX ring, so the only reason
add_buf may fail is out of memory. Thus, we can not stop the
device until some request completes - there's no guarantee anything
at all is outstanding.

Make the error message clearer as well: error here does not
indicate queue full.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> (...and avoid TX_BUSY)
Cc: stable@kernel.org  # .34.x (s/virtqueue_/vi->svq->vq_ops->/)
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Rusty Russell authored and David S. Miller committed Jul 3, 2010
1 parent 1788f49 commit 58eba97
Showing 1 changed file with 13 additions and 8 deletions.
21 changes: 13 additions & 8 deletions drivers/net/virtio_net.c
Original file line number Diff line number Diff line change
Expand Up @@ -562,7 +562,6 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
struct virtnet_info *vi = netdev_priv(dev);
int capacity;

again:
/* Free up any pending old buffers before queueing new ones. */
free_old_xmit_skbs(vi);

Expand All @@ -571,14 +570,20 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)

/* This can happen with OOM and indirect buffers. */
if (unlikely(capacity < 0)) {
netif_stop_queue(dev);
dev_warn(&dev->dev, "Unexpected full queue\n");
if (unlikely(!virtqueue_enable_cb(vi->svq))) {
virtqueue_disable_cb(vi->svq);
netif_start_queue(dev);
goto again;
if (net_ratelimit()) {
if (likely(capacity == -ENOMEM)) {
dev_warn(&dev->dev,
"TX queue failure: out of memory\n");
} else {
dev->stats.tx_fifo_errors++;
dev_warn(&dev->dev,
"Unexpected TX queue failure: %d\n",
capacity);
}
}
return NETDEV_TX_BUSY;
dev->stats.tx_dropped++;
kfree_skb(skb);
return NETDEV_TX_OK;
}
virtqueue_kick(vi->svq);

Expand Down

0 comments on commit 58eba97

Please sign in to comment.