direct-io.hg

changeset 11749:dcee7eca71af

[NET] back: Copy tx_ring data before verification

We need to make a copy of data from tx_ring before
verifying them as otherwise what we end up using may
be different from what was verified.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
author kfraser@localhost.localdomain
date Thu Oct 12 16:09:15 2006 +0100 (2006-10-12)
parents af1aa35265eb
children d845c9522d9e
files linux-2.6-xen-sparse/drivers/xen/netback/netback.c
line diff
     1.1 --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c	Thu Oct 12 14:28:59 2006 +0100
     1.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c	Thu Oct 12 16:09:15 2006 +0100
     1.3 @@ -883,20 +883,28 @@ static void netbk_tx_err(netif_t *netif,
     1.4  	netif_put(netif);
     1.5  }
     1.6  
     1.7 -static int netbk_count_requests(netif_t *netif, netif_tx_request_t *txp,
     1.8 -				int work_to_do)
     1.9 +static int netbk_count_requests(netif_t *netif, netif_tx_request_t *first,
    1.10 +				netif_tx_request_t *txp, int work_to_do)
    1.11  {
    1.12 -	netif_tx_request_t *first = txp;
    1.13  	RING_IDX cons = netif->tx.req_cons;
    1.14  	int frags = 0;
    1.15  
    1.16 -	while (txp->flags & NETTXF_more_data) {
    1.17 +	if (!(first->flags & NETTXF_more_data))
    1.18 +		return 0;
    1.19 +
    1.20 +	do {
    1.21  		if (frags >= work_to_do) {
    1.22  			DPRINTK("Need more frags\n");
    1.23  			return -frags;
    1.24  		}
    1.25  
    1.26 -		txp = RING_GET_REQUEST(&netif->tx, cons + frags);
    1.27 +		if (unlikely(frags >= MAX_SKB_FRAGS)) {
    1.28 +			DPRINTK("Too many frags\n");
    1.29 +			return -frags;
    1.30 +		}
    1.31 +
    1.32 +		memcpy(txp, RING_GET_REQUEST(&netif->tx, cons + frags),
    1.33 +		       sizeof(*txp));
    1.34  		if (txp->size > first->size) {
    1.35  			DPRINTK("Frags galore\n");
    1.36  			return -frags;
    1.37 @@ -910,27 +918,25 @@ static int netbk_count_requests(netif_t 
    1.38  				txp->offset, txp->size);
    1.39  			return -frags;
    1.40  		}
    1.41 -	}
    1.42 +	} while ((txp++)->flags & NETTXF_more_data);
    1.43  
    1.44  	return frags;
    1.45  }
    1.46  
    1.47  static gnttab_map_grant_ref_t *netbk_get_requests(netif_t *netif,
    1.48  						  struct sk_buff *skb,
    1.49 +						  netif_tx_request_t *txp,
    1.50  						  gnttab_map_grant_ref_t *mop)
    1.51  {
    1.52  	struct skb_shared_info *shinfo = skb_shinfo(skb);
    1.53  	skb_frag_t *frags = shinfo->frags;
    1.54 -	netif_tx_request_t *txp;
    1.55  	unsigned long pending_idx = *((u16 *)skb->data);
    1.56 -	RING_IDX cons = netif->tx.req_cons;
    1.57  	int i, start;
    1.58  
    1.59  	/* Skip first skb fragment if it is on same page as header fragment. */
    1.60  	start = ((unsigned long)shinfo->frags[0].page == pending_idx);
    1.61  
    1.62 -	for (i = start; i < shinfo->nr_frags; i++) {
    1.63 -		txp = RING_GET_REQUEST(&netif->tx, cons++);
    1.64 +	for (i = start; i < shinfo->nr_frags; i++, txp++) {
    1.65  		pending_idx = pending_ring[MASK_PEND_IDX(pending_cons++)];
    1.66  
    1.67  		gnttab_set_map_op(mop++, idx_to_kaddr(pending_idx),
    1.68 @@ -1044,7 +1050,7 @@ static void netbk_fill_frags(struct sk_b
    1.69  int netbk_get_extras(netif_t *netif, struct netif_extra_info *extras,
    1.70  		     int work_to_do)
    1.71  {
    1.72 -	struct netif_extra_info *extra;
    1.73 +	struct netif_extra_info extra;
    1.74  	RING_IDX cons = netif->tx.req_cons;
    1.75  
    1.76  	do {
    1.77 @@ -1053,18 +1059,18 @@ int netbk_get_extras(netif_t *netif, str
    1.78  			return -EBADR;
    1.79  		}
    1.80  
    1.81 -		extra = (struct netif_extra_info *)
    1.82 -			RING_GET_REQUEST(&netif->tx, cons);
    1.83 -		if (unlikely(!extra->type ||
    1.84 -			     extra->type >= XEN_NETIF_EXTRA_TYPE_MAX)) {
    1.85 +		memcpy(&extra, RING_GET_REQUEST(&netif->tx, cons),
    1.86 +		       sizeof(extra));
    1.87 +		if (unlikely(!extra.type ||
    1.88 +			     extra.type >= XEN_NETIF_EXTRA_TYPE_MAX)) {
    1.89  			netif->tx.req_cons = ++cons;
    1.90 -			DPRINTK("Invalid extra type: %d\n", extra->type);
    1.91 +			DPRINTK("Invalid extra type: %d\n", extra.type);
    1.92  			return -EINVAL;
    1.93  		}
    1.94  
    1.95 -		memcpy(&extras[extra->type - 1], extra, sizeof(*extra));
    1.96 +		memcpy(&extras[extra.type - 1], &extra, sizeof(extra));
    1.97  		netif->tx.req_cons = ++cons;
    1.98 -	} while (extra->flags & XEN_NETIF_EXTRA_FLAG_MORE);
    1.99 +	} while (extra.flags & XEN_NETIF_EXTRA_FLAG_MORE);
   1.100  
   1.101  	return work_to_do;
   1.102  }
   1.103 @@ -1099,6 +1105,7 @@ static void net_tx_action(unsigned long 
   1.104  	struct sk_buff *skb;
   1.105  	netif_t *netif;
   1.106  	netif_tx_request_t txreq;
   1.107 +	netif_tx_request_t txfrags[MAX_SKB_FRAGS];
   1.108  	struct netif_extra_info extras[XEN_NETIF_EXTRA_TYPE_MAX - 1];
   1.109  	u16 pending_idx;
   1.110  	RING_IDX i;
   1.111 @@ -1175,19 +1182,13 @@ static void net_tx_action(unsigned long 
   1.112  			}
   1.113  		}
   1.114  
   1.115 -		ret = netbk_count_requests(netif, &txreq, work_to_do);
   1.116 +		ret = netbk_count_requests(netif, &txreq, txfrags, work_to_do);
   1.117  		if (unlikely(ret < 0)) {
   1.118  			netbk_tx_err(netif, &txreq, i - ret);
   1.119  			continue;
   1.120  		}
   1.121  		i += ret;
   1.122  
   1.123 -		if (unlikely(ret > MAX_SKB_FRAGS)) {
   1.124 -			DPRINTK("Too many frags\n");
   1.125 -			netbk_tx_err(netif, &txreq, i);
   1.126 -			continue;
   1.127 -		}
   1.128 -
   1.129  		if (unlikely(txreq.size < ETH_HLEN)) {
   1.130  			DPRINTK("Bad packet size: %d\n", txreq.size);
   1.131  			netbk_tx_err(netif, &txreq, i);
   1.132 @@ -1256,7 +1257,7 @@ static void net_tx_action(unsigned long 
   1.133  
   1.134  		pending_cons++;
   1.135  
   1.136 -		mop = netbk_get_requests(netif, skb, mop);
   1.137 +		mop = netbk_get_requests(netif, skb, txfrags, mop);
   1.138  
   1.139  		netif->tx.req_cons = i;
   1.140  		netif_schedule_work(netif);