From: Chuck Lever <cel@kernel.org>
To: Steve Dickson <SteveD@redhat.com>
Cc: <linux-nfs@vger.kernel.org>, Chuck Lever <chuck.lever@oracle.com>
Subject: [PATCH] mountstats: Fix per-operation percentages with nconnect
Date: Sat, 28 Feb 2026 12:46:54 -0500 [thread overview]
Message-ID: <20260228174654.129309-1-cel@kernel.org> (raw)
From: Chuck Lever <chuck.lever@oracle.com>
Per-operation percentages reported by "mountstats --rpc" are
inaccurate when an NFS mount uses nconnect.
With nconnect=N, the kernel emits N separate "xprt:" lines in
/proc/self/mountstats, one per transport. Each transport tracks
its own rpcsends counter reflecting only RPCs routed through that
connection.
The parser overwrites rpcsends on each "xprt:" line, keeping only
the last transport's value. Per-operation counts (READ, WRITE,
etc.) are maintained in a single array per RPC client and reflect
all RPCs across all transports.
With nconnect=3 and balanced round-robin, rpcsends holds roughly
one third of total RPCs while per-op counts hold the full total.
display_rpc_op_stats() computes (op_count * 100) / rpcsends,
yielding percentages roughly three times too large.
Accumulate rpcsends, rpcreceives, badxids, backlogutil,
sendutil, and pendutil across multiple "xprt:" lines. These are
cumulative counters where the sum across transports gives the
correct aggregate. Per-connection properties (port, bind_count,
connect_count, connect_time, idle_time, maxslots, inflightsends)
retain the value from the last transport seen.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
tools/mountstats/mountstats.py | 61 +++++++++++++++++++++++++---------
1 file changed, 46 insertions(+), 15 deletions(-)
diff --git a/tools/mountstats/mountstats.py b/tools/mountstats/mountstats.py
index d488f9e1c258..a6adab344d0e 100755
--- a/tools/mountstats/mountstats.py
+++ b/tools/mountstats/mountstats.py
@@ -140,6 +140,38 @@ XprtRdmaCounters = [
'reply_waits_for_send',
]
+# Counters that should be summed across transports when nconnect > 1.
+# Each is stored in a per-transport structure in the kernel
+# (xprt->stat or rpcrdma_xprt.rx_stats) and represents a cumulative
+# event count or utilization value. Per-connection properties (port,
+# bind_count, connect_count, connect_time, idle_time, maxslots,
+# inflightsends) retain the value from the last transport seen.
+XprtAccumulatedCounters = {
+ 'rpcsends',
+ 'rpcreceives',
+ 'badxids',
+ 'backlogutil',
+ 'sendutil',
+ 'pendutil',
+ 'read_segments',
+ 'write_segments',
+ 'reply_segments',
+ 'total_rdma_req',
+ 'total_rdma_rep',
+ 'pullup',
+ 'fixup',
+ 'hardway',
+ 'failed_marshal',
+ 'bad_reply',
+ 'nomsg_calls',
+ 'recovered_mrs',
+ 'orphaned_mrs',
+ 'allocated_mrs',
+ 'local_invalidates',
+ 'empty_sendctx_q',
+ 'reply_waits_for_send',
+}
+
Nfsv3ops = [
'NULL',
'GETATTR',
@@ -291,23 +323,22 @@ class DeviceData:
elif words[0] == 'xprt:':
self.__rpc_data['protocol'] = words[1]
if words[1] == 'udp':
- i = 2
- for key in XprtUdpCounters:
- if i < len(words):
- self.__rpc_data[key] = int(words[i])
- i += 1
+ counters = XprtUdpCounters
elif words[1] == 'tcp':
- i = 2
- for key in XprtTcpCounters:
- if i < len(words):
- self.__rpc_data[key] = int(words[i])
- i += 1
+ counters = XprtTcpCounters
elif words[1] == 'rdma':
- i = 2
- for key in XprtRdmaCounters:
- if i < len(words):
- self.__rpc_data[key] = int(words[i])
- i += 1
+ counters = XprtRdmaCounters
+ else:
+ counters = []
+ i = 2
+ for key in counters:
+ if i < len(words):
+ val = int(words[i])
+ if key in XprtAccumulatedCounters and key in self.__rpc_data:
+ self.__rpc_data[key] += val
+ else:
+ self.__rpc_data[key] = val
+ i += 1
elif words[0] == 'per-op':
self.__rpc_data['per-op'] = words
else:
--
2.53.0
next reply other threads:[~2026-02-28 17:46 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-28 17:46 Chuck Lever [this message]
2026-03-06 22:11 ` [PATCH] mountstats: Fix per-operation percentages with nconnect Steve Dickson
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=20260228174654.129309-1-cel@kernel.org \
--to=cel@kernel.org \
--cc=SteveD@redhat.com \
--cc=chuck.lever@oracle.com \
--cc=linux-nfs@vger.kernel.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.