diff --git a/nfs-utils-2.5.4-nfsiostat-fixes.patch b/nfs-utils-2.5.4-nfsiostat-fixes.patch new file mode 100644 index 0000000..7533ba4 --- /dev/null +++ b/nfs-utils-2.5.4-nfsiostat-fixes.patch @@ -0,0 +1,310 @@ +diff --git a/tools/mountstats/mountstats.py b/tools/mountstats/mountstats.py +index 8e129c83..d488f9e1 100755 +--- a/tools/mountstats/mountstats.py ++++ b/tools/mountstats/mountstats.py +@@ -333,6 +333,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 +@@ -953,73 +958,78 @@ def nfsstat_command(args): + return 0 + + def print_iostat_summary(old, new, devices, time): ++ if len(devices) == 0: ++ print('No NFS mount points were found') ++ return ++ + for device in devices: + stats = DeviceData() + stats.parse_stats(new[device]) +- if not old or device not in old: ++ if old and device in old: ++ old_stats = DeviceData() ++ old_stats.parse_stats(old[device]) ++ if stats.fstype() == old_stats.fstype(): ++ stats.compare_iostats(old_stats).display_iostats(time) ++ else: # device is in old, but fstypes are different ++ stats.display_iostats(time) ++ else: # device is only in new + stats.display_iostats(time) +- else: +- if ("fstype autofs" not in str(old[device])) and ("fstype autofs" not in str(new[device])): +- old_stats = DeviceData() +- old_stats.parse_stats(old[device]) +- diff_stats = stats.compare_iostats(old_stats) +- diff_stats.display_iostats(time) ++ ++def list_nfs_mounts(givenlist, mountstats): ++ """return a list of NFS mounts given a list to validate or ++ return a full list if the given list is empty - ++ may return an empty list if none found ++ """ ++ devicelist = [] ++ if len(givenlist) > 0: ++ for device in givenlist: ++ 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() ++ stats.parse_stats(descr) ++ if stats.is_nfs_mountpoint(): ++ devicelist += [device] ++ return devicelist + + def iostat_command(args): + """iostat-like command for NFS mount points + """ + mountstats = parse_stats_file(args.infile) +- devices = [os.path.normpath(mp) for mp in args.mountpoints] ++ origdevices = [os.path.normpath(mp) for mp in args.mountpoints] + + if args.since: + old_mountstats = parse_stats_file(args.since) + else: + old_mountstats = None + +- # make certain devices contains only NFS mount points +- if len(devices) > 0: +- check = [] +- for device in devices: +- stats = DeviceData() +- try: +- stats.parse_stats(mountstats[device]) +- if stats.is_nfs_mountpoint(): +- check += [device] +- except KeyError: +- continue +- devices = check +- else: +- for device, descr in mountstats.items(): +- stats = DeviceData() +- stats.parse_stats(descr) +- if stats.is_nfs_mountpoint(): +- devices += [device] +- if len(devices) == 0: +- print('No NFS mount points were found') +- return 1 +- + sample_time = 0 + ++ # make certain devices contains only NFS mount points ++ devices = list_nfs_mounts(origdevices, mountstats) ++ print_iostat_summary(old_mountstats, mountstats, devices, sample_time) ++ + if args.interval is None: +- print_iostat_summary(old_mountstats, mountstats, devices, sample_time) + return + +- if args.count is not None: +- count = args.count +- while count != 0: +- print_iostat_summary(old_mountstats, mountstats, devices, sample_time) +- old_mountstats = mountstats +- time.sleep(args.interval) +- sample_time = args.interval +- mountstats = parse_stats_file(args.infile) ++ count = args.count ++ while True: ++ if count is not None: + count -= 1 +- else: +- while True: +- print_iostat_summary(old_mountstats, mountstats, devices, sample_time) +- old_mountstats = mountstats +- time.sleep(args.interval) +- sample_time = args.interval +- mountstats = parse_stats_file(args.infile) ++ if count == 0: ++ break ++ time.sleep(args.interval) ++ old_mountstats = mountstats ++ sample_time = args.interval ++ mountstats = parse_stats_file(args.infile) ++ # 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) + + args.infile.close() + if args.since: +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 diff --git a/nfs-utils.spec b/nfs-utils.spec index 21040a1..a07b027 100644 --- a/nfs-utils.spec +++ b/nfs-utils.spec @@ -73,6 +73,7 @@ Patch029: nfs-utils-2.5.4-mount-writable.patch Patch030: nfs-utils-2.5.4-mount-v3-retry.patch Patch031: nfs-utils-2.5.4-conffile-argument.patch Patch032: nfs-utils-2.5.4-fix-nfsdcld-starting-too-early.patch +Patch033: nfs-utils-2.5.4-nfsiostat-fixes.patch Patch100: nfs-utils-1.2.1-statdpath-man.patch Patch101: nfs-utils-1.2.1-exp-subtree-warn-off.patch @@ -514,6 +515,12 @@ fi %{_mandir}/*/nfsiostat.8.gz %changelog +* Sun Feb 16 2025 Steve Dickson 2.5.4-34 +- mountstats/nfsiostat: bugfixes for iostat (RHEL-72243) + +* Sat Feb 15 2025 Steve Dickson 2.5.4-33 +- Add nfs.conf to nfsv4-client-utils package (RHEL-72013) + * Fri Feb 7 2025 Scott Mayhew 2.5.4-32 - Undo 'Add explicit version requirement for libnfsidmap' from previous build (RHEL-78107) - Undo 'Add --disable-sbin-override for when /sbin is a symlink' from previous build (RHEL-69771)