[Devel] [PATCH RHEL10 COMMIT] fs/fuse kio: zero cs_stats accumulators on each seqlock retry
Konstantin Khorenko
khorenko at virtuozzo.com
Mon Jun 15 13:43:02 MSK 2026
The commit is pushed to "branch-rh10-6.12.0-211.16.1.12.x.vz10-ovz" and will appear at git at bitbucket.org:openvz/vzkernel.git
after rh10-6.12.0-211.16.1.el10
------>
commit e3508247b74d6c6c8a1cf9dc2058a45a6b9d18b4
Author: Konstantin Khorenko <khorenko at virtuozzo.com>
Date: Wed Jun 3 23:57:17 2026 +0200
fs/fuse kio: zero cs_stats accumulators on each seqlock retry
do_show_cs_stats() sums the per-cpu latency/rate counters into the
on-stack accumulators inside a read_seqretry() loop:
iolat, netlat, read_ops_rate, write_ops_rate, sync_ops_rate.
The accumulators were initialised only once, before the loop.
If a writer (pcs_cs_update_stat() / pcs_cs_stat_up(), both under
write_seqlock(&cs->stat.seqlock)) runs concurrently, read_seqretry()
re-executes the loop body, summing every per-cpu counter a second time
on top of the already-populated structs - producing over-counted values
in the cs_stats output.
Zero the accumulators at the top of each pass so a retry starts clean,
and remove the initialization in the header as redundant.
Fixes: d3a72ba5c1ae ("fs/fuse kio: implement cs_stats statistics info")
https://virtuozzo.atlassian.net/browse/VSTOR-132310
Signed-off-by: Konstantin Khorenko <khorenko at virtuozzo.com>
Feature: vStorage
---
fs/fuse/kio/pcs/fuse_stat.c | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/fs/fuse/kio/pcs/fuse_stat.c b/fs/fuse/kio/pcs/fuse_stat.c
index 447e4a617655..41bb9c71af90 100644
--- a/fs/fuse/kio/pcs/fuse_stat.c
+++ b/fs/fuse/kio/pcs/fuse_stat.c
@@ -331,15 +331,25 @@ static int do_show_cs_stats(struct pcs_cs *cs, void *ctx)
struct seq_file *m = ctx;
int rpc_state = cs->rpc ? cs->rpc->state : PCS_RPC_UNCONN;
unsigned int in_flight_avg = cs->in_flight_avg;
- struct fuse_lat_stat iolat = {}, netlat = {};
- struct pcs_perf_rate_cnt read_ops_rate = {}, write_ops_rate = {},
- sync_ops_rate = {};
+ struct fuse_lat_stat iolat, netlat;
+ struct pcs_perf_rate_cnt read_ops_rate, write_ops_rate, sync_ops_rate;
unsigned seq;
do {
int cpu;
seq = read_seqbegin(&cs->stat.seqlock);
+ /*
+ * read_seqretry() may re-run this loop if a writer updated the
+ * stats meanwhile; zero the accumulators on every pass so a
+ * retry does not sum the per-cpu counters on top of the values
+ * already gathered by the previous (aborted) pass.
+ */
+ memset(&iolat, 0, sizeof(iolat));
+ memset(&netlat, 0, sizeof(netlat));
+ memset(&read_ops_rate, 0, sizeof(read_ops_rate));
+ memset(&write_ops_rate, 0, sizeof(write_ops_rate));
+ memset(&sync_ops_rate, 0, sizeof(sync_ops_rate));
for_each_possible_cpu(cpu) {
struct fuse_lat_stat *pcpu_iolat, *pcpu_netlat;
struct pcs_perf_rate_cnt *pcpu_read_rate,
More information about the Devel
mailing list