Blame SOURCES/nfs-utils-1.3.0-mountstats-rdma.patch

64c563
diff -up nfs-utils-1.3.0/tools/mountstats/mountstats.man.orig nfs-utils-1.3.0/tools/mountstats/mountstats.man
64c563
--- nfs-utils-1.3.0/tools/mountstats/mountstats.man.orig	2018-06-11 10:10:22.450171982 -0400
64c563
+++ nfs-utils-1.3.0/tools/mountstats/mountstats.man	2018-06-11 10:11:00.756778817 -0400
64c563
@@ -19,6 +19,8 @@ mountstats \- Displays various NFS clien
64c563
 .RB [ \-r | \-\-rpc ]
64c563
 |
64c563
 .RB  [ \-R | \-\-raw ]
64c563
+|
64c563
+.RB  [ \-x | \-\-xprt ]
64c563
 ]
64c563
 .RI [ mountpoint ] ...
64c563
 .P
64c563
@@ -110,6 +112,9 @@ Display only the raw statistics.  This i
64c563
 and
64c563
 .BR \-S | \-\-since
64c563
 options.
64c563
+.TP
64c563
+.B \-x, \-\-xprt
64c563
+Display only the transport statistics
64c563
 .SS Options specific to the iostat sub-command
64c563
 .IP "\fIinterval\fP"
64c563
 Specifies the amount of time in seconds between each report.  The first report contains statistics for the time since each file system was mounted.  Each subsequent report contains statistics collected during the interval since the previous report.  This may not be used with the
64c563
diff -up nfs-utils-1.3.0/tools/mountstats/mountstats.py.orig nfs-utils-1.3.0/tools/mountstats/mountstats.py
64c563
--- nfs-utils-1.3.0/tools/mountstats/mountstats.py.orig	2018-06-11 10:10:22.501172790 -0400
64c563
+++ nfs-utils-1.3.0/tools/mountstats/mountstats.py	2018-06-11 10:11:00.757778833 -0400
64c563
@@ -87,7 +87,10 @@ XprtUdpCounters = [
64c563
     'rpcreceives',
64c563
     'badxids',
64c563
     'inflightsends',
64c563
-    'backlogutil'
64c563
+    'backlogutil',
64c563
+    'maxslots',
64c563
+    'sendutil',
64c563
+    'pendutil'
64c563
 ]
64c563
 
