All of lore.kernel.org
 help / color / mirror / Atom feed
From: Steve Dickson <steved@redhat.com>
To: Chuck Lever <cel@kernel.org>
Cc: linux-nfs@vger.kernel.org, Chuck Lever <chuck.lever@oracle.com>
Subject: Re: [PATCH] mountstats: Fix per-operation percentages with nconnect
Date: Fri, 6 Mar 2026 17:11:29 -0500	[thread overview]
Message-ID: <4ad019df-e024-4ecd-b7c0-a44b348dcdb0@redhat.com> (raw)
In-Reply-To: <20260228174654.129309-1-cel@kernel.org>



On 2/28/26 12:46 PM, Chuck Lever wrote:
> 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>
Committed... (tag: nfs-utils-2-8-6-rc4)

steved.
> ---
>   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:


      reply	other threads:[~2026-03-06 22:11 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-02-28 17:46 [PATCH] mountstats: Fix per-operation percentages with nconnect Chuck Lever
2026-03-06 22:11 ` Steve Dickson [this message]

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=4ad019df-e024-4ecd-b7c0-a44b348dcdb0@redhat.com \
    --to=steved@redhat.com \
    --cc=cel@kernel.org \
    --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.