Commit 08c852c4 authored by David S. Miller's avatar David S. Miller

Merge branch 'xen-netback'

David Vrabel says:

====================
xen-netback: fix ethtool stats and memory leak

A couple of bug fixes for netback:
- make ethool stats to report the correct values.
- don't leak 1 MiB every time a VIF is destroyed.

Changes in v2:
- Split 2nd patch into leak fix and refactor patches
====================
Acked-by: default avatarIan Campbell <ian.campbell@citrix.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 04b91701 b0c21bad
...@@ -340,12 +340,11 @@ static void xenvif_get_ethtool_stats(struct net_device *dev, ...@@ -340,12 +340,11 @@ static void xenvif_get_ethtool_stats(struct net_device *dev,
unsigned int num_queues = vif->num_queues; unsigned int num_queues = vif->num_queues;
int i; int i;
unsigned int queue_index; unsigned int queue_index;
struct xenvif_stats *vif_stats;
for (i = 0; i < ARRAY_SIZE(xenvif_stats); i++) { for (i = 0; i < ARRAY_SIZE(xenvif_stats); i++) {
unsigned long accum = 0; unsigned long accum = 0;
for (queue_index = 0; queue_index < num_queues; ++queue_index) { for (queue_index = 0; queue_index < num_queues; ++queue_index) {
vif_stats = &vif->queues[queue_index].stats; void *vif_stats = &vif->queues[queue_index].stats;
accum += *(unsigned long *)(vif_stats + xenvif_stats[i].offset); accum += *(unsigned long *)(vif_stats + xenvif_stats[i].offset);
} }
data[i] = accum; data[i] = accum;
......
...@@ -1349,7 +1349,7 @@ static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *s ...@@ -1349,7 +1349,7 @@ static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *s
{ {
unsigned int offset = skb_headlen(skb); unsigned int offset = skb_headlen(skb);
skb_frag_t frags[MAX_SKB_FRAGS]; skb_frag_t frags[MAX_SKB_FRAGS];
int i; int i, f;
struct ubuf_info *uarg; struct ubuf_info *uarg;
struct sk_buff *nskb = skb_shinfo(skb)->frag_list; struct sk_buff *nskb = skb_shinfo(skb)->frag_list;
...@@ -1389,23 +1389,25 @@ static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *s ...@@ -1389,23 +1389,25 @@ static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *s
frags[i].page_offset = 0; frags[i].page_offset = 0;
skb_frag_size_set(&frags[i], len); skb_frag_size_set(&frags[i], len);
} }
/* swap out with old one */
memcpy(skb_shinfo(skb)->frags,
frags,
i * sizeof(skb_frag_t));
skb_shinfo(skb)->nr_frags = i;
skb->truesize += i * PAGE_SIZE;
/* remove traces of mapped pages and frag_list */ /* Copied all the bits from the frag list -- free it. */
skb_frag_list_init(skb); skb_frag_list_init(skb);
xenvif_skb_zerocopy_prepare(queue, nskb);
kfree_skb(nskb);
/* Release all the original (foreign) frags. */
for (f = 0; f < skb_shinfo(skb)->nr_frags; f++)
skb_frag_unref(skb, f);
uarg = skb_shinfo(skb)->destructor_arg; uarg = skb_shinfo(skb)->destructor_arg;
/* increase inflight counter to offset decrement in callback */ /* increase inflight counter to offset decrement in callback */
atomic_inc(&queue->inflight_packets); atomic_inc(&queue->inflight_packets);
uarg->callback(uarg, true); uarg->callback(uarg, true);
skb_shinfo(skb)->destructor_arg = NULL; skb_shinfo(skb)->destructor_arg = NULL;
xenvif_skb_zerocopy_prepare(queue, nskb); /* Fill the skb with the new (local) frags. */
kfree_skb(nskb); memcpy(skb_shinfo(skb)->frags, frags, i * sizeof(skb_frag_t));
skb_shinfo(skb)->nr_frags = i;
skb->truesize += i * PAGE_SIZE;
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment