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

[Xen-changelog] [xen-unstable] [NET] back: Loopback must copy foreign mappings.



# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Node ID 9977b878557066527ccdf37bf388d8efbba3eaa1
# Parent  593b5623a0d2ac66576baeb275a3b93cad606c9f
[NET] back: Loopback must copy foreign mappings.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 linux-2.6-xen-sparse/drivers/xen/netback/loopback.c |   50 ++++++++++++++++++++
 linux-2.6-xen-sparse/drivers/xen/netback/netback.c  |    2 
 2 files changed, 51 insertions(+), 1 deletion(-)

diff -r 593b5623a0d2 -r 9977b8785570 
linux-2.6-xen-sparse/drivers/xen/netback/loopback.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/loopback.c       Fri Sep 29 
15:40:35 2006 +0100
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/loopback.c       Fri Sep 29 
19:12:15 2006 +0100
@@ -79,9 +79,59 @@ static int loopback_close(struct net_dev
        return 0;
 }
 
+#ifdef CONFIG_X86
+static int is_foreign(unsigned long pfn)
+{
+       /* NB. Play it safe for auto-translation mode. */
+       return (xen_feature(XENFEAT_auto_translated_physmap) ||
+               (phys_to_machine_mapping[pfn] & FOREIGN_FRAME_BIT));
+}
+#else
+/* How to detect a foreign mapping? Play it safe. */
+#define is_foreign(pfn)        (1)
+#endif
+
+static int skb_remove_foreign_references(struct sk_buff *skb)
+{
+       struct page *page;
+       unsigned long pfn;
+       int i, off;
+       char *vaddr;
+
+       BUG_ON(skb_shinfo(skb)->frag_list);
+
+       for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+               pfn = page_to_pfn(skb_shinfo(skb)->frags[i].page);
+               if (!is_foreign(pfn))
+                       continue;
+               
+               page = alloc_page(GFP_ATOMIC | __GFP_NOWARN);
+               if (unlikely(!page))
+                       return 0;
+
+               vaddr = kmap_skb_frag(&skb_shinfo(skb)->frags[i]);
+               off = skb_shinfo(skb)->frags[i].page_offset;
+               memcpy(page_address(page) + off,
+                      vaddr + off,
+                      skb_shinfo(skb)->frags[i].size);
+               kunmap_skb_frag(vaddr);
+
+               put_page(skb_shinfo(skb)->frags[i].page);
+               skb_shinfo(skb)->frags[i].page = page;
+       }
+
+       return 1;
+}
+
 static int loopback_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct net_private *np = netdev_priv(dev);
+
+       if (!skb_remove_foreign_references(skb)) {
+               np->stats.tx_dropped++;
+               dev_kfree_skb(skb);
+               return 0;
+       }
 
        dst_release(skb->dst);
        skb->dst = NULL;
diff -r 593b5623a0d2 -r 9977b8785570 
linux-2.6-xen-sparse/drivers/xen/netback/netback.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c        Fri Sep 29 
15:40:35 2006 +0100
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c        Fri Sep 29 
19:12:15 2006 +0100
@@ -217,7 +217,7 @@ static struct sk_buff *netbk_copy_skb(st
                copy = len >= PAGE_SIZE ? PAGE_SIZE : len;
                zero = len >= PAGE_SIZE ? 0 : __GFP_ZERO;
 
-               page = alloc_page(GFP_ATOMIC | zero);
+               page = alloc_page(GFP_ATOMIC | __GFP_NOWARN | zero);
                if (unlikely(!page))
                        goto err_free;
 

_______________________________________________
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®.