# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxxx
# Node ID 2d70f2de180989078dc104479bef6b713f88d33a
# Parent b85da7cd9ea5a74d07da5098c37ee10d2ca68c8f
[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@xxxxxxxxxxxxx>
---
linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c | 43 ++++++++++++-------
1 files changed, 29 insertions(+), 14 deletions(-)
diff -r b85da7cd9ea5 -r 2d70f2de1809
linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Sat Aug 19
10:58:07 2006 +0100
+++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Sat Aug 19
11:08:40 2006 +0100
@@ -1397,10 +1397,31 @@ err:
return more_to_do;
}
+static void netif_release_tx_bufs(struct netfront_info *np)
+{
+ struct sk_buff *skb;
+ int i;
+
+ for (i = 1; i <= NET_TX_RING_SIZE; i++) {
+ if ((unsigned long)np->tx_skbs[i] < PAGE_OFFSET)
+ continue;
+
+ skb = np->tx_skbs[i];
+ gnttab_end_foreign_access_ref(
+ np->grant_tx_ref[i], GNTMAP_readonly);
+ gnttab_release_grant_reference(
+ &np->gref_tx_head, np->grant_tx_ref[i]);
+ np->grant_tx_ref[i] = GRANT_INVALID_REF;
+ add_id_to_freelist(np->tx_skbs, i);
+ dev_kfree_skb_irq(skb);
+ }
+}
+
static void netif_release_rx_bufs(struct netfront_info *np)
{
struct mmu_update *mmu = np->rx_mmu;
struct multicall_entry *mcl = np->rx_mcl;
+ struct sk_buff_head free_list;
struct sk_buff *skb;
unsigned long mfn;
int xfer = 0, noxfer = 0, unused = 0;
@@ -1410,6 +1431,8 @@ static void netif_release_rx_bufs(struct
printk("%s: fix me for copying receiver.\n", __FUNCTION__);
return;
}
+
+ skb_queue_head_init(&free_list);
spin_lock(&np->rx_lock);
@@ -1451,7 +1474,7 @@ static void netif_release_rx_bufs(struct
set_phys_to_machine(pfn, mfn);
}
- dev_kfree_skb(skb);
+ __skb_queue_tail(&free_list, skb);
xfer++;
}
@@ -1474,6 +1497,9 @@ static void netif_release_rx_bufs(struct
}
}
+ while ((skb = __skb_dequeue(&free_list)) != NULL)
+ dev_kfree_skb(skb);
+
spin_unlock(&np->rx_lock);
}
@@ -1573,19 +1599,7 @@ static void network_connect(struct net_d
*/
/* Step 1: Discard all pending TX packet fragments. */
- for (requeue_idx = 0, i = 1; i <= NET_TX_RING_SIZE; i++) {
- if ((unsigned long)np->tx_skbs[i] < PAGE_OFFSET)
- continue;
-
- skb = np->tx_skbs[i];
- gnttab_end_foreign_access_ref(
- np->grant_tx_ref[i], GNTMAP_readonly);
- gnttab_release_grant_reference(
- &np->gref_tx_head, np->grant_tx_ref[i]);
- np->grant_tx_ref[i] = GRANT_INVALID_REF;
- add_id_to_freelist(np->tx_skbs, i);
- dev_kfree_skb_irq(skb);
- }
+ netif_release_tx_bufs(np);
/* Step 2: Rebuild the RX buffer freelist and the RX ring itself. */
for (requeue_idx = 0, i = 0; i < NET_RX_RING_SIZE; i++) {
@@ -1632,6 +1646,7 @@ static void netif_uninit(struct net_devi
static void netif_uninit(struct net_device *dev)
{
struct netfront_info *np = netdev_priv(dev);
+ netif_release_tx_bufs(np);
netif_release_rx_bufs(np);
gnttab_free_grant_references(np->gref_tx_head);
gnttab_free_grant_references(np->gref_rx_head);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|