ia64/linux-2.6.18-xen.hg

changeset 764:618fc299e2f1

netback: handle non-netback foreign pages

An SKB can contain pages which are foreign but not tracked by netback,
such as those created by gnttab_copy_grant_page when in
NETBK_DELAYED_COPY_SKB mode. These pages do not have a mapping field
which points to a valid offset in the pending_tx_info array.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Dec 18 11:51:36 2008 +0000 (2008-12-18)
parents ff9683032b76
children d5c2e97b87ac fad85221407b
files drivers/xen/netback/netback.c
line diff
     1.1 --- a/drivers/xen/netback/netback.c	Sat Dec 13 16:00:43 2008 +0000
     1.2 +++ b/drivers/xen/netback/netback.c	Thu Dec 18 11:51:36 2008 +0000
     1.3 @@ -40,9 +40,6 @@
     1.4  
     1.5  /*define NETBE_DEBUG_INTERRUPT*/
     1.6  
     1.7 -/* extra field used in struct page */
     1.8 -#define netif_page_index(pg) (*(long *)&(pg)->mapping)
     1.9 -
    1.10  struct netbk_rx_meta {
    1.11  	skb_frag_t frag;
    1.12  	int id;
    1.13 @@ -89,6 +86,25 @@ static inline unsigned long idx_to_kaddr
    1.14  	return (unsigned long)pfn_to_kaddr(idx_to_pfn(idx));
    1.15  }
    1.16  
    1.17 +/* extra field used in struct page */
    1.18 +static inline void netif_set_page_index(struct page *pg, unsigned int index)
    1.19 +{
    1.20 +	*(unsigned long *)&pg->mapping = index;
    1.21 +}
    1.22 +
    1.23 +static inline int netif_page_index(struct page *pg)
    1.24 +{
    1.25 +	unsigned long idx = (unsigned long)pg->mapping;
    1.26 +
    1.27 +	if (!PageForeign(pg))
    1.28 +		return -1;
    1.29 +
    1.30 +	if ((idx >= MAX_PENDING_REQS) || (mmap_pages[idx] != pg))
    1.31 +		return -1;
    1.32 +
    1.33 +	return idx;
    1.34 +}
    1.35 +
    1.36  #define PKT_PROT_LEN 64
    1.37  
    1.38  static struct pending_tx_info {
    1.39 @@ -370,6 +386,7 @@ static u16 netbk_gop_frag(netif_t *netif
    1.40  	multicall_entry_t *mcl;
    1.41  	netif_rx_request_t *req;
    1.42  	unsigned long old_mfn, new_mfn;
    1.43 +	int idx = netif_page_index(page);
    1.44  
    1.45  	old_mfn = virt_to_mfn(page_address(page));
    1.46  
    1.47 @@ -380,9 +397,8 @@ static u16 netbk_gop_frag(netif_t *netif
    1.48  		meta->copy = 1;
    1.49  		copy_gop = npo->copy + npo->copy_prod++;
    1.50  		copy_gop->flags = GNTCOPY_dest_gref;
    1.51 -		if (PageForeign(page)) {
    1.52 -			struct pending_tx_info *src_pend =
    1.53 -				&pending_tx_info[netif_page_index(page)];
    1.54 +		if (idx > -1) {
    1.55 +			struct pending_tx_info *src_pend = &pending_tx_info[idx];
    1.56  			copy_gop->source.domid = src_pend->netif->domid;
    1.57  			copy_gop->source.u.ref = src_pend->req.gref;
    1.58  			copy_gop->flags |= GNTCOPY_source_gref;
    1.59 @@ -1437,8 +1453,10 @@ static void netif_idx_release(u16 pendin
    1.60  
    1.61  static void netif_page_release(struct page *page, unsigned int order)
    1.62  {
    1.63 +	int idx = netif_page_index(page);
    1.64  	BUG_ON(order);
    1.65 -	netif_idx_release(netif_page_index(page));
    1.66 +	BUG_ON(idx < 0);
    1.67 +	netif_idx_release(idx);
    1.68  }
    1.69  
    1.70  irqreturn_t netif_be_int(int irq, void *dev_id, struct pt_regs *regs)
    1.71 @@ -1572,7 +1590,7 @@ static int __init netback_init(void)
    1.72  	for (i = 0; i < MAX_PENDING_REQS; i++) {
    1.73  		page = mmap_pages[i];
    1.74  		SetPageForeign(page, netif_page_release);
    1.75 -		netif_page_index(page) = i;
    1.76 +		netif_set_page_index(page, i);
    1.77  		INIT_LIST_HEAD(&pending_inuse[i].list);
    1.78  	}
    1.79