direct-io.hg

changeset 7939:340effeb64b5

Merged.
author emellor@leeni.uk.xensource.com
date Mon Nov 21 14:48:31 2005 +0100 (2005-11-21)
parents 6738fd14cb58 0add9fbe93ab
children eaaee5f43c67 c07d5bab4c2b
files
line diff
     1.1 --- a/linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c	Mon Nov 21 14:48:10 2005 +0100
     1.2 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c	Mon Nov 21 14:48:31 2005 +0100
     1.3 @@ -229,20 +229,29 @@ gnttab_grant_foreign_transfer_ref(grant_
     1.4  unsigned long
     1.5  gnttab_end_foreign_transfer_ref(grant_ref_t ref)
     1.6  {
     1.7 -	unsigned long frame = 0;
     1.8 +	unsigned long frame;
     1.9  	u16           flags;
    1.10  
    1.11 -	flags = shared[ref].flags;
    1.12 -
    1.13  	/*
    1.14 -	 * If a transfer is committed then wait for the frame address to
    1.15 -	 * appear. Otherwise invalidate the grant entry against future use.
    1.16 -	 */
    1.17 -	if (likely(flags != GTF_accept_transfer) ||
    1.18 -	    (synch_cmpxchg(&shared[ref].flags, flags, 0) !=
    1.19 -	     GTF_accept_transfer))
    1.20 -		while (unlikely((frame = shared[ref].frame) == 0))
    1.21 -			cpu_relax();
    1.22 +         * If a transfer is not even yet started, try to reclaim the grant
    1.23 +         * reference and return failure (== 0).
    1.24 +         */
    1.25 +	while (!((flags = shared[ref].flags) & GTF_transfer_committed)) {
    1.26 +		if ( synch_cmpxchg(&shared[ref].flags, flags, 0) == flags )
    1.27 +			return 0;
    1.28 +		cpu_relax();
    1.29 +	}
    1.30 +
    1.31 +	/* If a transfer is in progress then wait until it is completed. */
    1.32 +	while (!(flags & GTF_transfer_completed)) {
    1.33 +		flags = shared[ref].flags;
    1.34 +		cpu_relax();
    1.35 +	}
    1.36 +
    1.37 +	/* Read the frame number /after/ reading completion status. */
    1.38 +	rmb();
    1.39 +	frame = shared[ref].frame;
    1.40 +	BUG_ON(frame == 0);
    1.41  
    1.42  	return frame;
    1.43  }
     2.1 --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c	Mon Nov 21 14:48:10 2005 +0100
     2.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c	Mon Nov 21 14:48:31 2005 +0100
     2.3 @@ -99,7 +99,6 @@ static unsigned long alloc_mfn(void)
     2.4  	return mfn;
     2.5  }
     2.6  
     2.7 -#if 0
     2.8  static void free_mfn(unsigned long mfn)
     2.9  {
    2.10  	unsigned long flags;
    2.11 @@ -120,7 +119,6 @@ static void free_mfn(unsigned long mfn)
    2.12  	}
    2.13  	spin_unlock_irqrestore(&mfn_lock, flags);
    2.14  }
    2.15 -#endif
    2.16  
    2.17  static inline void maybe_schedule_tx_action(void)
    2.18  {
    2.19 @@ -287,28 +285,19 @@ static void net_rx_action(unsigned long 
    2.20  	ret = HYPERVISOR_multicall(rx_mcl, mcl - rx_mcl);
    2.21  	BUG_ON(ret != 0);
    2.22  
    2.23 +	ret = HYPERVISOR_grant_table_op(GNTTABOP_transfer, grant_rx_op, 
    2.24 +					gop - grant_rx_op);
    2.25 +	BUG_ON(ret != 0);
    2.26 +
    2.27  	mcl = rx_mcl;
    2.28 -	if( HYPERVISOR_grant_table_op(GNTTABOP_transfer, grant_rx_op, 
    2.29 -				      gop - grant_rx_op)) { 
    2.30 -		/*
    2.31 -		 * The other side has given us a bad grant ref, or has no 
    2.32 -		 * headroom, or has gone away. Unfortunately the current grant
    2.33 -		 * table code doesn't inform us which is the case, so not much
    2.34 -		 * we can do. 
    2.35 -		 */
    2.36 -		DPRINTK("net_rx: transfer to DOM%u failed; dropping (up to) "
    2.37 -			"%d packets.\n",
    2.38 -			grant_rx_op[0].domid, gop - grant_rx_op); 
    2.39 -	}
    2.40  	gop = grant_rx_op;
    2.41 -
    2.42  	while ((skb = __skb_dequeue(&rxq)) != NULL) {
    2.43  		netif   = netdev_priv(skb->dev);
    2.44  		size    = skb->tail - skb->data;
    2.45  
    2.46  		/* Rederive the machine addresses. */
    2.47 -		new_mfn = mcl[0].args[1] >> PAGE_SHIFT;
    2.48 -		old_mfn = 0; /* XXX Fix this so we can free_mfn() on error! */
    2.49 +		new_mfn = mcl->args[1] >> PAGE_SHIFT;
    2.50 +		old_mfn = gop->mfn;
    2.51  		atomic_set(&(skb_shinfo(skb)->dataref), 1);
    2.52  		skb_shinfo(skb)->nr_frags = 0;
    2.53  		skb_shinfo(skb)->frag_list = NULL;
    2.54 @@ -321,10 +310,10 @@ static void net_rx_action(unsigned long 
    2.55  
    2.56  		/* Check the reassignment error code. */
    2.57  		status = NETIF_RSP_OKAY;
    2.58 -		if(gop->status != 0) { 
    2.59 +		if (gop->status != 0) { 
    2.60  			DPRINTK("Bad status %d from grant transfer to DOM%u\n",
    2.61  				gop->status, netif->domid);
    2.62 -			/* XXX SMH: should free 'old_mfn' here */
    2.63 +			free_mfn(old_mfn);
    2.64  			status = NETIF_RSP_ERROR; 
    2.65  		}
    2.66  		irq = netif->irq;
     3.1 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c	Mon Nov 21 14:48:10 2005 +0100
     3.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c	Mon Nov 21 14:48:31 2005 +0100
     3.3 @@ -739,14 +739,23 @@ static int netif_poll(struct net_device 
     3.4  	     (i != rp) && (work_done < budget);
     3.5  	     i++, work_done++) {
     3.6  		rx = &np->rx->ring[MASK_NETIF_RX_IDX(i)].resp;
     3.7 +
     3.8  		/*
     3.9 -		 * An error here is very odd. Usually indicates a backend bug,
    3.10 -		 * low-mem condition, or we didn't have reservation headroom.
    3.11 -		 */
    3.12 -		if (unlikely(rx->status <= 0)) {
    3.13 +                 * This definitely indicates a bug, either in this driver or
    3.14 +                 * in the backend driver. In future this should flag the bad
    3.15 +                 * situation to the system controller to reboot the backed.
    3.16 +                 */
    3.17 +		if ((ref = np->grant_rx_ref[rx->id]) == GRANT_INVALID_REF) {
    3.18 +			WPRINTK("Bad rx response id %d.\n", rx->id);
    3.19 +			work_done--;
    3.20 +			continue;
    3.21 +		}
    3.22 +
    3.23 +		/* Memory pressure, insufficient buffer headroom, ... */
    3.24 +		if ((mfn = gnttab_end_foreign_transfer_ref(ref)) == 0) {
    3.25  			if (net_ratelimit())
    3.26 -				printk(KERN_WARNING "Bad rx buffer "
    3.27 -				       "(memory squeeze?).\n");
    3.28 +				WPRINTK("Unfulfilled rx req (id=%d, st=%d).\n",
    3.29 +					rx->id, rx->status);
    3.30  			np->rx->ring[MASK_NETIF_RX_IDX(np->rx->req_prod)].
    3.31  				req.id = rx->id;
    3.32  			wmb();
    3.33 @@ -755,23 +764,8 @@ static int netif_poll(struct net_device 
    3.34  			continue;
    3.35  		}
    3.36  
    3.37 -		ref = np->grant_rx_ref[rx->id]; 
    3.38 -
    3.39 -		if(ref == GRANT_INVALID_REF) { 
    3.40 -			printk(KERN_WARNING "Bad rx grant reference %d "
    3.41 -			       "from dom %d.\n",
    3.42 -			       ref, np->xbdev->otherend_id);
    3.43 -			np->rx->ring[MASK_NETIF_RX_IDX(np->rx->req_prod)].
    3.44 -				req.id = rx->id;
    3.45 -			wmb();
    3.46 -			np->rx->req_prod++;
    3.47 -			work_done--;
    3.48 -			continue;
    3.49 -		}
    3.50 -
    3.51 +		gnttab_release_grant_reference(&np->gref_rx_head, ref);
    3.52  		np->grant_rx_ref[rx->id] = GRANT_INVALID_REF;
    3.53 -		mfn = gnttab_end_foreign_transfer_ref(ref);
    3.54 -		gnttab_release_grant_reference(&np->gref_rx_head, ref);
    3.55  
    3.56  		skb = np->rx_skbs[rx->id];
    3.57  		ADD_ID_TO_FREELIST(np->rx_skbs, rx->id);
     4.1 --- a/xen/common/grant_table.c	Mon Nov 21 14:48:10 2005 +0100
     4.2 +++ b/xen/common/grant_table.c	Mon Nov 21 14:48:31 2005 +0100
     4.3 @@ -706,35 +706,34 @@ gnttab_transfer(
     4.4      struct pfn_info *page;
     4.5      u32 _d, _nd, x, y;
     4.6      int i;
     4.7 -    int result = GNTST_okay;
     4.8      grant_entry_t *sha;
     4.9 +    gnttab_transfer_t gop;
    4.10  
    4.11      for ( i = 0; i < count; i++ )
    4.12      {
    4.13 -        gnttab_transfer_t *gop = &uop[i];
    4.14 -
    4.15 -        page = &frame_table[gop->mfn];
    4.16 -        
    4.17 -        if ( unlikely(IS_XEN_HEAP_FRAME(page)))
    4.18 -        { 
    4.19 -            printk("gnttab_transfer: xen heap frame mfn=%lx\n", 
    4.20 -                   (unsigned long) gop->mfn);
    4.21 -            gop->status = GNTST_bad_virt_addr;
    4.22 -            continue;
    4.23 -        }
    4.24 -        
    4.25 -        if ( unlikely(!pfn_valid(page_to_pfn(page))) )
    4.26 +        /* Read from caller address space. */
    4.27 +        if ( unlikely(__copy_from_user(&gop, &uop[i], sizeof(gop))) )
    4.28          {
    4.29 -            printk("gnttab_transfer: invalid pfn for mfn=%lx\n", 
    4.30 -                   (unsigned long) gop->mfn);
    4.31 -            gop->status = GNTST_bad_virt_addr;
    4.32 -            continue;
    4.33 +            /* Caller error: bail immediately. */
    4.34 +            DPRINTK("gnttab_transfer: error reading req %d/%d\n", i, count);
    4.35 +            return -EFAULT;
    4.36          }
    4.37  
    4.38 -        if ( unlikely((e = find_domain_by_id(gop->domid)) == NULL) )
    4.39 +        /* Check the passed page frame for basic validity. */
    4.40 +        page = &frame_table[gop.mfn];
    4.41 +        if ( unlikely(!pfn_valid(gop.mfn) || IS_XEN_HEAP_FRAME(page)) )
    4.42 +        { 
    4.43 +            /* Caller error: bail immediately. */
    4.44 +            DPRINTK("gnttab_transfer: out-of-range or xen frame %lx\n",
    4.45 +                    (unsigned long)gop.mfn);
    4.46 +            return -EINVAL;
    4.47 +        }
    4.48 +
    4.49 +        /* Find the target domain. */
    4.50 +        if ( unlikely((e = find_domain_by_id(gop.domid)) == NULL) )
    4.51          {
    4.52 -            printk("gnttab_transfer: can't find domain %d\n", gop->domid);
    4.53 -            gop->status = GNTST_bad_domain;
    4.54 +            DPRINTK("gnttab_transfer: can't find domain %d\n", gop.domid);
    4.55 +            (void)__put_user(GNTST_bad_domain, &uop[i].status);
    4.56              continue;
    4.57          }
    4.58  
    4.59 @@ -752,15 +751,16 @@ gnttab_transfer(
    4.60          do {
    4.61              x = y;
    4.62              if (unlikely((x & (PGC_count_mask|PGC_allocated)) !=
    4.63 -                         (1 | PGC_allocated)) || unlikely(_nd != _d)) {
    4.64 -                printk("gnttab_transfer: Bad page values %p: ed=%p(%u), sd=%p,"
    4.65 +                         (1 | PGC_allocated)) || unlikely(_nd != _d)) { 
    4.66 +                /* Caller error: bail immediately. */
    4.67 +                DPRINTK("gnttab_transfer: Bad page %p: ed=%p(%u), sd=%p,"
    4.68                         " caf=%08x, taf=%" PRtype_info "\n", 
    4.69                         (void *) page_to_pfn(page),
    4.70                          d, d->domain_id, unpickle_domptr(_nd), x, 
    4.71                          page->u.inuse.type_info);
    4.72                  spin_unlock(&d->page_alloc_lock);
    4.73                  put_domain(e);
    4.74 -                return 0;
    4.75 +                return -EINVAL;
    4.76              }
    4.77              __asm__ __volatile__(
    4.78                  LOCK_PREFIX "cmpxchg8b %2"
    4.79 @@ -788,16 +788,16 @@ gnttab_transfer(
    4.80           */
    4.81          if ( unlikely(test_bit(_DOMF_dying, &e->domain_flags)) ||
    4.82               unlikely(e->tot_pages >= e->max_pages) ||
    4.83 -             unlikely(!gnttab_prepare_for_transfer(e, d, gop->ref)) )
    4.84 +             unlikely(!gnttab_prepare_for_transfer(e, d, gop.ref)) )
    4.85          {
    4.86              DPRINTK("gnttab_transfer: Transferee has no reservation headroom "
    4.87                      "(%d,%d) or provided a bad grant ref (%08x) or "
    4.88                      "is dying (%lx)\n",
    4.89 -                    e->tot_pages, e->max_pages, gop->ref, e->domain_flags);
    4.90 +                    e->tot_pages, e->max_pages, gop.ref, e->domain_flags);
    4.91              spin_unlock(&e->page_alloc_lock);
    4.92              put_domain(e);
    4.93 -            gop->status = result = GNTST_general_error;
    4.94 -            break;
    4.95 +            (void)__put_user(GNTST_general_error, &uop[i].status);
    4.96 +            continue;
    4.97          }
    4.98  
    4.99          /* Okay, add the page to 'e'. */
   4.100 @@ -805,23 +805,23 @@ gnttab_transfer(
   4.101              get_knownalive_domain(e);
   4.102          list_add_tail(&page->list, &e->page_list);
   4.103          page_set_owner(page, e);
   4.104 -        
   4.105 +
   4.106          spin_unlock(&e->page_alloc_lock);
   4.107  
   4.108          TRACE_1D(TRC_MEM_PAGE_GRANT_TRANSFER, e->domain_id);
   4.109 -        
   4.110 +
   4.111          /* Tell the guest about its new page frame. */
   4.112 -        sha = &e->grant_table->shared[gop->ref];
   4.113 -        sha->frame = gop->mfn;
   4.114 +        sha = &e->grant_table->shared[gop.ref];
   4.115 +        sha->frame = gop.mfn;
   4.116          wmb();
   4.117          sha->flags |= GTF_transfer_completed;
   4.118 -        
   4.119 +
   4.120          put_domain(e);
   4.121 -        
   4.122 -        gop->status = GNTST_okay;
   4.123 +
   4.124 +        (void)__put_user(GNTST_okay, &uop[i].status);
   4.125      }
   4.126  
   4.127 -    return result;
   4.128 +    return 0;
   4.129  }
   4.130  
   4.131  long