virtio_net: do not reschedule rx refill forever
Subsystems (3)
PATCH 1/2 virtio_net: do not reschedule rx refill forever
From: "Michael S. Tsirkin" <[email protected]>
We currently fill all of RX ring, then add_buf returns ENOSPC, which gets mis-detected as an out of memory condition and causes us to reschedule the work, and so on forever. Fix this by oom = err == -ENOMEM;
--- drivers/net/virtio_net.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
drivers/net/virtio_net.c +3 -4
@@ -416,7 +416,7 @@ static int add_recvbuf_mergeable(struct virtnet_info *vi, gfp_t gfp)static bool try_fill_recv (struct virtnet_info *vi,gfp_t gfp) {int err; -bool oom = false; +bool oom; do { if (vi->mergeable_rx_bufs)
@@ -426,10 +426,9 @@ static bool try_fill_recv(struct virtnet_info *vi, gfp_t gfp)else err =add_recvbuf_small (vi, gfp); -if (err <0 ) { - oom = true; + oom = err == -ENOMEM ; +if (err <0 )break ; - } ++vi->num; }while (err >0 );if (unlikely (vi->num > vi->max))
PATCH 2/2 virtio_net: fix oom handling on tx
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.
--- drivers/net/virtio_net.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-)
drivers/net/virtio_net.c +13 -8
@@ -562,7 +562,6 @@ static netdev_tx_t start_xmit(struct sk_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);
@@ -571,14 +570,20 @@ again:/* 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);
From: Rusty Russell <[email protected]>
Date: Sat, 3 Jul 2010 12:32:55 +1000
Quoted 10 lines
From: "Michael S. Tsirkin" <[email protected]>
We currently fill all of RX ring, then
add_bufreturns ENOSPC, which gets mis-detected as an out of memory condition and causes us to reschedule the work, and so on forever. Fix this by oom = err ==-ENOMEM;Signed-off-by Michael S. Tsirkin <[email protected]>Signed-off-by Rusty Russell <[email protected]>Cc [email protected] # .34.x
Applied.
Re: [PATCH 2/2] virtio_net: fix oom handling on tx
In reply to Rusty RussellFrom: Rusty Russell <[email protected]>
Date: Sat, 3 Jul 2010 12:34:01 +1000
Quoted 11 lines
virtio net will never try to overflow the TX ring, so the only reason
add_bufmay 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 <[email protected]>Signed-off-by Rusty Russell <[email protected]> (...and avoid TX_BUSY)Cc [email protected] # .34.x (s/virtqueue_/vi->svq->vq_ops->/)
Applied.