ia64/xen-unstable

changeset 7967:52020caa244f

Change semantics of gnttab_transfer to take the page away
from the calling domain, even on error (except for special
error GNTST_bad_page). This has a knock-on advantage of
simplifying Linux's netback driver.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Mon Nov 21 18:10:35 2005 +0100 (2005-11-21)
parents e336e186e5f9
children 976e53674e84
files linux-2.6-xen-sparse/drivers/xen/netback/netback.c xen/common/grant_table.c xen/common/page_alloc.c xen/include/public/grant_table.h
line diff
     1.1 --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c	Mon Nov 21 17:30:43 2005 +0100
     1.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c	Mon Nov 21 18:10:35 2005 +0100
     1.3 @@ -99,27 +99,6 @@ static unsigned long alloc_mfn(void)
     1.4  	return mfn;
     1.5  }
     1.6  
     1.7 -static void free_mfn(unsigned long mfn)
     1.8 -{
     1.9 -	unsigned long flags;
    1.10 -	struct xen_memory_reservation reservation = {
    1.11 -		.extent_start = &mfn,
    1.12 -		.nr_extents   = 1,
    1.13 -		.extent_order = 0,
    1.14 -		.domid        = DOMID_SELF
    1.15 -	};
    1.16 -	spin_lock_irqsave(&mfn_lock, flags);
    1.17 -	if ( alloc_index != MAX_MFN_ALLOC )
    1.18 -		mfn_list[alloc_index++] = mfn;
    1.19 -	else {
    1.20 -		int ret;
    1.21 -		ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
    1.22 -					    &reservation);
    1.23 -		BUG_ON(ret != 1);
    1.24 -	}
    1.25 -	spin_unlock_irqrestore(&mfn_lock, flags);
    1.26 -}
    1.27 -
    1.28  static inline void maybe_schedule_tx_action(void)
    1.29  {
    1.30  	smp_mb();
    1.31 @@ -306,14 +285,18 @@ static void net_rx_action(unsigned long 
    1.32  		netif->stats.tx_packets++;
    1.33  
    1.34  		/* The update_va_mapping() must not fail. */
    1.35 -		BUG_ON(mcl[0].result != 0);
    1.36 +		BUG_ON(mcl->result != 0);
    1.37  
    1.38  		/* Check the reassignment error code. */
    1.39  		status = NETIF_RSP_OKAY;
    1.40  		if (gop->status != 0) { 
    1.41  			DPRINTK("Bad status %d from grant transfer to DOM%u\n",
    1.42  				gop->status, netif->domid);
    1.43 -			free_mfn(old_mfn);
    1.44 +			/*
    1.45 +                         * Page no longer belongs to us unless GNTST_bad_page,
    1.46 +                         * but that should be a fatal error anyway.
    1.47 +                         */
    1.48 +			BUG_ON(gop->status == GNTST_bad_page);
    1.49  			status = NETIF_RSP_ERROR; 
    1.50  		}
    1.51  		irq = netif->irq;
     2.1 --- a/xen/common/grant_table.c	Mon Nov 21 17:30:43 2005 +0100
     2.2 +++ b/xen/common/grant_table.c	Mon Nov 21 18:10:35 2005 +0100
     2.3 @@ -714,26 +714,18 @@ gnttab_transfer(
     2.4          /* Read from caller address space. */
     2.5          if ( unlikely(__copy_from_user(&gop, &uop[i], sizeof(gop))) )
     2.6          {
     2.7 -            /* Caller error: bail immediately. */
     2.8              DPRINTK("gnttab_transfer: error reading req %d/%d\n", i, count);
     2.9 -            return -EFAULT;
    2.10 +            (void)__put_user(GNTST_bad_page, &uop[i].status);
    2.11 +            return -EFAULT; /* This is *very* fatal. */
    2.12          }
    2.13  
    2.14          /* Check the passed page frame for basic validity. */
    2.15          page = &frame_table[gop.mfn];
    2.16          if ( unlikely(!pfn_valid(gop.mfn) || IS_XEN_HEAP_FRAME(page)) )
    2.17          { 
    2.18 -            /* Caller error: bail immediately. */
    2.19              DPRINTK("gnttab_transfer: out-of-range or xen frame %lx\n",
    2.20                      (unsigned long)gop.mfn);
    2.21 -            return -EINVAL;
    2.22 -        }
    2.23 -
    2.24 -        /* Find the target domain. */
    2.25 -        if ( unlikely((e = find_domain_by_id(gop.domid)) == NULL) )
    2.26 -        {
    2.27 -            DPRINTK("gnttab_transfer: can't find domain %d\n", gop.domid);
    2.28 -            (void)__put_user(GNTST_bad_domain, &uop[i].status);
    2.29 +            (void)__put_user(GNTST_bad_page, &uop[i].status);
    2.30              continue;
    2.31          }
    2.32  
    2.33 @@ -752,15 +744,14 @@ gnttab_transfer(
    2.34              x = y;
    2.35              if (unlikely((x & (PGC_count_mask|PGC_allocated)) !=
    2.36                           (1 | PGC_allocated)) || unlikely(_nd != _d)) { 
    2.37 -                /* Caller error: bail immediately. */
    2.38                  DPRINTK("gnttab_transfer: Bad page %p: ed=%p(%u), sd=%p,"
    2.39                         " caf=%08x, taf=%" PRtype_info "\n", 
    2.40                         (void *) page_to_pfn(page),
    2.41                          d, d->domain_id, unpickle_domptr(_nd), x, 
    2.42                          page->u.inuse.type_info);
    2.43                  spin_unlock(&d->page_alloc_lock);
    2.44 -                put_domain(e);
    2.45 -                return -EINVAL;
    2.46 +                (void)__put_user(GNTST_bad_page, &uop[i].status);
    2.47 +                continue;
    2.48              }
    2.49              __asm__ __volatile__(
    2.50                  LOCK_PREFIX "cmpxchg8b %2"
    2.51 @@ -779,6 +770,16 @@ gnttab_transfer(
    2.52  
    2.53          spin_unlock(&d->page_alloc_lock);
    2.54  
    2.55 +        /* Find the target domain. */
    2.56 +        if ( unlikely((e = find_domain_by_id(gop.domid)) == NULL) )
    2.57 +        {
    2.58 +            DPRINTK("gnttab_transfer: can't find domain %d\n", gop.domid);
    2.59 +            (void)__put_user(GNTST_bad_domain, &uop[i].status);
    2.60 +            page->count_info &= ~(PGC_count_mask|PGC_allocated);
    2.61 +            free_domheap_page(page);
    2.62 +            continue;
    2.63 +        }
    2.64 +
    2.65          spin_lock(&e->page_alloc_lock);
    2.66  
    2.67          /*
    2.68 @@ -797,6 +798,8 @@ gnttab_transfer(
    2.69              spin_unlock(&e->page_alloc_lock);
    2.70              put_domain(e);
    2.71              (void)__put_user(GNTST_general_error, &uop[i].status);
    2.72 +            page->count_info &= ~(PGC_count_mask|PGC_allocated);
    2.73 +            free_domheap_page(page);
    2.74              continue;
    2.75          }
    2.76  
     3.1 --- a/xen/common/page_alloc.c	Mon Nov 21 17:30:43 2005 +0100
     3.2 +++ b/xen/common/page_alloc.c	Mon Nov 21 18:10:35 2005 +0100
     3.3 @@ -645,7 +645,9 @@ void free_domheap_pages(struct pfn_info 
     3.4      }
     3.5      else
     3.6      {
     3.7 -        /* Freeing an anonymous domain-heap page. */
     3.8 +        /* Freeing anonymous domain-heap pages. */
     3.9 +        for ( i = 0; i < (1 << order); i++ )
    3.10 +            pg[i].u.free.cpumask = CPU_MASK_NONE;
    3.11          free_heap_pages(pfn_dom_zone_type(page_to_pfn(pg)), pg, order);
    3.12          drop_dom_ref = 0;
    3.13      }
     4.1 --- a/xen/include/public/grant_table.h	Mon Nov 21 17:30:43 2005 +0100
     4.2 +++ b/xen/include/public/grant_table.h	Mon Nov 21 18:10:35 2005 +0100
     4.3 @@ -215,9 +215,12 @@ typedef struct gnttab_dump_table {
     4.4  } gnttab_dump_table_t;
     4.5  
     4.6  /*
     4.7 - * GNTTABOP_transfer_grant_ref: Transfer <frame> to a foreign domain.  The
     4.8 - * foreign domain has previously registered the details of the transfer.
     4.9 - * These can be identified from <handle>, a grant reference.
    4.10 + * GNTTABOP_transfer_grant_ref: Transfer <frame> to a foreign domain. The
    4.11 + * foreign domain has previously registered its interest in the transfer via
    4.12 + * <domid, ref>.
    4.13 + * 
    4.14 + * Note that, even if the transfer fails, the specified page no longer belongs
    4.15 + * to the calling domain *unless* the error is GNTST_bad_page.
    4.16   */
    4.17  #define GNTTABOP_transfer                4
    4.18  typedef struct {
    4.19 @@ -269,6 +272,7 @@ typedef struct {
    4.20  #define GNTST_bad_dev_addr     (-6) /* Inappropriate device address to unmap.*/
    4.21  #define GNTST_no_device_space  (-7) /* Out of space in I/O MMU.              */
    4.22  #define GNTST_permission_denied (-8) /* Not enough privilege for operation.  */
    4.23 +#define GNTST_bad_page         (-9) /* Specified page was invalid for op.    */
    4.24  
    4.25  #define GNTTABOP_error_msgs {                   \
    4.26      "okay",                                     \