[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |