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

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