Skip to content

Commit

Permalink
Merge branch 'net-adopt-u64_stats_t-type'
Browse files Browse the repository at this point in the history
Eric Dumazet says:

====================
net: adopt u64_stats_t type

While KCSAN has not raised any reports yet, we should address the
potential load/store tearing problem happening with per cpu stats.

This series is not exhaustive, but hopefully a step in the right
direction.
====================

Link: https://lore.kernel.org/r/20220608154640.1235958-1-eric.dumazet@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Jakub Kicinski committed Jun 10, 2022
2 parents d62607c + 9ec321a commit f5f37fc
Show file tree
Hide file tree
Showing 24 changed files with 151 additions and 161 deletions.
10 changes: 5 additions & 5 deletions drivers/net/ipvlan/ipvlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@ typedef enum {
} ipvl_hdr_type;

struct ipvl_pcpu_stats {
u64 rx_pkts;
u64 rx_bytes;
u64 rx_mcast;
u64 tx_pkts;
u64 tx_bytes;
u64_stats_t rx_pkts;
u64_stats_t rx_bytes;
u64_stats_t rx_mcast;
u64_stats_t tx_pkts;
u64_stats_t tx_bytes;
struct u64_stats_sync syncp;
u32 rx_errs;
u32 tx_drps;
Expand Down
6 changes: 3 additions & 3 deletions drivers/net/ipvlan/ipvlan_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ void ipvlan_count_rx(const struct ipvl_dev *ipvlan,

pcptr = this_cpu_ptr(ipvlan->pcpu_stats);
u64_stats_update_begin(&pcptr->syncp);
pcptr->rx_pkts++;
pcptr->rx_bytes += len;
u64_stats_inc(&pcptr->rx_pkts);
u64_stats_add(&pcptr->rx_bytes, len);
if (mcast)
pcptr->rx_mcast++;
u64_stats_inc(&pcptr->rx_mcast);
u64_stats_update_end(&pcptr->syncp);
} else {
this_cpu_inc(ipvlan->pcpu_stats->rx_errs);
Expand Down
18 changes: 9 additions & 9 deletions drivers/net/ipvlan/ipvlan_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -224,8 +224,8 @@ static netdev_tx_t ipvlan_start_xmit(struct sk_buff *skb,
pcptr = this_cpu_ptr(ipvlan->pcpu_stats);

u64_stats_update_begin(&pcptr->syncp);
pcptr->tx_pkts++;
pcptr->tx_bytes += skblen;
u64_stats_inc(&pcptr->tx_pkts);
u64_stats_add(&pcptr->tx_bytes, skblen);
u64_stats_update_end(&pcptr->syncp);
} else {
this_cpu_inc(ipvlan->pcpu_stats->tx_drps);
Expand Down Expand Up @@ -300,11 +300,11 @@ static void ipvlan_get_stats64(struct net_device *dev,
pcptr = per_cpu_ptr(ipvlan->pcpu_stats, idx);
do {
strt= u64_stats_fetch_begin_irq(&pcptr->syncp);
rx_pkts = pcptr->rx_pkts;
rx_bytes = pcptr->rx_bytes;
rx_mcast = pcptr->rx_mcast;
tx_pkts = pcptr->tx_pkts;
tx_bytes = pcptr->tx_bytes;
rx_pkts = u64_stats_read(&pcptr->rx_pkts);
rx_bytes = u64_stats_read(&pcptr->rx_bytes);
rx_mcast = u64_stats_read(&pcptr->rx_mcast);
tx_pkts = u64_stats_read(&pcptr->tx_pkts);
tx_bytes = u64_stats_read(&pcptr->tx_bytes);
} while (u64_stats_fetch_retry_irq(&pcptr->syncp,
strt));

Expand All @@ -315,8 +315,8 @@ static void ipvlan_get_stats64(struct net_device *dev,
s->tx_bytes += tx_bytes;

/* u32 values are updated without syncp protection. */
rx_errs += pcptr->rx_errs;
tx_drps += pcptr->tx_drps;
rx_errs += READ_ONCE(pcptr->rx_errs);
tx_drps += READ_ONCE(pcptr->tx_drps);
}
s->rx_errors = rx_errs;
s->rx_dropped = rx_errs;
Expand Down
8 changes: 4 additions & 4 deletions drivers/net/macsec.c
Original file line number Diff line number Diff line change
Expand Up @@ -523,8 +523,8 @@ static void count_tx(struct net_device *dev, int ret, int len)
struct pcpu_sw_netstats *stats = this_cpu_ptr(dev->tstats);

u64_stats_update_begin(&stats->syncp);
stats->tx_packets++;
stats->tx_bytes += len;
u64_stats_inc(&stats->tx_packets);
u64_stats_add(&stats->tx_bytes, len);
u64_stats_update_end(&stats->syncp);
}
}
Expand Down Expand Up @@ -825,8 +825,8 @@ static void count_rx(struct net_device *dev, int len)
struct pcpu_sw_netstats *stats = this_cpu_ptr(dev->tstats);

u64_stats_update_begin(&stats->syncp);
stats->rx_packets++;
stats->rx_bytes += len;
u64_stats_inc(&stats->rx_packets);
u64_stats_add(&stats->rx_bytes, len);
u64_stats_update_end(&stats->syncp);
}

Expand Down
18 changes: 9 additions & 9 deletions drivers/net/macvlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -575,8 +575,8 @@ static netdev_tx_t macvlan_start_xmit(struct sk_buff *skb,

pcpu_stats = this_cpu_ptr(vlan->pcpu_stats);
u64_stats_update_begin(&pcpu_stats->syncp);
pcpu_stats->tx_packets++;
pcpu_stats->tx_bytes += len;
u64_stats_inc(&pcpu_stats->tx_packets);
u64_stats_add(&pcpu_stats->tx_bytes, len);
u64_stats_update_end(&pcpu_stats->syncp);
} else {
this_cpu_inc(vlan->pcpu_stats->tx_dropped);
Expand Down Expand Up @@ -949,11 +949,11 @@ static void macvlan_dev_get_stats64(struct net_device *dev,
p = per_cpu_ptr(vlan->pcpu_stats, i);
do {
start = u64_stats_fetch_begin_irq(&p->syncp);
rx_packets = p->rx_packets;
rx_bytes = p->rx_bytes;
rx_multicast = p->rx_multicast;
tx_packets = p->tx_packets;
tx_bytes = p->tx_bytes;
rx_packets = u64_stats_read(&p->rx_packets);
rx_bytes = u64_stats_read(&p->rx_bytes);
rx_multicast = u64_stats_read(&p->rx_multicast);
tx_packets = u64_stats_read(&p->tx_packets);
tx_bytes = u64_stats_read(&p->tx_bytes);
} while (u64_stats_fetch_retry_irq(&p->syncp, start));

stats->rx_packets += rx_packets;
Expand All @@ -964,8 +964,8 @@ static void macvlan_dev_get_stats64(struct net_device *dev,
/* rx_errors & tx_dropped are u32, updated
* without syncp protection.
*/
rx_errors += p->rx_errors;
tx_dropped += p->tx_dropped;
rx_errors += READ_ONCE(p->rx_errors);
tx_dropped += READ_ONCE(p->tx_dropped);
}
stats->rx_errors = rx_errors;
stats->rx_dropped = rx_errors;
Expand Down
26 changes: 13 additions & 13 deletions drivers/net/team/team.c
Original file line number Diff line number Diff line change
Expand Up @@ -749,10 +749,10 @@ static rx_handler_result_t team_handle_frame(struct sk_buff **pskb)

pcpu_stats = this_cpu_ptr(team->pcpu_stats);
u64_stats_update_begin(&pcpu_stats->syncp);
pcpu_stats->rx_packets++;
pcpu_stats->rx_bytes += skb->len;
u64_stats_inc(&pcpu_stats->rx_packets);
u64_stats_add(&pcpu_stats->rx_bytes, skb->len);
if (skb->pkt_type == PACKET_MULTICAST)
pcpu_stats->rx_multicast++;
u64_stats_inc(&pcpu_stats->rx_multicast);
u64_stats_update_end(&pcpu_stats->syncp);

skb->dev = team->dev;
Expand Down Expand Up @@ -1720,8 +1720,8 @@ static netdev_tx_t team_xmit(struct sk_buff *skb, struct net_device *dev)

pcpu_stats = this_cpu_ptr(team->pcpu_stats);
u64_stats_update_begin(&pcpu_stats->syncp);
pcpu_stats->tx_packets++;
pcpu_stats->tx_bytes += len;
u64_stats_inc(&pcpu_stats->tx_packets);
u64_stats_add(&pcpu_stats->tx_bytes, len);
u64_stats_update_end(&pcpu_stats->syncp);
} else {
this_cpu_inc(team->pcpu_stats->tx_dropped);
Expand Down Expand Up @@ -1854,11 +1854,11 @@ team_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
p = per_cpu_ptr(team->pcpu_stats, i);
do {
start = u64_stats_fetch_begin_irq(&p->syncp);
rx_packets = p->rx_packets;
rx_bytes = p->rx_bytes;
rx_multicast = p->rx_multicast;
tx_packets = p->tx_packets;
tx_bytes = p->tx_bytes;
rx_packets = u64_stats_read(&p->rx_packets);
rx_bytes = u64_stats_read(&p->rx_bytes);
rx_multicast = u64_stats_read(&p->rx_multicast);
tx_packets = u64_stats_read(&p->tx_packets);
tx_bytes = u64_stats_read(&p->tx_bytes);
} while (u64_stats_fetch_retry_irq(&p->syncp, start));

stats->rx_packets += rx_packets;
Expand All @@ -1870,9 +1870,9 @@ team_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
* rx_dropped, tx_dropped & rx_nohandler are u32,
* updated without syncp protection.
*/
rx_dropped += p->rx_dropped;
tx_dropped += p->tx_dropped;
rx_nohandler += p->rx_nohandler;
rx_dropped += READ_ONCE(p->rx_dropped);
tx_dropped += READ_ONCE(p->tx_dropped);
rx_nohandler += READ_ONCE(p->rx_nohandler);
}
stats->rx_dropped = rx_dropped;
stats->tx_dropped = tx_dropped;
Expand Down
8 changes: 4 additions & 4 deletions drivers/net/usb/usbnet.c
Original file line number Diff line number Diff line change
Expand Up @@ -337,8 +337,8 @@ void usbnet_skb_return (struct usbnet *dev, struct sk_buff *skb)
skb->protocol = eth_type_trans (skb, dev->net);

flags = u64_stats_update_begin_irqsave(&stats64->syncp);
stats64->rx_packets++;
stats64->rx_bytes += skb->len;
u64_stats_inc(&stats64->rx_packets);
u64_stats_add(&stats64->rx_bytes, skb->len);
u64_stats_update_end_irqrestore(&stats64->syncp, flags);

netif_dbg(dev, rx_status, dev->net, "< rx, len %zu, type 0x%x\n",
Expand Down Expand Up @@ -1258,8 +1258,8 @@ static void tx_complete (struct urb *urb)
unsigned long flags;

flags = u64_stats_update_begin_irqsave(&stats64->syncp);
stats64->tx_packets += entry->packets;
stats64->tx_bytes += entry->length;
u64_stats_add(&stats64->tx_packets, entry->packets);
u64_stats_add(&stats64->tx_bytes, entry->length);
u64_stats_update_end_irqrestore(&stats64->syncp, flags);
} else {
dev->net->stats.tx_errors++;
Expand Down
8 changes: 4 additions & 4 deletions drivers/net/vxlan/vxlan_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -2385,15 +2385,15 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
vxlan_snoop(dev, &loopback, eth_hdr(skb)->h_source, 0, vni);

u64_stats_update_begin(&tx_stats->syncp);
tx_stats->tx_packets++;
tx_stats->tx_bytes += len;
u64_stats_inc(&tx_stats->tx_packets);
u64_stats_add(&tx_stats->tx_bytes, len);
u64_stats_update_end(&tx_stats->syncp);
vxlan_vnifilter_count(src_vxlan, vni, NULL, VXLAN_VNI_STATS_TX, len);

if (__netif_rx(skb) == NET_RX_SUCCESS) {
u64_stats_update_begin(&rx_stats->syncp);
rx_stats->rx_packets++;
rx_stats->rx_bytes += len;
u64_stats_inc(&rx_stats->rx_packets);
u64_stats_add(&rx_stats->rx_bytes, len);
u64_stats_update_end(&rx_stats->syncp);
vxlan_vnifilter_count(dst_vxlan, vni, NULL, VXLAN_VNI_STATS_RX,
len);
Expand Down
9 changes: 1 addition & 8 deletions drivers/net/wireguard/receive.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,8 @@
/* Must be called with bh disabled. */
static void update_rx_stats(struct wg_peer *peer, size_t len)
{
struct pcpu_sw_netstats *tstats =
get_cpu_ptr(peer->device->dev->tstats);

u64_stats_update_begin(&tstats->syncp);
++tstats->rx_packets;
tstats->rx_bytes += len;
dev_sw_netstats_rx_add(peer->device->dev, len);
peer->rx_bytes += len;
u64_stats_update_end(&tstats->syncp);
put_cpu_ptr(tstats);
}

#define SKB_TYPE_LE32(skb) (((struct message_header *)(skb)->data)->type)
Expand Down
6 changes: 3 additions & 3 deletions include/linux/if_macvlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ static inline void macvlan_count_rx(const struct macvlan_dev *vlan,

pcpu_stats = get_cpu_ptr(vlan->pcpu_stats);
u64_stats_update_begin(&pcpu_stats->syncp);
pcpu_stats->rx_packets++;
pcpu_stats->rx_bytes += len;
u64_stats_inc(&pcpu_stats->rx_packets);
u64_stats_add(&pcpu_stats->rx_bytes, len);
if (multicast)
pcpu_stats->rx_multicast++;
u64_stats_inc(&pcpu_stats->rx_multicast);
u64_stats_update_end(&pcpu_stats->syncp);
put_cpu_ptr(vlan->pcpu_stats);
} else {
Expand Down
10 changes: 5 additions & 5 deletions include/linux/if_team.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@
#include <uapi/linux/if_team.h>

struct team_pcpu_stats {
u64 rx_packets;
u64 rx_bytes;
u64 rx_multicast;
u64 tx_packets;
u64 tx_bytes;
u64_stats_t rx_packets;
u64_stats_t rx_bytes;
u64_stats_t rx_multicast;
u64_stats_t tx_packets;
u64_stats_t tx_bytes;
struct u64_stats_sync syncp;
u32 rx_dropped;
u32 tx_dropped;
Expand Down
10 changes: 5 additions & 5 deletions include/linux/if_vlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,11 @@ static inline void vlan_drop_rx_stag_filter_info(struct net_device *dev)
* @tx_dropped: number of tx drops
*/
struct vlan_pcpu_stats {
u64 rx_packets;
u64 rx_bytes;
u64 rx_multicast;
u64 tx_packets;
u64 tx_bytes;
u64_stats_t rx_packets;
u64_stats_t rx_bytes;
u64_stats_t rx_multicast;
u64_stats_t tx_packets;
u64_stats_t tx_bytes;
struct u64_stats_sync syncp;
u32 rx_errors;
u32 tx_dropped;
Expand Down
16 changes: 8 additions & 8 deletions include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -2636,10 +2636,10 @@ struct packet_offload {

/* often modified stats are per-CPU, other are shared (netdev->stats) */
struct pcpu_sw_netstats {
u64 rx_packets;
u64 rx_bytes;
u64 tx_packets;
u64 tx_bytes;
u64_stats_t rx_packets;
u64_stats_t rx_bytes;
u64_stats_t tx_packets;
u64_stats_t tx_bytes;
struct u64_stats_sync syncp;
} __aligned(4 * sizeof(u64));

Expand All @@ -2656,8 +2656,8 @@ static inline void dev_sw_netstats_rx_add(struct net_device *dev, unsigned int l
struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats);

u64_stats_update_begin(&tstats->syncp);
tstats->rx_bytes += len;
tstats->rx_packets++;
u64_stats_add(&tstats->rx_bytes, len);
u64_stats_inc(&tstats->rx_packets);
u64_stats_update_end(&tstats->syncp);
}

Expand All @@ -2668,8 +2668,8 @@ static inline void dev_sw_netstats_tx_add(struct net_device *dev,
struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats);

u64_stats_update_begin(&tstats->syncp);
tstats->tx_bytes += len;
tstats->tx_packets += packets;
u64_stats_add(&tstats->tx_bytes, len);
u64_stats_add(&tstats->tx_packets, packets);
u64_stats_update_end(&tstats->syncp);
}

Expand Down
4 changes: 2 additions & 2 deletions include/net/ip_tunnels.h
Original file line number Diff line number Diff line change
Expand Up @@ -456,8 +456,8 @@ static inline void iptunnel_xmit_stats(struct net_device *dev, int pkt_len)
struct pcpu_sw_netstats *tstats = get_cpu_ptr(dev->tstats);

u64_stats_update_begin(&tstats->syncp);
tstats->tx_bytes += pkt_len;
tstats->tx_packets++;
u64_stats_add(&tstats->tx_bytes, pkt_len);
u64_stats_inc(&tstats->tx_packets);
u64_stats_update_end(&tstats->syncp);
put_cpu_ptr(tstats);
} else {
Expand Down
6 changes: 3 additions & 3 deletions net/8021q/vlan_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@ bool vlan_do_receive(struct sk_buff **skbp)
rx_stats = this_cpu_ptr(vlan_dev_priv(vlan_dev)->vlan_pcpu_stats);

u64_stats_update_begin(&rx_stats->syncp);
rx_stats->rx_packets++;
rx_stats->rx_bytes += skb->len;
u64_stats_inc(&rx_stats->rx_packets);
u64_stats_add(&rx_stats->rx_bytes, skb->len);
if (skb->pkt_type == PACKET_MULTICAST)
rx_stats->rx_multicast++;
u64_stats_inc(&rx_stats->rx_multicast);
u64_stats_update_end(&rx_stats->syncp);

return true;
Expand Down
18 changes: 9 additions & 9 deletions net/8021q/vlan_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,8 @@ static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb,

stats = this_cpu_ptr(vlan->vlan_pcpu_stats);
u64_stats_update_begin(&stats->syncp);
stats->tx_packets++;
stats->tx_bytes += len;
u64_stats_inc(&stats->tx_packets);
u64_stats_add(&stats->tx_bytes, len);
u64_stats_update_end(&stats->syncp);
} else {
this_cpu_inc(vlan->vlan_pcpu_stats->tx_dropped);
Expand Down Expand Up @@ -713,11 +713,11 @@ static void vlan_dev_get_stats64(struct net_device *dev,
p = per_cpu_ptr(vlan_dev_priv(dev)->vlan_pcpu_stats, i);
do {
start = u64_stats_fetch_begin_irq(&p->syncp);
rxpackets = p->rx_packets;
rxbytes = p->rx_bytes;
rxmulticast = p->rx_multicast;
txpackets = p->tx_packets;
txbytes = p->tx_bytes;
rxpackets = u64_stats_read(&p->rx_packets);
rxbytes = u64_stats_read(&p->rx_bytes);
rxmulticast = u64_stats_read(&p->rx_multicast);
txpackets = u64_stats_read(&p->tx_packets);
txbytes = u64_stats_read(&p->tx_bytes);
} while (u64_stats_fetch_retry_irq(&p->syncp, start));

stats->rx_packets += rxpackets;
Expand All @@ -726,8 +726,8 @@ static void vlan_dev_get_stats64(struct net_device *dev,
stats->tx_packets += txpackets;
stats->tx_bytes += txbytes;
/* rx_errors & tx_dropped are u32 */
rx_errors += p->rx_errors;
tx_dropped += p->tx_dropped;
rx_errors += READ_ONCE(p->rx_errors);
tx_dropped += READ_ONCE(p->tx_dropped);
}
stats->rx_errors = rx_errors;
stats->tx_dropped = tx_dropped;
Expand Down
Loading

0 comments on commit f5f37fc

Please sign in to comment.