summaryrefslogtreecommitdiffstats
path: root/debian/patches-rt/net-stats-Read-the-statistics-in-___gnet_stats_copy_.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches-rt/net-stats-Read-the-statistics-in-___gnet_stats_copy_.patch')
-rw-r--r--debian/patches-rt/net-stats-Read-the-statistics-in-___gnet_stats_copy_.patch90
1 files changed, 90 insertions, 0 deletions
diff --git a/debian/patches-rt/net-stats-Read-the-statistics-in-___gnet_stats_copy_.patch b/debian/patches-rt/net-stats-Read-the-statistics-in-___gnet_stats_copy_.patch
new file mode 100644
index 000000000..b43ea9f32
--- /dev/null
+++ b/debian/patches-rt/net-stats-Read-the-statistics-in-___gnet_stats_copy_.patch
@@ -0,0 +1,90 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Thu, 21 Oct 2021 11:59:19 +0200
+Subject: [PATCH] net: stats: Read the statistics in ___gnet_stats_copy_basic()
+ instead of adding.
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/5.15/older/patches-5.15.3-rt21.tar.xz
+
+Since the rework, the statistics code always adds up the byte and packet
+value(s). On 32bit architectures a seqcount_t is used in
+gnet_stats_basic_sync to ensure that the 64bit values are not modified
+during the read since two 32bit loads are required. The usage of a
+seqcount_t requires a lock to ensure that only one writer is active at a
+time. This lock leads to disabled preemption during the update.
+
+The lack of disabling preemption is now creating a warning as reported
+by Naresh since the query done by gnet_stats_copy_basic() is in
+preemptible context.
+
+For ___gnet_stats_copy_basic() there is no need to disable preemption
+since the update is performed on stack and can't be modified by another
+writer. Instead of disabling preemption, to avoid the warning,
+simply create a read function to just read the values and return as u64.
+
+Reported-by: Naresh Kamboju <naresh.kamboju@linaro.org>
+Fixes: 67c9e6270f301 ("net: sched: Protect Qdisc::bstats with u64_stats")
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lore.kernel.org/r/20211021095919.bi3szpt3c2kcoiso@linutronix.de
+---
+ net/core/gen_stats.c | 43 +++++++++++++++++++++++++++++++++++++------
+ 1 file changed, 37 insertions(+), 6 deletions(-)
+
+--- a/net/core/gen_stats.c
++++ b/net/core/gen_stats.c
+@@ -171,20 +171,51 @@ void gnet_stats_add_basic(struct gnet_st
+ }
+ EXPORT_SYMBOL(gnet_stats_add_basic);
+
++static void gnet_stats_read_basic(u64 *ret_bytes, u64 *ret_packets,
++ struct gnet_stats_basic_sync __percpu *cpu,
++ struct gnet_stats_basic_sync *b, bool running)
++{
++ unsigned int start;
++
++ if (cpu) {
++ u64 t_bytes = 0, t_packets = 0;
++ int i;
++
++ for_each_possible_cpu(i) {
++ struct gnet_stats_basic_sync *bcpu = per_cpu_ptr(cpu, i);
++ unsigned int start;
++ u64 bytes, packets;
++
++ do {
++ start = u64_stats_fetch_begin_irq(&bcpu->syncp);
++ bytes = u64_stats_read(&bcpu->bytes);
++ packets = u64_stats_read(&bcpu->packets);
++ } while (u64_stats_fetch_retry_irq(&bcpu->syncp, start));
++
++ t_bytes += bytes;
++ t_packets += packets;
++ }
++ *ret_bytes = t_bytes;
++ *ret_packets = t_packets;
++ return;
++ }
++ do {
++ if (running)
++ start = u64_stats_fetch_begin_irq(&b->syncp);
++ *ret_bytes = u64_stats_read(&b->bytes);
++ *ret_packets = u64_stats_read(&b->packets);
++ } while (running && u64_stats_fetch_retry_irq(&b->syncp, start));
++}
++
+ static int
+ ___gnet_stats_copy_basic(struct gnet_dump *d,
+ struct gnet_stats_basic_sync __percpu *cpu,
+ struct gnet_stats_basic_sync *b,
+ int type, bool running)
+ {
+- struct gnet_stats_basic_sync bstats;
+ u64 bstats_bytes, bstats_packets;
+
+- gnet_stats_basic_sync_init(&bstats);
+- gnet_stats_add_basic(&bstats, cpu, b, running);
+-
+- bstats_bytes = u64_stats_read(&bstats.bytes);
+- bstats_packets = u64_stats_read(&bstats.packets);
++ gnet_stats_read_basic(&bstats_bytes, &bstats_packets, cpu, b, running);
+
+ if (d->compat_tc_stats && type == TCA_STATS_BASIC) {
+ d->tc_stats.bytes = bstats_bytes;