26f8410d mountstats/nfsiostat: merge and rework the infinite and counted loops 21238e5c mountstats/nfsiostat: Move the checks for empty mountpoint list into the print function 1bd30a9d nfsiostat: make comment explain mount/unmount more broadly 2b9251ed nfsiostat: fix crash when filtering mountstats after unmount 9836adbc nfsiostat: mirror how mountstats iostat prints the stats 936a19cc mountstats/nfsiostat: add a function to return the fstype 155c5343 nfsiostat: skip argv[0] when parsing command-line 39f57998 nfsiostat/mountstats: handle KeyError in compare_iostats() c4c14011 nfsiostat: replace 'list' reserved word diff --git a/tools/nfs-iostat/nfs-iostat.py b/tools/nfs-iostat/nfs-iostat.py index 7cbe543c..dec0e861 100644 --- a/tools/nfs-iostat/nfs-iostat.py +++ b/tools/nfs-iostat/nfs-iostat.py @@ -493,20 +493,20 @@ def list_nfs_mounts(givenlist, mountstats): return a full list if the given list is empty - may return an empty list if none found """ - list = [] + devicelist = [] if len(givenlist) > 0: for device in givenlist: stats = DeviceData() stats.parse_stats(mountstats[device]) if stats.is_nfs_mountpoint(): - list += [device] + devicelist += [device] else: for device, descr in mountstats.items(): stats = DeviceData() stats.parse_stats(descr) if stats.is_nfs_mountpoint(): - list += [device] - return list + devicelist += [device] + return devicelist def iostat_command(name): """iostat-like command for NFS mount points diff --git a/tools/mountstats/mountstats.py b/tools/mountstats/mountstats.py index 014f38a3..1054f698 100755 --- a/tools/mountstats/mountstats.py +++ b/tools/mountstats/mountstats.py @@ -560,7 +560,10 @@ class DeviceData: # the reference to them. so we build new lists here # for the result object. for op in result.__rpc_data['ops']: - result.__rpc_data[op] = list(map(difference, self.__rpc_data[op], old_stats.__rpc_data[op])) + try: + result.__rpc_data[op] = list(map(difference, self.__rpc_data[op], old_stats.__rpc_data[op])) + except KeyError: + continue # update the remaining keys if protocol == 'udp': diff --git a/tools/nfs-iostat/nfs-iostat.py b/tools/nfs-iostat/nfs-iostat.py index b7e98a2a..5556f692 100755 --- a/tools/nfs-iostat/nfs-iostat.py +++ b/tools/nfs-iostat/nfs-iostat.py @@ -213,8 +213,11 @@ class DeviceData: # the reference to them. so we build new lists here # for the result object. for op in result.__rpc_data['ops']: - result.__rpc_data[op] = list(map( - difference, self.__rpc_data[op], old_stats.__rpc_data[op])) + try: + result.__rpc_data[op] = list(map( + difference, self.__rpc_data[op], old_stats.__rpc_data[op])) + except KeyError: + continue # update the remaining keys we care about result.__rpc_data['rpcsends'] -= old_stats.__rpc_data['rpcsends'] diff --git a/tools/nfs-iostat/nfs-iostat.py b/tools/nfs-iostat/nfs-iostat.py index 85294fb9..e46b1a83 100755 --- a/tools/nfs-iostat/nfs-iostat.py +++ b/tools/nfs-iostat/nfs-iostat.py @@ -187,6 +187,11 @@ class DeviceData: found = True self.__parse_rpc_line(words) + def fstype(self): + """Return the fstype for the mountpoint + """ + return self.__nfs_data['fstype'] + def is_nfs_mountpoint(self): """Return True if this is an NFS or NFSv4 mountpoint, otherwise return False @@ -471,41 +476,31 @@ def parse_stats_file(filename): return ms_dict def print_iostat_summary(old, new, devices, time, options): - stats = {} - diff_stats = {} - devicelist = [] - if old: - # Trim device list to only include intersection of old and new data, - # this addresses umounts due to autofs mountpoints - for device in devices: - if "fstype autofs" not in str(old[device]): - devicelist.append(device) - else: - devicelist = devices + display_stats = {} + + if len(devices) == 0: + print('No NFS mount points were found') + return - for device in devicelist: - stats[device] = DeviceData() - stats[device].parse_stats(new[device]) - if old: + for device in devices: + stats = DeviceData() + stats.parse_stats(new[device]) + if old and device in old: old_stats = DeviceData() old_stats.parse_stats(old[device]) - diff_stats[device] = stats[device].compare_iostats(old_stats) + if stats.fstype() == old_stats.fstype(): + display_stats[device] = stats.compare_iostats(old_stats) + else: # device is in old, but fstypes are different + display_stats[device] = stats + else: # device is only in new + display_stats[device] = stats if options.sort: - if old: - # We now have compared data and can print a comparison - # ordered by mountpoint ops per second - devicelist.sort(key=lambda x: diff_stats[x].ops(time), reverse=True) - else: - # First iteration, just sort by newly parsed ops/s - devicelist.sort(key=lambda x: stats[x].ops(time), reverse=True) + devices.sort(key=lambda x: display_stats[x].ops(time), reverse=True) count = 1 - for device in devicelist: - if old: - diff_stats[device].display_iostats(time, options.which) - else: - stats[device].display_iostats(time, options.which) + for device in devices: + display_stats[device].display_iostats(time, options.which) count += 1 if (count > options.list): @@ -520,10 +515,11 @@ def list_nfs_mounts(givenlist, mountstats): devicelist = [] if len(givenlist) > 0: for device in givenlist: - stats = DeviceData() - stats.parse_stats(mountstats[device]) - if stats.is_nfs_mountpoint(): - devicelist += [device] + if device in mountstats: + stats = DeviceData() + stats.parse_stats(mountstats[device]) + if stats.is_nfs_mountpoint(): + devicelist += [device] else: for device, descr in mountstats.items(): stats = DeviceData() @@ -592,11 +588,7 @@ client are listed. parser.add_option_group(displaygroup) (options, args) = parser.parse_args(sys.argv) - for arg in args: - - if arg == sys.argv[0]: - continue - + for arg in args[1:]: if arg in mountstats: origdevices += [arg] elif not interval_seen: @@ -622,47 +614,29 @@ client are listed. print('Illegal value %s' % arg) return - # make certain devices contains only NFS mount points - devices = list_nfs_mounts(origdevices, mountstats) - if len(devices) == 0: - print('No NFS mount points were found') - return - - old_mountstats = None sample_time = 0.0 + # make certain devices contains only NFS mount points + devices = list_nfs_mounts(origdevices, mountstats) + print_iostat_summary(old_mountstats, mountstats, devices, sample_time, options) + if not interval_seen: - print_iostat_summary(old_mountstats, mountstats, devices, sample_time, options) return - if count_seen: - while count != 0: - print_iostat_summary(old_mountstats, mountstats, devices, sample_time, options) - old_mountstats = mountstats - time.sleep(interval) - sample_time = interval - mountstats = parse_stats_file('/proc/self/mountstats') - # automount mountpoints add and drop, if automount is involved - # we need to recheck the devices list when reparsing - devices = list_nfs_mounts(origdevices,mountstats) - if len(devices) == 0: - print('No NFS mount points were found') - return + while True: + if count_seen: count -= 1 - else: - while True: - print_iostat_summary(old_mountstats, mountstats, devices, sample_time, options) - old_mountstats = mountstats - time.sleep(interval) - sample_time = interval - mountstats = parse_stats_file('/proc/self/mountstats') - # automount mountpoints add and drop, if automount is involved - # we need to recheck the devices list when reparsing - devices = list_nfs_mounts(origdevices,mountstats) - if len(devices) == 0: - print('No NFS mount points were found') - return + if count == 0: + break + time.sleep(interval) + old_mountstats = mountstats + sample_time = interval + mountstats = parse_stats_file('/proc/self/mountstats') + # nfs mountpoints may appear or disappear, so we need to + # recheck the devices list each time we parse mountstats + devices = list_nfs_mounts(origdevices, mountstats) + print_iostat_summary(old_mountstats, mountstats, devices, sample_time, options) # # Main