[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [linux-2.6.18-xen] Changes to netback to handle GNTST_eagain errors.



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1261031870 0
# Node ID 399c485098f6fba099142fed73837d4d6efa7981
# Parent  df70d482d0f43fbd6f5e55a006350e93e26ed9a5
Changes to netback to handle GNTST_eagain errors.

Signed-off-by: Grzegorz Milos <Grzegorz.Milos@xxxxxxxxxx>
---
 drivers/xen/netback/interface.c |   17 +++++++++-----
 drivers/xen/netback/netback.c   |   46 +++++++++++++++++++++++++++++++++-------
 2 files changed, 50 insertions(+), 13 deletions(-)

diff -r df70d482d0f4 -r 399c485098f6 drivers/xen/netback/interface.c
--- a/drivers/xen/netback/interface.c   Thu Dec 17 06:37:50 2009 +0000
+++ b/drivers/xen/netback/interface.c   Thu Dec 17 06:37:50 2009 +0000
@@ -33,6 +33,7 @@
 #include "common.h"
 #include <linux/ethtool.h>
 #include <linux/rtnetlink.h>
+#include <linux/delay.h>
 
 /*
  * Module parameter 'queue_length':
@@ -250,9 +251,11 @@ static int map_frontend_pages(
 
        gnttab_set_map_op(&op, (unsigned long)netif->tx_comms_area->addr,
                          GNTMAP_host_map, tx_ring_ref, netif->domid);
-    
-       if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
-               BUG();
+    do {
+               if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
+                       BUG();
+        msleep(10);
+    } while(op.status == GNTST_eagain);
 
        if (op.status) { 
                DPRINTK(" Gnttab failure mapping tx_ring_ref!\n");
@@ -264,9 +267,11 @@ static int map_frontend_pages(
 
        gnttab_set_map_op(&op, (unsigned long)netif->rx_comms_area->addr,
                          GNTMAP_host_map, rx_ring_ref, netif->domid);
-
-       if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
-               BUG();
+    do {
+           if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
+                   BUG();
+        msleep(10);
+    } while(op.status == GNTST_eagain);
 
        if (op.status) {
                struct gnttab_unmap_grant_ref unop;
diff -r df70d482d0f4 -r 399c485098f6 drivers/xen/netback/netback.c
--- a/drivers/xen/netback/netback.c     Thu Dec 17 06:37:50 2009 +0000
+++ b/drivers/xen/netback/netback.c     Thu Dec 17 06:37:50 2009 +0000
@@ -495,13 +495,15 @@ static inline void netbk_free_pages(int 
    netrx_pending_operations, which have since been done.  Check that
    they didn't give any errors and advance over them. */
 static int netbk_check_gop(int nr_frags, domid_t domid,
-                          struct netrx_pending_operations *npo)
+                          struct netrx_pending_operations *npo, int *eagain)
 {
        multicall_entry_t *mcl;
        gnttab_transfer_t *gop;
        gnttab_copy_t     *copy_op;
        int status = NETIF_RSP_OKAY;
        int i;
+
+    *eagain = 0;
 
        for (i = 0; i <= nr_frags; i++) {
                if (npo->meta[npo->meta_cons + i].copy) {
@@ -510,6 +512,8 @@ static int netbk_check_gop(int nr_frags,
                                DPRINTK("Bad status %d from copy to DOM%d.\n",
                                        copy_op->status, domid);
                                status = NETIF_RSP_ERROR;
+                if(copy_op->status == GNTST_eagain)
+                    *eagain = 1;
                        }
                } else {
                        if (!xen_feature(XENFEAT_auto_translated_physmap)) {
@@ -529,6 +533,8 @@ static int netbk_check_gop(int nr_frags,
                                 * a fatal error anyway.
                                 */
                                BUG_ON(gop->status == GNTST_bad_page);
+                if(gop->status == GNTST_eagain)
+                    *eagain = 1;
                                status = NETIF_RSP_ERROR;
                        }
                }
@@ -570,6 +576,7 @@ static void net_rx_action(unsigned long 
        int nr_frags;
        int count;
        unsigned long offset;
+    int eagain;
 
        /*
         * Putting hundreds of bytes on the stack is considered rude.
@@ -672,6 +679,9 @@ static void net_rx_action(unsigned long 
                nr_frags = *(int *)skb->cb;
 
                netif = netdev_priv(skb->dev);
+
+               status = netbk_check_gop(nr_frags, netif->domid, &npo, &eagain);
+
                /* We can't rely on skb_release_data to release the
                   pages used by fragments for us, since it tries to
                   touch the pages in the fraglist.  If we're in
@@ -681,16 +691,22 @@ static void net_rx_action(unsigned long 
                /* (Freeing the fragments is safe since we copy
                   non-linear skbs destined for flipping interfaces) */
                if (!netif->copying_receiver) {
+            /* 
+             * Cannot handle failed grant transfers at the moment (because
+             * mmu_updates likely completed)
+             */
+            BUG_ON(eagain);
                        atomic_set(&(skb_shinfo(skb)->dataref), 1);
                        skb_shinfo(skb)->frag_list = NULL;
                        skb_shinfo(skb)->nr_frags = 0;
                        netbk_free_pages(nr_frags, meta + npo.meta_cons + 1);
                }
 
-               netif->stats.tx_bytes += skb->len;
-               netif->stats.tx_packets++;
-
-               status = netbk_check_gop(nr_frags, netif->domid, &npo);
+        if(!eagain)
+        {
+                   netif->stats.tx_bytes += skb->len;
+                   netif->stats.tx_packets++;
+        }
 
                id = meta[npo.meta_cons].id;
                flags = nr_frags ? NETRXF_more_data : 0;
@@ -740,8 +756,19 @@ static void net_rx_action(unsigned long 
                    !netbk_queue_full(netif))
                        netif_wake_queue(netif->dev);
 
-               netif_put(netif);
-               dev_kfree_skb(skb);
+        if(!eagain || netbk_queue_full(netif))
+        {
+                   netif_put(netif);
+                   dev_kfree_skb(skb);
+                   netif->stats.tx_dropped += !!eagain;
+        } 
+        else
+        {
+               netif->rx_req_cons_peek += skb_shinfo(skb)->nr_frags + 1 +
+                                  !!skb_shinfo(skb)->gso_size;
+            skb_queue_head(&rx_queue, skb);
+        }
+
                npo.meta_cons += nr_frags + 1;
        }
 
@@ -1387,6 +1414,11 @@ static void net_tx_action(unsigned long 
        if (mop == tx_map_ops)
                goto out;
 
+    /* NOTE: some maps may fail with GNTST_eagain, which could be successfully
+     * retried in the backend after a delay. However, we can also fail the tx
+     * req and let the frontend resend the relevant packet again. This is fine
+     * because it is unlikely that a network buffer will be paged out or 
shared,
+     * and therefore it is unlikely to fail with GNTST_eagain. */
        ret = HYPERVISOR_grant_table_op(
                GNTTABOP_map_grant_ref, tx_map_ops, mop - tx_map_ops);
        BUG_ON(ret);

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.