ia64/xen-unstable

changeset 11695:9977b8785570

[NET] back: Loopback must copy foreign mappings.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Fri Sep 29 19:12:15 2006 +0100 (2006-09-29)
parents 593b5623a0d2
children a949bd6ceb85
files linux-2.6-xen-sparse/drivers/xen/netback/loopback.c linux-2.6-xen-sparse/drivers/xen/netback/netback.c
line diff
     1.1 --- a/linux-2.6-xen-sparse/drivers/xen/netback/loopback.c	Fri Sep 29 15:40:35 2006 +0100
     1.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/loopback.c	Fri Sep 29 19:12:15 2006 +0100
     1.3 @@ -79,10 +79,60 @@ static int loopback_close(struct net_dev
     1.4  	return 0;
     1.5  }
     1.6  
     1.7 +#ifdef CONFIG_X86
     1.8 +static int is_foreign(unsigned long pfn)
     1.9 +{
    1.10 +	/* NB. Play it safe for auto-translation mode. */
    1.11 +	return (xen_feature(XENFEAT_auto_translated_physmap) ||
    1.12 +		(phys_to_machine_mapping[pfn] & FOREIGN_FRAME_BIT));
    1.13 +}
    1.14 +#else
    1.15 +/* How to detect a foreign mapping? Play it safe. */
    1.16 +#define is_foreign(pfn)	(1)
    1.17 +#endif
    1.18 +
    1.19 +static int skb_remove_foreign_references(struct sk_buff *skb)
    1.20 +{
    1.21 +	struct page *page;
    1.22 +	unsigned long pfn;
    1.23 +	int i, off;
    1.24 +	char *vaddr;
    1.25 +
    1.26 +	BUG_ON(skb_shinfo(skb)->frag_list);
    1.27 +
    1.28 +	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
    1.29 +		pfn = page_to_pfn(skb_shinfo(skb)->frags[i].page);
    1.30 +		if (!is_foreign(pfn))
    1.31 +			continue;
    1.32 +		
    1.33 +		page = alloc_page(GFP_ATOMIC | __GFP_NOWARN);
    1.34 +		if (unlikely(!page))
    1.35 +			return 0;
    1.36 +
    1.37 +		vaddr = kmap_skb_frag(&skb_shinfo(skb)->frags[i]);
    1.38 +		off = skb_shinfo(skb)->frags[i].page_offset;
    1.39 +		memcpy(page_address(page) + off,
    1.40 +		       vaddr + off,
    1.41 +		       skb_shinfo(skb)->frags[i].size);
    1.42 +		kunmap_skb_frag(vaddr);
    1.43 +
    1.44 +		put_page(skb_shinfo(skb)->frags[i].page);
    1.45 +		skb_shinfo(skb)->frags[i].page = page;
    1.46 +	}
    1.47 +
    1.48 +	return 1;
    1.49 +}
    1.50 +
    1.51  static int loopback_start_xmit(struct sk_buff *skb, struct net_device *dev)
    1.52  {
    1.53  	struct net_private *np = netdev_priv(dev);
    1.54  
    1.55 +	if (!skb_remove_foreign_references(skb)) {
    1.56 +		np->stats.tx_dropped++;
    1.57 +		dev_kfree_skb(skb);
    1.58 +		return 0;
    1.59 +	}
    1.60 +
    1.61  	dst_release(skb->dst);
    1.62  	skb->dst = NULL;
    1.63  
     2.1 --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c	Fri Sep 29 15:40:35 2006 +0100
     2.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c	Fri Sep 29 19:12:15 2006 +0100
     2.3 @@ -217,7 +217,7 @@ static struct sk_buff *netbk_copy_skb(st
     2.4  		copy = len >= PAGE_SIZE ? PAGE_SIZE : len;
     2.5  		zero = len >= PAGE_SIZE ? 0 : __GFP_ZERO;
     2.6  
     2.7 -		page = alloc_page(GFP_ATOMIC | zero);
     2.8 +		page = alloc_page(GFP_ATOMIC | __GFP_NOWARN | zero);
     2.9  		if (unlikely(!page))
    2.10  			goto err_free;
    2.11