diff options
-rw-r--r-- | drivers/net/macvlan.c | 37 | ||||
-rw-r--r-- | include/linux/if_macvlan.h | 19 |
2 files changed, 35 insertions, 21 deletions
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index e096875aa055..e6d626e78515 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c | |||
@@ -431,29 +431,38 @@ static void macvlan_uninit(struct net_device *dev) | |||
431 | free_percpu(vlan->rx_stats); | 431 | free_percpu(vlan->rx_stats); |
432 | } | 432 | } |
433 | 433 | ||
434 | static struct net_device_stats *macvlan_dev_get_stats(struct net_device *dev) | 434 | static struct rtnl_link_stats64 *macvlan_dev_get_stats64(struct net_device *dev) |
435 | { | 435 | { |
436 | struct net_device_stats *stats = &dev->stats; | 436 | struct rtnl_link_stats64 *stats = &dev->stats64; |
437 | struct macvlan_dev *vlan = netdev_priv(dev); | 437 | struct macvlan_dev *vlan = netdev_priv(dev); |
438 | 438 | ||
439 | dev_txq_stats_fold(dev, stats); | 439 | dev_txq_stats_fold(dev, &dev->stats); |
440 | 440 | ||
441 | if (vlan->rx_stats) { | 441 | if (vlan->rx_stats) { |
442 | struct macvlan_rx_stats *p, rx = {0}; | 442 | struct macvlan_rx_stats *p, accum = {0}; |
443 | u64 rx_packets, rx_bytes, rx_multicast; | ||
444 | unsigned int start; | ||
443 | int i; | 445 | int i; |
444 | 446 | ||
445 | for_each_possible_cpu(i) { | 447 | for_each_possible_cpu(i) { |
446 | p = per_cpu_ptr(vlan->rx_stats, i); | 448 | p = per_cpu_ptr(vlan->rx_stats, i); |
447 | rx.rx_packets += p->rx_packets; | 449 | do { |
448 | rx.rx_bytes += p->rx_bytes; | 450 | start = u64_stats_fetch_begin_bh(&p->syncp); |
449 | rx.rx_errors += p->rx_errors; | 451 | rx_packets = p->rx_packets; |
450 | rx.multicast += p->multicast; | 452 | rx_bytes = p->rx_bytes; |
453 | rx_multicast = p->rx_multicast; | ||
454 | } while (u64_stats_fetch_retry_bh(&p->syncp, start)); | ||
455 | accum.rx_packets += rx_packets; | ||
456 | accum.rx_bytes += rx_bytes; | ||
457 | accum.rx_multicast += rx_multicast; | ||
458 | /* rx_errors is an ulong, updated without syncp protection */ | ||
459 | accum.rx_errors += p->rx_errors; | ||
451 | } | 460 | } |
452 | stats->rx_packets = rx.rx_packets; | 461 | stats->rx_packets = accum.rx_packets; |
453 | stats->rx_bytes = rx.rx_bytes; | 462 | stats->rx_bytes = accum.rx_bytes; |
454 | stats->rx_errors = rx.rx_errors; | 463 | stats->rx_errors = accum.rx_errors; |
455 | stats->rx_dropped = rx.rx_errors; | 464 | stats->rx_dropped = accum.rx_errors; |
456 | stats->multicast = rx.multicast; | 465 | stats->multicast = accum.rx_multicast; |
457 | } | 466 | } |
458 | return stats; | 467 | return stats; |
459 | } | 468 | } |
@@ -502,7 +511,7 @@ static const struct net_device_ops macvlan_netdev_ops = { | |||
502 | .ndo_change_rx_flags = macvlan_change_rx_flags, | 511 | .ndo_change_rx_flags = macvlan_change_rx_flags, |
503 | .ndo_set_mac_address = macvlan_set_mac_address, | 512 | .ndo_set_mac_address = macvlan_set_mac_address, |
504 | .ndo_set_multicast_list = macvlan_set_multicast_list, | 513 | .ndo_set_multicast_list = macvlan_set_multicast_list, |
505 | .ndo_get_stats = macvlan_dev_get_stats, | 514 | .ndo_get_stats64 = macvlan_dev_get_stats64, |
506 | .ndo_validate_addr = eth_validate_addr, | 515 | .ndo_validate_addr = eth_validate_addr, |
507 | }; | 516 | }; |
508 | 517 | ||
diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h index c26a0e4f0ce8..e24ce6ea1fa3 100644 --- a/include/linux/if_macvlan.h +++ b/include/linux/if_macvlan.h | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <linux/netdevice.h> | 6 | #include <linux/netdevice.h> |
7 | #include <linux/netlink.h> | 7 | #include <linux/netlink.h> |
8 | #include <net/netlink.h> | 8 | #include <net/netlink.h> |
9 | #include <linux/u64_stats_sync.h> | ||
9 | 10 | ||
10 | #if defined(CONFIG_MACVTAP) || defined(CONFIG_MACVTAP_MODULE) | 11 | #if defined(CONFIG_MACVTAP) || defined(CONFIG_MACVTAP_MODULE) |
11 | struct socket *macvtap_get_socket(struct file *); | 12 | struct socket *macvtap_get_socket(struct file *); |
@@ -27,14 +28,16 @@ struct macvtap_queue; | |||
27 | * struct macvlan_rx_stats - MACVLAN percpu rx stats | 28 | * struct macvlan_rx_stats - MACVLAN percpu rx stats |
28 | * @rx_packets: number of received packets | 29 | * @rx_packets: number of received packets |
29 | * @rx_bytes: number of received bytes | 30 | * @rx_bytes: number of received bytes |
30 | * @multicast: number of received multicast packets | 31 | * @rx_multicast: number of received multicast packets |
32 | * @syncp: synchronization point for 64bit counters | ||
31 | * @rx_errors: number of errors | 33 | * @rx_errors: number of errors |
32 | */ | 34 | */ |
33 | struct macvlan_rx_stats { | 35 | struct macvlan_rx_stats { |
34 | unsigned long rx_packets; | 36 | u64 rx_packets; |
35 | unsigned long rx_bytes; | 37 | u64 rx_bytes; |
36 | unsigned long multicast; | 38 | u64 rx_multicast; |
37 | unsigned long rx_errors; | 39 | struct u64_stats_sync syncp; |
40 | unsigned long rx_errors; | ||
38 | }; | 41 | }; |
39 | 42 | ||
40 | struct macvlan_dev { | 43 | struct macvlan_dev { |
@@ -56,12 +59,14 @@ static inline void macvlan_count_rx(const struct macvlan_dev *vlan, | |||
56 | { | 59 | { |
57 | struct macvlan_rx_stats *rx_stats; | 60 | struct macvlan_rx_stats *rx_stats; |
58 | 61 | ||
59 | rx_stats = per_cpu_ptr(vlan->rx_stats, smp_processor_id()); | 62 | rx_stats = this_cpu_ptr(vlan->rx_stats); |
60 | if (likely(success)) { | 63 | if (likely(success)) { |
64 | u64_stats_update_begin(&rx_stats->syncp); | ||
61 | rx_stats->rx_packets++;; | 65 | rx_stats->rx_packets++;; |
62 | rx_stats->rx_bytes += len; | 66 | rx_stats->rx_bytes += len; |
63 | if (multicast) | 67 | if (multicast) |
64 | rx_stats->multicast++; | 68 | rx_stats->rx_multicast++; |
69 | u64_stats_update_end(&rx_stats->syncp); | ||
65 | } else { | 70 | } else { |
66 | rx_stats->rx_errors++; | 71 | rx_stats->rx_errors++; |
67 | } | 72 | } |