X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=tools%2Fnfs-iostat%2Fnfs-iostat.py;h=d9096321f59aae9eb131340cb8a5cff5b38d7ccd;hp=5c46f9261cff998755ea3333026bb92a9b666ca4;hb=3ad7dea527170ae12c9cdc2e428d0676ac261144;hpb=c3203ff9a940e1e2270e06673eca77066aabd77c diff --git a/tools/nfs-iostat/nfs-iostat.py b/tools/nfs-iostat/nfs-iostat.py index 5c46f92..d909632 100644 --- a/tools/nfs-iostat/nfs-iostat.py +++ b/tools/nfs-iostat/nfs-iostat.py @@ -17,7 +17,8 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +MA 02110-1301 USA """ import sys, os, time @@ -85,6 +86,12 @@ class DeviceData: self.__nfs_data['fstype'] = words[7] if words[7] == 'nfs': self.__nfs_data['statvers'] = words[8] + elif 'nfs' in words or 'nfs4' in words: + self.__nfs_data['export'] = words[0] + self.__nfs_data['mountpoint'] = words[3] + self.__nfs_data['fstype'] = words[6] + if words[6] == 'nfs': + self.__nfs_data['statvers'] = words[7] elif words[0] == 'age:': self.__nfs_data['age'] = long(words[1]) elif words[0] == 'opts:': @@ -354,12 +361,24 @@ class DeviceData: print '\t%7.3f' % rtt_per_op, print '\t%7.3f' % exe_per_op + def ops(self, sample_time): + sends = float(self.__rpc_data['rpcsends']) + if sample_time == 0: + sample_time = float(self.__nfs_data['age']) + return (sends / sample_time) + def display_iostats(self, sample_time, which): """Display NFS and RPC stats in an iostat-like way """ sends = float(self.__rpc_data['rpcsends']) if sample_time == 0: sample_time = float(self.__nfs_data['age']) + # sample_time could still be zero if the export was just mounted. + # Set it to 1 to avoid divide by zero errors in this case since we'll + # likely still have relevant mount statistics to show. + # + if sample_time == 0: + sample_time = 1; if sends != 0: backlog = (float(self.__rpc_data['backlogutil']) / sends) / sample_time else: @@ -413,6 +432,9 @@ def parse_stats_file(filename): if words[0] == 'device': key = words[4] new = [ line.strip() ] + elif 'nfs' in words or 'nfs4' in words: + key = words[3] + new = [ line.strip() ] else: new += [ line.strip() ] ms_dict[key] = new @@ -420,7 +442,9 @@ def parse_stats_file(filename): return ms_dict -def print_iostat_summary(old, new, devices, time, ac): +def print_iostat_summary(old, new, devices, time, options): + stats = {} + diff_stats = {} if old: # Trim device list to only include intersection of old and new data, # this addresses umounts due to autofs mountpoints @@ -429,15 +453,33 @@ def print_iostat_summary(old, new, devices, time, ac): devicelist = devices for device in devicelist: - stats = DeviceData() - stats.parse_stats(new[device]) - if not old: - stats.display_iostats(time, ac) - else: + stats[device] = DeviceData() + stats[device].parse_stats(new[device]) + if old: old_stats = DeviceData() old_stats.parse_stats(old[device]) - diff_stats = stats.compare_iostats(old_stats) - diff_stats.display_iostats(time, ac) + diff_stats[device] = stats[device].compare_iostats(old_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) + + count = 1 + for device in devicelist: + if old: + diff_stats[device].display_iostats(time, options.which) + else: + stats[device].display_iostats(time, options.which) + + count += 1 + if (count > options.list): + return + def list_nfs_mounts(givenlist, mountstats): """return a list of NFS mounts given a list to validate or @@ -485,10 +527,10 @@ client are listed. usage="usage: %prog [ [ ] ] [ ] [ ]", description=mydescription, version='version %s' % Iostats_version) - parser.set_defaults(which=0) + parser.set_defaults(which=0, sort=False, list=sys.maxint) statgroup = OptionGroup(parser, "Statistics Options", - 'File I/O is displayed unless one of the following is specified:') + 'File I/O is displayed unless one of the following is specified:') statgroup.add_option('-a', '--attr', action="store_const", dest="which", @@ -505,9 +547,20 @@ client are listed. const=3, help='displays statistics related to the page cache') parser.add_option_group(statgroup) + displaygroup = OptionGroup(parser, "Display Options", + 'Options affecting display format:') + displaygroup.add_option('-s', '--sort', + action="store_true", + dest="sort", + help="Sort NFS mount points by ops/second") + displaygroup.add_option('-l','--list', + action="store", + type="int", + dest="list", + help="only print stats for first LIST mount points") + parser.add_option_group(displaygroup) (options, args) = parser.parse_args(sys.argv) - for arg in args: if arg == sys.argv[0]: @@ -549,12 +602,12 @@ client are listed. sample_time = 0.0 if not interval_seen: - print_iostat_summary(old_mountstats, mountstats, devices, sample_time, options.which) + 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.which) + print_iostat_summary(old_mountstats, mountstats, devices, sample_time, options) old_mountstats = mountstats time.sleep(interval) sample_time = interval @@ -568,7 +621,7 @@ client are listed. count -= 1 else: while True: - print_iostat_summary(old_mountstats, mountstats, devices, sample_time, options.which) + print_iostat_summary(old_mountstats, mountstats, devices, sample_time, options) old_mountstats = mountstats time.sleep(interval) sample_time = interval