diff options
author | David S. Miller <davem@davemloft.net> | 2015-03-05 14:58:23 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-03-05 14:59:32 -0500 |
commit | 08c852c43a707333baa1329c4df6f628c345bbc3 (patch) | |
tree | ecb76c714145e1306435ab184a182721d45f0852 | |
parent | 04b91701d471fbc09689b96d2e7c94ee3a0fff74 (diff) | |
parent | b0c21badf174eb00160f842398f3918d7b365853 (diff) |
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: Ian Campbell <ian.campbell@citrix.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/xen-netback/interface.c | 3 | ||||
-rw-r--r-- | drivers/net/xen-netback/netback.c | 22 |
2 files changed, 13 insertions, 12 deletions
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index f38227afe099..3aa8648080c8 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c | |||
@@ -340,12 +340,11 @@ static void xenvif_get_ethtool_stats(struct net_device *dev, | |||
340 | unsigned int num_queues = vif->num_queues; | 340 | unsigned int num_queues = vif->num_queues; |
341 | int i; | 341 | int i; |
342 | unsigned int queue_index; | 342 | unsigned int queue_index; |
343 | struct xenvif_stats *vif_stats; | ||
344 | 343 | ||
345 | for (i = 0; i < ARRAY_SIZE(xenvif_stats); i++) { | 344 | for (i = 0; i < ARRAY_SIZE(xenvif_stats); i++) { |
346 | unsigned long accum = 0; | 345 | unsigned long accum = 0; |
347 | for (queue_index = 0; queue_index < num_queues; ++queue_index) { | 346 | for (queue_index = 0; queue_index < num_queues; ++queue_index) { |
348 | vif_stats = &vif->queues[queue_index].stats; | 347 | void *vif_stats = &vif->queues[queue_index].stats; |
349 | accum += *(unsigned long *)(vif_stats + xenvif_stats[i].offset); | 348 | accum += *(unsigned long *)(vif_stats + xenvif_stats[i].offset); |
350 | } | 349 | } |
351 | data[i] = accum; | 350 | data[i] = accum; |
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index c4d68d768408..cab9f5257f57 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c | |||
@@ -1349,7 +1349,7 @@ static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *s | |||
1349 | { | 1349 | { |
1350 | unsigned int offset = skb_headlen(skb); | 1350 | unsigned int offset = skb_headlen(skb); |
1351 | skb_frag_t frags[MAX_SKB_FRAGS]; | 1351 | skb_frag_t frags[MAX_SKB_FRAGS]; |
1352 | int i; | 1352 | int i, f; |
1353 | struct ubuf_info *uarg; | 1353 | struct ubuf_info *uarg; |
1354 | struct sk_buff *nskb = skb_shinfo(skb)->frag_list; | 1354 | struct sk_buff *nskb = skb_shinfo(skb)->frag_list; |
1355 | 1355 | ||
@@ -1389,23 +1389,25 @@ static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *s | |||
1389 | frags[i].page_offset = 0; | 1389 | frags[i].page_offset = 0; |
1390 | skb_frag_size_set(&frags[i], len); | 1390 | skb_frag_size_set(&frags[i], len); |
1391 | } | 1391 | } |
1392 | /* swap out with old one */ | ||
1393 | memcpy(skb_shinfo(skb)->frags, | ||
1394 | frags, | ||
1395 | i * sizeof(skb_frag_t)); | ||
1396 | skb_shinfo(skb)->nr_frags = i; | ||
1397 | skb->truesize += i * PAGE_SIZE; | ||
1398 | 1392 | ||
1399 | /* remove traces of mapped pages and frag_list */ | 1393 | /* Copied all the bits from the frag list -- free it. */ |
1400 | skb_frag_list_init(skb); | 1394 | skb_frag_list_init(skb); |
1395 | xenvif_skb_zerocopy_prepare(queue, nskb); | ||
1396 | kfree_skb(nskb); | ||
1397 | |||
1398 | /* Release all the original (foreign) frags. */ | ||
1399 | for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) | ||
1400 | skb_frag_unref(skb, f); | ||
1401 | uarg = skb_shinfo(skb)->destructor_arg; | 1401 | uarg = skb_shinfo(skb)->destructor_arg; |
1402 | /* increase inflight counter to offset decrement in callback */ | 1402 | /* increase inflight counter to offset decrement in callback */ |
1403 | atomic_inc(&queue->inflight_packets); | 1403 | atomic_inc(&queue->inflight_packets); |
1404 | uarg->callback(uarg, true); | 1404 | uarg->callback(uarg, true); |
1405 | skb_shinfo(skb)->destructor_arg = NULL; | 1405 | skb_shinfo(skb)->destructor_arg = NULL; |
1406 | 1406 | ||
1407 | xenvif_skb_zerocopy_prepare(queue, nskb); | 1407 | /* Fill the skb with the new (local) frags. */ |
1408 | kfree_skb(nskb); | 1408 | memcpy(skb_shinfo(skb)->frags, frags, i * sizeof(skb_frag_t)); |
1409 | skb_shinfo(skb)->nr_frags = i; | ||
1410 | skb->truesize += i * PAGE_SIZE; | ||
1409 | 1411 | ||
1410 | return 0; | 1412 | return 0; |
1411 | } | 1413 | } |