ia64/xen-unstable

changeset 11218:2d70f2de1809

[NET] front: Fix tx buffer leak in teardown path. Fix rx-buffer
cleanup: cannot free skbuffs until their memory is remapped by
multicall.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@localhost.localdomain
date Sat Aug 19 11:08:40 2006 +0100 (2006-08-19)
parents b85da7cd9ea5
children 03fd2accb4d9
files linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c
line diff
     1.1 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c	Sat Aug 19 10:58:07 2006 +0100
     1.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c	Sat Aug 19 11:08:40 2006 +0100
     1.3 @@ -1397,10 +1397,31 @@ err:
     1.4  	return more_to_do;
     1.5  }
     1.6  
     1.7 +static void netif_release_tx_bufs(struct netfront_info *np)
     1.8 +{
     1.9 +	struct sk_buff *skb;
    1.10 +	int i;
    1.11 +
    1.12 +	for (i = 1; i <= NET_TX_RING_SIZE; i++) {
    1.13 +		if ((unsigned long)np->tx_skbs[i] < PAGE_OFFSET)
    1.14 +			continue;
    1.15 +
    1.16 +		skb = np->tx_skbs[i];
    1.17 +		gnttab_end_foreign_access_ref(
    1.18 +			np->grant_tx_ref[i], GNTMAP_readonly);
    1.19 +		gnttab_release_grant_reference(
    1.20 +			&np->gref_tx_head, np->grant_tx_ref[i]);
    1.21 +		np->grant_tx_ref[i] = GRANT_INVALID_REF;
    1.22 +		add_id_to_freelist(np->tx_skbs, i);
    1.23 +		dev_kfree_skb_irq(skb);
    1.24 +	}
    1.25 +}
    1.26 +
    1.27  static void netif_release_rx_bufs(struct netfront_info *np)
    1.28  {
    1.29  	struct mmu_update      *mmu = np->rx_mmu;
    1.30  	struct multicall_entry *mcl = np->rx_mcl;
    1.31 +	struct sk_buff_head free_list;
    1.32  	struct sk_buff *skb;
    1.33  	unsigned long mfn;
    1.34  	int xfer = 0, noxfer = 0, unused = 0;
    1.35 @@ -1411,6 +1432,8 @@ static void netif_release_rx_bufs(struct
    1.36  		return;
    1.37  	}
    1.38  
    1.39 +	skb_queue_head_init(&free_list);
    1.40 +
    1.41  	spin_lock(&np->rx_lock);
    1.42  
    1.43  	for (id = 0; id < NET_RX_RING_SIZE; id++) {
    1.44 @@ -1451,7 +1474,7 @@ static void netif_release_rx_bufs(struct
    1.45  
    1.46  			set_phys_to_machine(pfn, mfn);
    1.47  		}
    1.48 -		dev_kfree_skb(skb);
    1.49 +		__skb_queue_tail(&free_list, skb);
    1.50  		xfer++;
    1.51  	}
    1.52  
    1.53 @@ -1474,6 +1497,9 @@ static void netif_release_rx_bufs(struct
    1.54  		}
    1.55  	}
    1.56  
    1.57 +	while ((skb = __skb_dequeue(&free_list)) != NULL)
    1.58 +		dev_kfree_skb(skb);
    1.59 +
    1.60  	spin_unlock(&np->rx_lock);
    1.61  }
    1.62  
    1.63 @@ -1573,19 +1599,7 @@ static void network_connect(struct net_d
    1.64  	 */
    1.65  
    1.66  	/* Step 1: Discard all pending TX packet fragments. */
    1.67 -	for (requeue_idx = 0, i = 1; i <= NET_TX_RING_SIZE; i++) {
    1.68 -		if ((unsigned long)np->tx_skbs[i] < PAGE_OFFSET)
    1.69 -			continue;
    1.70 -
    1.71 -		skb = np->tx_skbs[i];
    1.72 -		gnttab_end_foreign_access_ref(
    1.73 -			np->grant_tx_ref[i], GNTMAP_readonly);
    1.74 -		gnttab_release_grant_reference(
    1.75 -			&np->gref_tx_head, np->grant_tx_ref[i]);
    1.76 -		np->grant_tx_ref[i] = GRANT_INVALID_REF;
    1.77 -		add_id_to_freelist(np->tx_skbs, i);
    1.78 -		dev_kfree_skb_irq(skb);
    1.79 -	}
    1.80 +	netif_release_tx_bufs(np);
    1.81  
    1.82  	/* Step 2: Rebuild the RX buffer freelist and the RX ring itself. */
    1.83  	for (requeue_idx = 0, i = 0; i < NET_RX_RING_SIZE; i++) {
    1.84 @@ -1632,6 +1646,7 @@ static void network_connect(struct net_d
    1.85  static void netif_uninit(struct net_device *dev)
    1.86  {
    1.87  	struct netfront_info *np = netdev_priv(dev);
    1.88 +	netif_release_tx_bufs(np);
    1.89  	netif_release_rx_bufs(np);
    1.90  	gnttab_free_grant_references(np->gref_tx_head);
    1.91  	gnttab_free_grant_references(np->gref_rx_head);