64c563
 XprtTcpCounters = [
64c563
@@ -100,7 +103,10 @@ XprtTcpCounters = [
64c563
     'rpcreceives',
64c563
     'badxids',
64c563
     'inflightsends',
64c563
-    'backlogutil'
64c563
+    'backlogutil',
64c563
+    'maxslots',
64c563
+    'sendutil',
64c563
+    'pendutil'
64c563
 ]
64c563
 
64c563
 XprtRdmaCounters = [
64c563
@@ -112,17 +118,25 @@ XprtRdmaCounters = [
64c563
     'rpcsends',
64c563
     'rpcreceives',
64c563
     'badxids',
64c563
+    'inflightsends',
64c563
     'backlogutil',
64c563
-    'read_chunks',
64c563
-    'write_chunks',
64c563
-    'reply_chunks',
64c563
+    'read_segments',
64c563
+    'write_segments',
64c563
+    'reply_segments',
64c563
     'total_rdma_req',
64c563
     'total_rdma_rep',
64c563
     'pullup',
64c563
     'fixup',
64c563
     'hardway',
64c563
     'failed_marshal',
64c563
-    'bad_reply'
64c563
+    'bad_reply',
64c563
+    'nomsg_calls',
64c563
+    'recovered_mrs',
64c563
+    'orphaned_mrs',
64c563
+    'allocated_mrs',
64c563
+    'local_invalidates',
64c563
+    'empty_sendctx_q',
64c563
+    'reply_waits_for_send',
64c563
 ]
64c563
 
64c563
 Nfsv3ops = [
64c563
@@ -266,17 +280,20 @@ class DeviceData:
64c563
             if words[1] == 'udp':
64c563
                 i = 2
64c563
                 for key in XprtUdpCounters:
64c563
-                    self.__rpc_data[key] = int(words[i])
64c563
+                    if i < len(words):
64c563
+                        self.__rpc_data[key] = int(words[i])
64c563
                     i += 1
64c563
             elif words[1] == 'tcp':
64c563
                 i = 2
64c563
                 for key in XprtTcpCounters:
64c563
-                    self.__rpc_data[key] = int(words[i])
64c563
+                    if i < len(words):
64c563
+                        self.__rpc_data[key] = int(words[i])
64c563
                     i += 1
64c563
             elif words[1] == 'rdma':
64c563
                 i = 2
64c563
                 for key in XprtRdmaCounters:
64c563
-                    self.__rpc_data[key] = int(words[i])
64c563
+                    if i < len(words):
64c563
+                        self.__rpc_data[key] = int(words[i])
64c563
                     i += 1
64c563
         elif words[0] == 'per-op':
64c563
             self.__rpc_data['per-op'] = words
64c563
@@ -354,12 +371,11 @@ class DeviceData:
64c563
     def display_stats_header(self):
64c563
         print('Stats for %s mounted on %s:' % \
64c563
             (self.__nfs_data['export'], self.__nfs_data['mountpoint']))
64c563
+        print()
64c563
 
64c563
     def display_nfs_options(self):
64c563
         """Pretty-print the NFS options
64c563
         """
64c563
-        self.display_stats_header()
64c563
-
64c563
         print('  NFS mount options: %s' % ','.join(self.__nfs_data['mountoptions']))
64c563
         print('  NFS server capabilities: %s' % ','.join(self.__nfs_data['servercapabilities']))
64c563
         if 'nfsv4flags' in self.__nfs_data:
64c563
@@ -425,7 +441,6 @@ class DeviceData:
64c563
         """
64c563
         sends = self.__rpc_data['rpcsends']
64c563
 
64c563
-        print()
64c563
         print('RPC statistics:')
64c563
 
64c563
         print('  %d RPC requests sent, %d RPC replies received (%d XIDs not found)' % \
64c563
@@ -643,6 +658,83 @@ class DeviceData:
64c563
         self.__print_rpc_op_stats('WRITE', sample_time)
64c563
         sys.stdout.flush()
64c563
 
64c563
+    def display_xprt_stats(self):
64c563
+        """Pretty-print the xprt statistics
64c563
+        """
64c563
+        if self.__rpc_data['protocol'] == 'udp':
64c563
+            print('\tTransport protocol: udp')
64c563
+            print('\tSource port: %d' % self.__rpc_data['port'])
64c563
+            print('\tBind count: %d' % self.__rpc_data['bind_count'])
64c563
+            print('\tRPC requests: %d' % self.__rpc_data['rpcsends'])
64c563
+            print('\tRPC replies: %d' % self.__rpc_data['rpcreceives'])
64c563
+            print('\tXIDs not found: %d' % self.__rpc_data['badxids'])
64c563
+            print('\tMax slots: %d' % self.__rpc_data['maxslots'])
64c563
+            if self.__rpc_data['rpcsends'] != 0:
64c563
+                print('\tAvg backlog length: %d' % \
64c563
+                    (float(self.__rpc_data['backlogutil']) / self.__rpc_data['rpcsends']))
64c563
+                print('\tAvg send queue length: %d' % \
64c563
+                    (float(self.__rpc_data['sendutil']) / self.__rpc_data['rpcsends']))
64c563
+                print('\tAvg pending queue length: %d' % \
64c563
+                    (float(self.__rpc_data['pendutil']) / self.__rpc_data['rpcsends']))
64c563
+        elif self.__rpc_data['protocol'] == 'tcp':
64c563
+            print('\tTransport protocol: tcp')
64c563
+            print('\tSource port: %d' % self.__rpc_data['port'])
64c563
+            print('\tBind count: %d' % self.__rpc_data['bind_count'])
64c563
+            print('\tConnect count: %d' % self.__rpc_data['connect_count'])
64c563
+            print('\tConnect time: %d seconds' % self.__rpc_data['connect_time'])
64c563
+            print('\tIdle time: %d seconds' % self.__rpc_data['idle_time'])
64c563
+            print('\tRPC requests: %d' % self.__rpc_data['rpcsends'])
64c563
+            print('\tRPC replies: %d' % self.__rpc_data['rpcreceives'])
64c563
+            print('\tXIDs not found: %d' % self.__rpc_data['badxids'])
64c563
+            print('\tMax slots: %d' % self.__rpc_data['maxslots'])
64c563
+            if self.__rpc_data['rpcsends'] != 0:
64c563
+                print('\tAvg backlog length: %d' % \
64c563
+                    (float(self.__rpc_data['backlogutil']) / self.__rpc_data['rpcsends']))
64c563
+                print('\tAvg send queue length: %d' % \
64c563
+                    (float(self.__rpc_data['sendutil']) / self.__rpc_data['rpcsends']))
64c563
+                print('\tAvg pending queue length: %d' % \
64c563
+                    (float(self.__rpc_data['pendutil']) / self.__rpc_data['rpcsends']))
64c563
+        elif self.__rpc_data['protocol'] == 'rdma':
64c563
+            print('\tTransport protocol: rdma')
64c563
+            print('\tConnect count: %d' % self.__rpc_data['connect_count'])
64c563
+            print('\tConnect time: %d seconds' % self.__rpc_data['connect_time'])
64c563
+            print('\tIdle time: %d seconds' % self.__rpc_data['idle_time'])
64c563
+            sends = self.__rpc_data['rpcsends']
64c563
+            print('\tRPC requests: %d' % self.__rpc_data['rpcsends'])
64c563
+            print('\tRPC replies: %d' % self.__rpc_data['rpcreceives'])
64c563
+            print('\tXIDs not found: %d' % self.__rpc_data['badxids'])
64c563
+            if self.__rpc_data['rpcsends'] != 0:
64c563
+                print('\tAvg backlog length: %d' % \
64c563
+                    (float(self.__rpc_data['backlogutil']) / self.__rpc_data['rpcsends']))
64c563
+            print('\tRead segments: %d' % self.__rpc_data['read_segments'])
64c563
+            print('\tWrite segments: %d' % self.__rpc_data['write_segments'])
64c563
+            print('\tReply segments: %d' % self.__rpc_data['reply_segments'])
64c563
+            print('\tRegistered: %d bytes' % self.__rpc_data['total_rdma_req'])
64c563
+            print('\tRDMA received: %d bytes' % self.__rpc_data['total_rdma_rep'])
64c563
+            print('\tTotal pull-up: %d bytes' % self.__rpc_data['pullup'])
64c563
+            print('\tTotal fix-up: %d bytes' % self.__rpc_data['fixup'])
64c563
+            print('\tHardway allocations: %d bytes' % self.__rpc_data['hardway'])
64c563
+            print('\tFailed marshals: %d' % self.__rpc_data['failed_marshal'])
64c563
+            print('\tBad replies: %d' % self.__rpc_data['bad_reply'])
64c563
+
64c563
+            """ Counters not present in all kernels """
64c563
+            if 'nomsg_calls' in self.__rpc_data:
64c563
+                print('\tRDMA_NOMSG calls: %d' % self.__rpc_data['nomsg_calls'])
64c563
+            if 'allocated_mrs' in self.__rpc_data:
64c563
+                print('\tAllocated MRs: %d' % self.__rpc_data['allocated_mrs'])
64c563
+            if 'recovered_mrs' in self.__rpc_data:
64c563
+                print('\tRecovered MRs: %d' % self.__rpc_data['recovered_mrs'])
64c563
+            if 'orphaned_mrs' in self.__rpc_data:
64c563
+                print('\tOrphaned MRs: %d' % self.__rpc_data['orphaned_mrs'])
64c563
+            if 'local_invalidates' in self.__rpc_data:
64c563
+                print('\tLocal Invalidates needed: %d' % self.__rpc_data['local_invalidates'])
64c563
+            if 'empty_sendctx_q' in self.__rpc_data:
64c563
+                print('\tEmpty sendctx queue count: %d' % self.__rpc_data['empty_sendctx_q'])
64c563
+            if 'reply_waits_for_send' in self.__rpc_data:
64c563
+                print('\tReplies that waited for Send completion: %d' % self.__rpc_data['reply_waits_for_send'])
64c563
+        else:
64c563
+            raise Exception('Unknown RPC transport protocol %s' % self.__rpc_data['protocol'])
64c563
+
64c563
 def parse_stats_file(f):
64c563
     """pop the contents of a mountstats file into a dictionary,
64c563
     keyed by mount point.  each value object is a list of the
64c563
@@ -669,8 +761,9 @@ def parse_stats_file(f):
64c563
 
64c563
     return ms_dict
64c563
 
64c563
-def print_mountstats(stats, nfs_only, rpc_only, raw):
64c563
+def print_mountstats(stats, nfs_only, rpc_only, raw, xprt_only):
64c563
     if nfs_only:
64c563
+       stats.display_stats_header()
64c563
        stats.display_nfs_options()
64c563
        stats.display_nfs_events()
64c563
        stats.display_nfs_bytes()
64c563
@@ -680,7 +773,11 @@ def print_mountstats(stats, nfs_only, rp
64c563
        stats.display_rpc_op_stats()
64c563
     elif raw:
64c563
        stats.display_raw_stats()
64c563
+    elif xprt_only:
64c563
+       stats.display_stats_header()
64c563
+       stats.display_xprt_stats()
64c563
     else:
64c563
+       stats.display_stats_header()
64c563
        stats.display_nfs_options()
64c563
        stats.display_nfs_bytes()
64c563
        stats.display_rpc_generic_stats()
64c563
@@ -722,14 +819,14 @@ def mountstats_command(args):
64c563
         stats = DeviceData()
64c563
         stats.parse_stats(mountstats[mp])
64c563
         if not args.since:
64c563
-            print_mountstats(stats, args.nfs_only, args.rpc_only, args.raw)
64c563
+            print_mountstats(stats, args.nfs_only, args.rpc_only, args.raw, args.xprt_only)
64c563
         elif args.since and mp not in old_mountstats:
64c563
-            print_mountstats(stats, args.nfs_only, args.rpc_only, args.raw)
64c563
+            print_mountstats(stats, args.nfs_only, args.rpc_only, args.raw, args.xprt_only)
64c563
         else:
64c563
             old_stats = DeviceData()
64c563
             old_stats.parse_stats(old_mountstats[mp])
64c563
             diff_stats = stats.compare_iostats(old_stats)
64c563
-            print_mountstats(diff_stats, args.nfs_only, args.rpc_only, args.raw)
64c563
+            print_mountstats(diff_stats, args.nfs_only, args.rpc_only, args.raw, args.xprt_only)
64c563
 
64c563
     args.infile.close()
64c563
     if args.since:
64c563
@@ -941,6 +1038,8 @@ def main():
64c563
         help='Display only the RPC statistics')
64c563
     group.add_argument('-R', '--raw', action='store_true',
64c563
         help='Display only the raw statistics')
64c563
+    group.add_argument('-x', '--xprt', action='store_true', dest='xprt_only',
64c563
+        help='Display only the xprt statistics')
64c563
     # The mountpoints argument cannot be moved into the common_parser because
64c563
     # it will screw up the parsing of the iostat arguments (interval and count)
64c563
     mountstats_parser.add_argument('mountpoints', nargs='*', metavar='mountpoint',