From: Eric Dumazet <eric.dumazet@gmail.com>
To: David Miller <davem@davemloft.net>
Cc: netdev@vger.kernel.org, bhutchings@solarflare.com,
Nick Piggin <npiggin@suse.de>
Subject: [PATCH net-next-2.6] net: Introduce u64_stats_sync infrastructure
Date: Tue, 15 Jun 2010 12:14:16 +0200 [thread overview]
Message-ID: <1276596856.2541.84.camel@edumazet-laptop> (raw)
In-Reply-To: <20100614.231412.39191304.davem@davemloft.net>
Le lundi 14 juin 2010 à 23:14 -0700, David Miller a écrit :
> From: Eric Dumazet <eric.dumazet@gmail.com>
> Date: Mon, 14 Jun 2010 17:59:22 +0200
>
> > Uses a seqcount_t to synchronize stat producer and consumer, for packets
> > and bytes counter, now u64 types.
> >
> > (dropped counter being rarely used, stay a native "unsigned long" type)
> >
> > No noticeable performance impact on x86, as it only adds two increments
> > per frame. It might be more expensive on arches where smp_wmb() is not
> > free.
> >
> > Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
>
> Applied, but I suspect we might end up eventually needing to
> abstract this kind of technique in a common place so other
> spots can use it.
Here is the followup patch to abstract things a bit, before upcoming
conversions.
Thanks !
[PATCH net-next-2.6] net: Introduce u64_stats_sync infrastructure
To properly implement 64bits network statistics on 32bit or 64bit hosts,
we provide one new type and four methods, to ease conversions.
Stats producer should use following template granted it already got an
exclusive access to counters (a previous lock is taken, or per cpu
data [used in a non preemptable context])
Let me repeat : stats producers must be serialized by other means before
using this template. Preemption must be disabled too.
u64_stats_update_begin(&stats->syncp);
stats->bytes += len;
stats->packets++;
u64_stats_update_end(&stats->syncp);
While a consumer should use following template to get consistent
snapshot :
u64 tbytes, tpackets;
unsigned int start;
do {
start = u64_stats_fetch_begin(&stats->syncp);
tbytes = stats->bytes;
tpackets = stats->packets;
} while (u64_stats_fetch_retry(&stats->lock, syncp));
This patch uses this infrastructure in net loopback driver, instead of
specific one added in commit 6b10de38f0ef (loopback: Implement 64bit
stats on 32bit arches)
Suggested by David Miller
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
CC: Nick Piggin <npiggin@suse.de>
---
drivers/net/loopback.c | 61 ++++++++----------------------------
include/linux/netdevice.h | 50 +++++++++++++++++++++++++++++
2 files changed, 65 insertions(+), 46 deletions(-)
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index 09334f8..f20b156 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -60,51 +60,12 @@
#include <net/net_namespace.h>
struct pcpu_lstats {
- u64 packets;
- u64 bytes;
-#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
- seqcount_t seq;
-#endif
- unsigned long drops;
+ u64 packets;
+ u64 bytes;
+ struct u64_stats_sync syncp;
+ unsigned long drops;
};
-#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
-static void inline lstats_update_begin(struct pcpu_lstats *lstats)
-{
- write_seqcount_begin(&lstats->seq);
-}
-static void inline lstats_update_end(struct pcpu_lstats *lstats)
-{
- write_seqcount_end(&lstats->seq);
-}
-static void inline lstats_fetch_and_add(u64 *packets, u64 *bytes, const struct pcpu_lstats *lstats)
-{
- u64 tpackets, tbytes;
- unsigned int seq;
-
- do {
- seq = read_seqcount_begin(&lstats->seq);
- tpackets = lstats->packets;
- tbytes = lstats->bytes;
- } while (read_seqcount_retry(&lstats->seq, seq));
-
- *packets += tpackets;
- *bytes += tbytes;
-}
-#else
-static void inline lstats_update_begin(struct pcpu_lstats *lstats)
-{
-}
-static void inline lstats_update_end(struct pcpu_lstats *lstats)
-{
-}
-static void inline lstats_fetch_and_add(u64 *packets, u64 *bytes, const struct pcpu_lstats *lstats)
-{
- *packets += lstats->packets;
- *bytes += lstats->bytes;
-}
-#endif
-
/*
* The higher levels take care of making this non-reentrant (it's
* called with bh's disabled).
@@ -126,10 +87,10 @@ static netdev_tx_t loopback_xmit(struct sk_buff *skb,
len = skb->len;
if (likely(netif_rx(skb) == NET_RX_SUCCESS)) {
- lstats_update_begin(lb_stats);
+ u64_stats_update_begin(&lb_stats->syncp);
lb_stats->bytes += len;
lb_stats->packets++;
- lstats_update_end(lb_stats);
+ u64_stats_update_end(&lb_stats->syncp);
} else
lb_stats->drops++;
@@ -148,10 +109,18 @@ static struct rtnl_link_stats64 *loopback_get_stats64(struct net_device *dev)
pcpu_lstats = (void __percpu __force *)dev->ml_priv;
for_each_possible_cpu(i) {
const struct pcpu_lstats *lb_stats;
+ u64 tbytes, tpackets;
+ unsigned int start;
lb_stats = per_cpu_ptr(pcpu_lstats, i);
- lstats_fetch_and_add(&packets, &bytes, lb_stats);
+ do {
+ start = u64_stats_fetch_begin(&lb_stats->syncp);
+ tbytes = lb_stats->bytes;
+ tpackets = lb_stats->packets;
+ } while (u64_stats_fetch_retry(&lb_stats->syncp, start));
drops += lb_stats->drops;
+ bytes += tbytes;
+ packets += tpackets;
}
stats->rx_packets = packets;
stats->tx_packets = packets;
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 4fbccc5..dd1d93d 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -174,6 +174,56 @@ static inline bool dev_xmit_complete(int rc)
#define NET_DEVICE_STATS_DEFINE(name) unsigned long pad_ ## name, name
#endif
+#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
+struct u64_stats_sync {
+ seqcount_t seq;
+};
+
+static void inline u64_stats_update_begin(struct u64_stats_sync *syncp)
+{
+ write_seqcount_begin(&syncp->seq);
+}
+
+static void inline u64_stats_update_end(struct u64_stats_sync *syncp)
+{
+ write_seqcount_end(&syncp->seq);
+}
+
+static unsigned int inline u64_stats_fetch_begin(const struct u64_stats_sync *syncp)
+{
+ return read_seqcount_begin(&syncp->seq);
+}
+
+static bool inline u64_stats_fetch_retry(const struct u64_stats_sync *syncp,
+ unsigned int start)
+{
+ return read_seqcount_retry(&syncp->seq, start);
+}
+
+#else
+struct u64_stats_sync {
+};
+
+static void inline u64_stats_update_begin(struct u64_stats_sync *syncp)
+{
+}
+
+static void inline u64_stats_update_end(struct u64_stats_sync *syncp)
+{
+}
+
+static unsigned int inline u64_stats_fetch_begin(const struct u64_stats_sync *syncp)
+{
+ return 0;
+}
+
+static bool inline u64_stats_fetch_retry(const struct u64_stats_sync *syncp,
+ unsigned int start)
+{
+ return false;
+}
+#endif
+
struct net_device_stats {
NET_DEVICE_STATS_DEFINE(rx_packets);
NET_DEVICE_STATS_DEFINE(tx_packets);
next prev parent reply other threads:[~2010-06-15 10:14 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-06-14 15:59 [PATCH net-next-2.6] loopback: Implement 64bit stats on 32bit arches Eric Dumazet
2010-06-15 6:14 ` David Miller
2010-06-15 6:49 ` Nick Piggin
2010-06-15 7:23 ` Eric Dumazet
2010-06-15 10:14 ` Eric Dumazet [this message]
2010-06-15 10:25 ` [PATCH net-next-2.6] net: Introduce u64_stats_sync infrastructure Nick Piggin
2010-06-15 10:43 ` Eric Dumazet
2010-06-15 11:04 ` Nick Piggin
2010-06-15 12:12 ` Eric Dumazet
2010-06-15 13:29 ` [PATCH net-next-2.6 v2] " Eric Dumazet
2010-06-22 17:24 ` David Miller
2010-06-22 17:31 ` Eric Dumazet
2010-06-15 10:39 ` [PATCH net-next-2.6] bridge: 64bit rx/tx counters Eric Dumazet
2010-06-22 17:25 ` David Miller
2010-08-10 4:47 ` Andrew Morton
2010-08-12 12:16 ` Eric Dumazet
2010-08-12 15:07 ` Andrew Morton
2010-08-12 21:47 ` Eric Dumazet
2010-08-12 22:11 ` Andrew Morton
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1276596856.2541.84.camel@edumazet-laptop \
--to=eric.dumazet@gmail.com \
--cc=bhutchings@solarflare.com \
--cc=davem@davemloft.net \
--cc=netdev@vger.kernel.org \
--cc=npiggin@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox