/
usr
/
sbin
/
/usr/sbin
mkdir
upload
Name
Size
Mode
Actions
accessdb
12888
0755
edit
dl
rm
addgnupghome
3075
0755
edit
dl
rm
addpart
25456
0755
edit
dl
rm
adduser
151720
0755
edit
dl
rm
agetty
63888
0755
edit
dl
rm
alternatives
37536
0755
edit
dl
rm
anacron
41976
0755
edit
dl
rm
apachectl
4804
0755
edit
dl
rm
applygnupgdefaults
2217
0755
edit
dl
rm
arp
66264
0755
edit
dl
rm
arpd
112152
0755
edit
dl
rm
arping
29432
0755
edit
dl
rm
atd
33408
0755
edit
dl
rm
atrun
67
0755
edit
dl
rm
auditctl
46120
0755
edit
dl
rm
auditd
155368
0755
edit
dl
rm
augenrules
4142
0755
edit
dl
rm
aureport
125288
0755
edit
dl
rm
ausearch
133488
0755
edit
dl
rm
autrace
16936
0750
edit
dl
rm
avcstat
16792
0755
edit
dl
rm
badblocks
33368
0755
edit
dl
rm
biosdecode
21960
0755
edit
dl
rm
blkdeactivate
16351
0555
edit
dl
rm
blkdiscard
29752
0755
edit
dl
rm
blkid
101024
0755
edit
dl
rm
blkmapd
54752
0755
edit
dl
rm
blkzone
50944
0755
edit
dl
rm
blockdev
42296
0755
edit
dl
rm
bridge
162048
0755
edit
dl
rm
capsh
33224
0755
edit
dl
rm
cfdisk
100768
0755
edit
dl
rm
cgdisk
211504
0755
edit
dl
rm
chcpu
29520
0755
edit
dl
rm
chgpasswd
71360
0755
edit
dl
rm
chkconfig
46192
0755
edit
dl
rm
chpasswd
62896
0755
edit
dl
rm
chronyd
384672
0755
edit
dl
rm
chroot
42448
0755
edit
dl
rm
clock
66784
0755
edit
dl
rm
clockdiff
20920
0755
edit
dl
rm
consoletype
12144
0755
edit
dl
rm
convertquota
80568
0755
edit
dl
rm
cracklib-check
13360
0755
edit
dl
rm
cracklib-format
251
0755
edit
dl
rm
cracklib-packer
13368
0755
edit
dl
rm
cracklib-unpacker
9248
0755
edit
dl
rm
create-cracklib-dict
990
0755
edit
dl
rm
crond
75712
0755
edit
dl
rm
csf
250979
0700
edit
dl
rm
ctrlaltdel
25384
0755
edit
dl
rm
ctstat
25936
0755
edit
dl
rm
dcb
158760
0755
edit
dl
rm
ddns-confgen
20952
0755
edit
dl
rm
debugfs
237184
0755
edit
dl
rm
delpart
25456
0755
edit
dl
rm
depmod
163784
0755
edit
dl
rm
devlink
221048
0755
edit
dl
rm
dhclient
464568
0755
edit
dl
rm
dhclient-script
33646
0755
edit
dl
rm
dmfilemapd
25136
0555
edit
dl
rm
dmidecode
145208
0755
edit
dl
rm
dmsetup
162448
0555
edit
dl
rm
dmstats
162448
0555
edit
dl
rm
dnssec-checkds
936
0755
edit
dl
rm
dnssec-coverage
938
0755
edit
dl
rm
dnssec-dsfromkey
62304
0755
edit
dl
rm
dnssec-importkey
62296
0755
edit
dl
rm
dnssec-keyfromlabel
66312
0755
edit
dl
rm
dnssec-keygen
74584
0755
edit
dl
rm
dnssec-keymgr
934
0755
edit
dl
rm
dnssec-revoke
58104
0755
edit
dl
rm
dnssec-settime
62304
0755
edit
dl
rm
dnssec-signzone
120016
0755
edit
dl
rm
dnssec-verify
54112
0755
edit
dl
rm
dosfsck
66688
0755
edit
dl
rm
dosfslabel
62568
0755
edit
dl
rm
dovecot
166072
0755
edit
dl
rm
dovecot_cpshutdown
3344
0755
edit
dl
rm
dpkg-fsys-usrunmess
12399
0755
edit
dl
rm
dumpe2fs
33296
0755
edit
dl
rm
e2freefrag
16816
0755
edit
dl
rm
e2fsck
336400
0755
edit
dl
rm
e2image
37488
0755
edit
dl
rm
e2label
113280
0755
edit
dl
rm
e2mmpstatus
33296
0755
edit
dl
rm
e2undo
20864
0755
edit
dl
rm
e4crypt
25136
0755
edit
dl
rm
e4defrag
29176
0755
edit
dl
rm
ebtables
226104
0755
edit
dl
rm
ebtables-restore
226104
0755
edit
dl
rm
ebtables-save
226104
0755
edit
dl
rm
edquota
93432
0755
edit
dl
rm
efibootdump
21016
0755
edit
dl
rm
efibootmgr
42992
0755
edit
dl
rm
ether-wake
75768
0755
edit
dl
rm
ethtool
571176
0755
edit
dl
rm
exicyclog
11366
0755
edit
dl
rm
exigrep
11711
0755
edit
dl
rm
exim
1604744
4755
edit
dl
rm
eximstats
152720
0755
edit
dl
rm
exim_checkaccess
4944
0755
edit
dl
rm
exim_dbmbuild
25280
0755
edit
dl
rm
exim_dumpdb
44608
0755
edit
dl
rm
exim_fixdb
50224
0755
edit
dl
rm
exim_lock
27232
0755
edit
dl
rm
exim_tidydb
44832
0755
edit
dl
rm
exinext
8218
0755
edit
dl
rm
exiqgrep
6740
0755
edit
dl
rm
exiqsumm
6444
0755
edit
dl
rm
exiwhat
4525
0755
edit
dl
rm
exportfs
84352
0755
edit
dl
rm
faillock
21016
0755
edit
dl
rm
fatlabel
62568
0755
edit
dl
rm
fcgistarter
17520
0755
edit
dl
rm
fdformat
33968
0755
edit
dl
rm
fdisk
134048
0755
edit
dl
rm
filefrag
16856
0755
edit
dl
rm
findfs
12672
0755
edit
dl
rm
firewalld
7088
0755
edit
dl
rm
fix-info-dir
8033
0755
edit
dl
rm
fixfiles
10727
0755
edit
dl
rm
fixparts
76712
0755
edit
dl
rm
fsck
54752
0755
edit
dl
rm
fsck.cramfs
42408
0755
edit
dl
rm
fsck.ext2
336400
0755
edit
dl
rm
fsck.ext3
336400
0755
edit
dl
rm
fsck.ext4
336400
0755
edit
dl
rm
fsck.fat
66688
0755
edit
dl
rm
fsck.minix
101120
0755
edit
dl
rm
fsck.msdos
66688
0755
edit
dl
rm
fsck.vfat
66688
0755
edit
dl
rm
fsck.xfs
1968
0755
edit
dl
rm
fsfreeze
16776
0755
edit
dl
rm
fstrim
50792
0755
edit
dl
rm
fuse2fs
72080
0755
edit
dl
rm
fuser
39056
0755
edit
dl
rm
g13-syshelp
194312
0755
edit
dl
rm
gdisk
219608
0755
edit
dl
rm
genhomedircon
29976
0755
edit
dl
rm
genhostid
12144
0755
edit
dl
rm
genl
124320
0755
edit
dl
rm
genrandom
12672
0755
edit
dl
rm
getcap
12648
0755
edit
dl
rm
getenforce
8024
0755
edit
dl
rm
getpcaps
12568
0755
edit
dl
rm
getsebool
12152
0755
edit
dl
rm
groupadd
97632
0755
edit
dl
rm
groupdel
93280
0755
edit
dl
rm
groupmems
62960
0755
edit
dl
rm
groupmod
101760
0755
edit
dl
rm
grpck
62944
0755
edit
dl
rm
grpconv
58640
0755
edit
dl
rm
grpunconv
58632
0755
edit
dl
rm
grub2-bios-setup
1213984
0755
edit
dl
rm
grub2-get-kernel-settings
2742
0755
edit
dl
rm
grub2-install
1511464
0755
edit
dl
rm
grub2-macbless
1192728
0755
edit
dl
rm
grub2-mkconfig
8888
0755
edit
dl
rm
grub2-ofpathname
252224
0755
edit
dl
rm
grub2-probe
1213928
0755
edit
dl
rm
grub2-reboot
4085
0755
edit
dl
rm
grub2-rpm-sort
289936
0755
edit
dl
rm
grub2-set-bootflag
16744
0755
edit
dl
rm
grub2-set-default
3535
0755
edit
dl
rm
grub2-set-password
3119
0755
edit
dl
rm
grub2-setpassword
3119
0755
edit
dl
rm
grub2-sparc64-setup
1218120
0755
edit
dl
rm
grub2-switch-to-blscfg
8809
0755
edit
dl
rm
grubby
260
0755
edit
dl
rm
gss-server
25200
0755
edit
dl
rm
gssproxy
135248
0755
edit
dl
rm
halt
223696
0755
edit
dl
rm
hardlink
17496
0755
edit
dl
rm
hdparm
135080
0755
edit
dl
rm
htcacheclean
45424
0755
edit
dl
rm
httpd
1015256
0755
edit
dl
rm
hwclock
66784
0755
edit
dl
rm
iconvconfig
33840
0755
edit
dl
rm
ifconfig
82800
0755
edit
dl
rm
ifdown
2123
0755
edit
dl
rm
ifenslave
25544
0755
edit
dl
rm
ifstat
120496
0755
edit
dl
rm
ifup
5463
0755
edit
dl
rm
imunify-notifier
10293320
0755
edit
dl
rm
init
1613656
0755
edit
dl
rm
insmod
163784
0755
edit
dl
rm
install-info
51432
0755
edit
dl
rm
installkernel
323
0755
edit
dl
rm
intel_sdsi
15992
0755
edit
dl
rm
ip
709944
0755
edit
dl
rm
ip6tables
226104
0755
edit
dl
rm
ip6tables-apply
7052
0755
edit
dl
rm
ip6tables-restore
226104
0755
edit
dl
rm
ip6tables-restore-translate
226104
0755
edit
dl
rm
ip6tables-save
226104
0755
edit
dl
rm
ip6tables-translate
226104
0755
edit
dl
rm
ipmaddr
21504
0755
edit
dl
rm
ipset
9224
0755
edit
dl
rm
iptables
226104
0755
edit
dl
rm
iptables-apply
7052
0755
edit
dl
rm
iptables-restore
226104
0755
edit
dl
rm
iptables-restore-translate
226104
0755
edit
dl
rm
iptables-save
226104
0755
edit
dl
rm
iptables-translate
226104
0755
edit
dl
rm
iptunnel
25600
0755
edit
dl
rm
irqbalance
63776
0755
edit
dl
rm
irqbalance-ui
42280
0755
edit
dl
rm
isc-hmac-fixup
12144
0755
edit
dl
rm
kexec
199656
0755
edit
dl
rm
key.dns_resolver
25104
0755
edit
dl
rm
kpartx
50232
0755
edit
dl
rm
lchage
16800
0755
edit
dl
rm
ldattach
33784
0755
edit
dl
rm
ldconfig
1009768
0755
edit
dl
rm
lfd
391629
0700
edit
dl
rm
lgroupadd
12160
0755
edit
dl
rm
lgroupdel
12160
0755
edit
dl
rm
lgroupmod
20352
0755
edit
dl
rm
lid
16664
0755
edit
dl
rm
lnewusers
20344
0755
edit
dl
rm
lnstat
25936
0755
edit
dl
rm
load_policy
12576
0755
edit
dl
rm
logrotate
95264
0755
edit
dl
rm
logsave
16800
0755
edit
dl
rm
losetup
92768
0755
edit
dl
rm
lpasswd
20840
0755
edit
dl
rm
lshw
992824
0755
edit
dl
rm
lsmod
163784
0755
edit
dl
rm
lspci
97128
0755
edit
dl
rm
luseradd
20352
0755
edit
dl
rm
luserdel
16256
0755
edit
dl
rm
lusermod
20360
0755
edit
dl
rm
lwresd
861120
0755
edit
dl
rm
makedumpfile
435392
0755
edit
dl
rm
mariadbd
29594424
0755
edit
dl
rm
matchpathcon
12664
0755
edit
dl
rm
mdadm
635648
0755
edit
dl
rm
mdmon
388616
0755
edit
dl
rm
mii-diag
26008
0755
edit
dl
rm
mii-tool
21536
0755
edit
dl
rm
mkdict
251
0755
edit
dl
rm
mkdosfs
40008
0755
edit
dl
rm
mkdumprd
12980
0755
edit
dl
rm
mke2fs
141768
0755
edit
dl
rm
mkfadumprd
2288
0755
edit
dl
rm
mkfs
16872
0755
edit
dl
rm
mkfs.cramfs
42256
0755
edit
dl
rm
mkfs.ext2
141768
0755
edit
dl
rm
mkfs.ext3
141768
0755
edit
dl
rm
mkfs.ext4
141768
0755
edit
dl
rm
mkfs.fat
40008
0755
edit
dl
rm
mkfs.minix
88640
0755
edit
dl
rm
mkfs.msdos
40008
0755
edit
dl
rm
mkfs.vfat
40008
0755
edit
dl
rm
mkfs.xfs
487408
0755
edit
dl
rm
mkhomedir_helper
25024
0755
edit
dl
rm
mklost+found
12144
0755
edit
dl
rm
mksquashfs
191312
0755
edit
dl
rm
mkswap
88552
0755
edit
dl
rm
modinfo
163784
0755
edit
dl
rm
modprobe
163784
0755
edit
dl
rm
modsec-sdbm-util
26448
0750
edit
dl
rm
mount.nfs
201976
0755
edit
dl
rm
mount.nfs4
201976
0755
edit
dl
rm
mountstats
43237
0755
edit
dl
rm
mysqld
29594424
0755
edit
dl
rm
named
861120
0755
edit
dl
rm
named-checkconf
41768
0755
edit
dl
rm
named-checkzone
37512
0755
edit
dl
rm
named-compilezone
37512
0755
edit
dl
rm
named-journalprint
12136
0755
edit
dl
rm
nameif
17384
0755
edit
dl
rm
NetworkManager
3579464
0755
edit
dl
rm
newusers
109800
0755
edit
dl
rm
nfsconf
38376
0755
edit
dl
rm
nfsconvert
13347
0755
edit
dl
rm
nfsdcld
67448
0755
edit
dl
rm
nfsdclddb
10242
0755
edit
dl
rm
nfsdclnts
9233
0755
edit
dl
rm
nfsdcltrack
50976
0755
edit
dl
rm
nfsidmap
46448
0755
edit
dl
rm
nfsiostat
23922
0755
edit
dl
rm
nfsref
67376
0755
edit
dl
rm
nfsstat
36368
0755
edit
dl
rm
nft
24992
0755
edit
dl
rm
nologin
12152
0755
edit
dl
rm
nscd
160448
0755
edit
dl
rm
nsec3hash
12584
0755
edit
dl
rm
nstat
116296
0755
edit
dl
rm
ownership
12696
0755
edit
dl
rm
packer
13368
0755
edit
dl
rm
pam_console_apply
46280
0755
edit
dl
rm
pam_timestamp_check
12152
0755
edit
dl
rm
paperconfig
4170
0755
edit
dl
rm
parted
87656
0755
edit
dl
rm
partprobe
16784
0755
edit
dl
rm
partx
96768
0755
edit
dl
rm
pdns_server
6559744
0755
edit
dl
rm
pidof
17096
0755
edit
dl
rm
ping
67712
0755
edit
dl
rm
ping6
67712
0755
edit
dl
rm
pivot_root
12680
0755
edit
dl
rm
plipconfig
13016
0755
edit
dl
rm
poweroff
223696
0755
edit
dl
rm
prl_nettool
914896
0755
edit
dl
rm
pure-authd
19696
0755
edit
dl
rm
pure-certd
19600
0755
edit
dl
rm
pure-config.pl
4755
0755
edit
dl
rm
pure-ftpd
186440
0755
edit
dl
rm
pure-ftpwho
27472
0755
edit
dl
rm
pure-mrtginfo
11432
0755
edit
dl
rm
pure-quotacheck
19272
0755
edit
dl
rm
pure-uploadscript
19536
0755
edit
dl
rm
pwck
58640
0755
edit
dl
rm
pwconv
54376
0755
edit
dl
rm
pwhistory_helper
20920
0755
edit
dl
rm
pwunconv
54400
0755
edit
dl
rm
quot
80560
0755
edit
dl
rm
quotacheck
118528
0755
edit
dl
rm
quotaoff
85152
0755
edit
dl
rm
quotaon
85152
0755
edit
dl
rm
quotastats
16936
0755
edit
dl
rm
raid-check
3793
0755
edit
dl
rm
rcmysql
-
0
edit
dl
rm
rdisc
25136
0755
edit
dl
rm
rdma
191880
0755
edit
dl
rm
readprofile
21040
0755
edit
dl
rm
reboot
223696
0755
edit
dl
rm
repquota
85240
0755
edit
dl
rm
request-key
24968
0755
edit
dl
rm
resize2fs
66472
0755
edit
dl
rm
resizepart
42568
0755
edit
dl
rm
resolvconf
200448
0755
edit
dl
rm
restorecon
21024
0755
edit
dl
rm
restorecon_xattr
16808
0755
edit
dl
rm
rfkill
54744
0755
edit
dl
rm
rmmod
163784
0755
edit
dl
rm
rndc
37408
0755
edit
dl
rm
rndc-confgen
20936
0755
edit
dl
rm
rotatelogs
31240
0755
edit
dl
rm
route
69248
0755
edit
dl
rm
rpc.gssd
109096
0755
edit
dl
rm
rpc.idmapd
63216
0755
edit
dl
rm
rpc.mountd
166952
0755
edit
dl
rm
rpc.nfsd
51120
0755
edit
dl
rm
rpc.statd
105776
0755
edit
dl
rm
rpcbind
63024
0755
edit
dl
rm
rpcctl
9631
0755
edit
dl
rm
rpcdebug
19840
0755
edit
dl
rm
rpcinfo
33424
0755
edit
dl
rm
rsyslogd
742120
0755
edit
dl
rm
rtacct
48064
0755
edit
dl
rm
rtcwake
50488
0755
edit
dl
rm
rtmon
120080
0755
edit
dl
rm
rtstat
25936
0755
edit
dl
rm
runlevel
223696
0755
edit
dl
rm
runq
1604744
4755
edit
dl
rm
runuser
50168
0755
edit
dl
rm
sasldblistusers2
21264
0755
edit
dl
rm
saslpasswd2
16816
0755
edit
dl
rm
sefcontext_compile
66920
0755
edit
dl
rm
selabel_digest
12576
0755
edit
dl
rm
selabel_lookup
12568
0755
edit
dl
rm
selabel_lookup_best_match
12176
0755
edit
dl
rm
selabel_partial_match
12168
0755
edit
dl
rm
selinuxconlist
12160
0755
edit
dl
rm
selinuxdefcon
12160
0755
edit
dl
rm
selinuxenabled
8024
0755
edit
dl
rm
selinuxexeccon
12144
0755
edit
dl
rm
selinux_check_access
12656
0755
edit
dl
rm
semodule
29976
0755
edit
dl
rm
sendmail
17320
2755
edit
dl
rm
service
3729
0755
edit
dl
rm
sestatus
20904
0755
edit
dl
rm
setcap
16664
0755
edit
dl
rm
setenforce
12560
0755
edit
dl
rm
setfiles
21024
0755
edit
dl
rm
setpci
29248
0755
edit
dl
rm
setquota
93568
0755
edit
dl
rm
setsebool
16768
0755
edit
dl
rm
sfdisk
121352
0755
edit
dl
rm
sgdisk
202800
0755
edit
dl
rm
showmount
21568
0755
edit
dl
rm
shutdown
223696
0755
edit
dl
rm
sim_server
12152
0755
edit
dl
rm
skdump
17320
0755
edit
dl
rm
sktest
13120
0755
edit
dl
rm
slattach
44808
0755
edit
dl
rm
sm-notify
80008
0755
edit
dl
rm
smartctl
928848
0755
edit
dl
rm
smartd
750800
0755
edit
dl
rm
ss
195888
0755
edit
dl
rm
sshd
890568
0755
edit
dl
rm
sssd
74760
0755
edit
dl
rm
sss_cache
62560
0755
edit
dl
rm
start-statd
838
0755
edit
dl
rm
start-stop-daemon
47088
0755
edit
dl
rm
suexec
25904
4755
edit
dl
rm
sulogin
50424
0755
edit
dl
rm
sw-engine-fpm
21096208
0755
edit
dl
rm
swaplabel
16896
0755
edit
dl
rm
swapoff
21248
0755
edit
dl
rm
swapon
50592
0755
edit
dl
rm
switch_root
16888
0755
edit
dl
rm
sysctl
29568
0755
edit
dl
rm
syspurpose
415
0755
edit
dl
rm
tcpdump
1057072
0755
edit
dl
rm
tcpslice
33416
0755
edit
dl
rm
tcsd
317152
0755
edit
dl
rm
telinit
223696
0755
edit
dl
rm
timedatex
34232
0755
edit
dl
rm
tipc
166984
0755
edit
dl
rm
tmpwatch
36320
0755
edit
dl
rm
tracepath
20928
0755
edit
dl
rm
tracepath6
20928
0755
edit
dl
rm
tsig-keygen
20952
0755
edit
dl
rm
tune2fs
113280
0755
edit
dl
rm
tuned
3977
0755
edit
dl
rm
tuned-adm
6661
0755
edit
dl
rm
udevadm
434752
0755
edit
dl
rm
umount.nfs
201976
0755
edit
dl
rm
umount.nfs4
201976
0755
edit
dl
rm
umount.udisks2
12176
0755
edit
dl
rm
unbound-anchor
58712
0755
edit
dl
rm
unix_chkpwd
37744
0755
edit
dl
rm
unix_update
37744
0700
edit
dl
rm
unsquashfs
101960
0755
edit
dl
rm
update-alternatives
37536
0755
edit
dl
rm
update-pciids
1753
0755
edit
dl
rm
update-smart-drivedb
14782
0755
edit
dl
rm
useradd
151720
0755
edit
dl
rm
userdel
109864
0755
edit
dl
rm
usermod
147568
0755
edit
dl
rm
usernetctl
12704
0755
edit
dl
rm
uuserver
16256
0755
edit
dl
rm
vdpa
120872
0755
edit
dl
rm
vigr
69688
0755
edit
dl
rm
vipw
69688
0755
edit
dl
rm
virt-what
14558
0755
edit
dl
rm
visudo
245024
0755
edit
dl
rm
vmcore-dmesg
29264
0755
edit
dl
rm
vpddecode
16864
0755
edit
dl
rm
weak-modules
34410
0755
edit
dl
rm
whmapi0
3496912
0755
edit
dl
rm
whmapi1
3496912
0755
edit
dl
rm
whmlogin
2390
0755
edit
dl
rm
wipefs
42104
0755
edit
dl
rm
xfs_admin
1415
0755
edit
dl
rm
xfs_bmap
695
0755
edit
dl
rm
xfs_copy
445016
0755
edit
dl
rm
xfs_db
778720
0755
edit
dl
rm
xfs_estimate
12688
0755
edit
dl
rm
xfs_freeze
800
0755
edit
dl
rm
xfs_fsr
54688
0755
edit
dl
rm
xfs_growfs
432616
0755
edit
dl
rm
xfs_info
1287
0755
edit
dl
rm
xfs_io
192800
0755
edit
dl
rm
xfs_logprint
465616
0755
edit
dl
rm
xfs_mdrestore
419928
0755
edit
dl
rm
xfs_metadump
782
0755
edit
dl
rm
xfs_mkfile
1040
0755
edit
dl
rm
xfs_ncheck
685
0755
edit
dl
rm
xfs_quota
96232
0755
edit
dl
rm
xfs_repair
732408
0755
edit
dl
rm
xfs_rtcp
16768
0755
edit
dl
rm
xfs_spaceman
46512
0755
edit
dl
rm
xqmstats
16848
0755
edit
dl
rm
xtables-monitor
226104
0755
edit
dl
rm
xtables-nft-multi
226104
0755
edit
dl
rm
zdump
21056
0755
edit
dl
rm
zic
54096
0755
edit
dl
rm
zramctl
101504
0755
edit
dl
rm
Edit:
/usr/sbin/mountstats
(43237B)
#!/usr/libexec/platform-python # -*- python-mode -*- """Parse /proc/self/mountstats and display it in human readable form """ from __future__ import print_function __copyright__ = """ Copyright (C) 2005, Chuck Lever <cel@netapp.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """ import sys, os, time from operator import itemgetter, add try: import argparse except ImportError: print('%s: Failed to import argparse - make sure argparse is installed!' % sys.argv[0]) sys.exit(1) Mountstats_version = '0.3' def difference(x, y): """Used for a map() function """ return x - y NfsEventCounters = [ 'inoderevalidates', 'dentryrevalidates', 'datainvalidates', 'attrinvalidates', 'vfsopen', 'vfslookup', 'vfspermission', 'vfsupdatepage', 'vfsreadpage', 'vfsreadpages', 'vfswritepage', 'vfswritepages', 'vfsreaddir', 'vfssetattr', 'vfsflush', 'vfsfsync', 'vfslock', 'vfsrelease', 'congestionwait', 'setattrtrunc', 'extendwrite', 'sillyrenames', 'shortreads', 'shortwrites', 'delay', 'pnfsreads', 'pnfswrites' ] NfsByteCounters = [ 'normalreadbytes', 'normalwritebytes', 'directreadbytes', 'directwritebytes', 'serverreadbytes', 'serverwritebytes', 'readpages', 'writepages' ] XprtUdpCounters = [ 'port', 'bind_count', 'rpcsends', 'rpcreceives', 'badxids', 'inflightsends', 'backlogutil', 'maxslots', 'sendutil', 'pendutil' ] XprtTcpCounters = [ 'port', 'bind_count', 'connect_count', 'connect_time', 'idle_time', 'rpcsends', 'rpcreceives', 'badxids', 'inflightsends', 'backlogutil', 'maxslots', 'sendutil', 'pendutil' ] XprtRdmaCounters = [ 'port', 'bind_count', 'connect_count', 'connect_time', 'idle_time', 'rpcsends', 'rpcreceives', 'badxids', 'inflightsends', 'backlogutil', 'read_segments', 'write_segments', 'reply_segments', 'total_rdma_req', 'total_rdma_rep', 'pullup', 'fixup', 'hardway', 'failed_marshal', 'bad_reply', 'nomsg_calls', 'recovered_mrs', 'orphaned_mrs', 'allocated_mrs', 'local_invalidates', 'empty_sendctx_q', 'reply_waits_for_send', ] Nfsv3ops = [ 'NULL', 'GETATTR', 'SETATTR', 'LOOKUP', 'ACCESS', 'READLINK', 'READ', 'WRITE', 'CREATE', 'MKDIR', 'SYMLINK', 'MKNOD', 'REMOVE', 'RMDIR', 'RENAME', 'LINK', 'READDIR', 'READDIRPLUS', 'FSSTAT', 'FSINFO', 'PATHCONF', 'COMMIT' ] # This list should be kept in-sync with the NFSPROC4_CLNT_* enum in # include/linux/nfs4.h in the kernel. Nfsv4ops = [ 'NULL', 'READ', 'WRITE', 'COMMIT', 'OPEN', 'OPEN_CONFIRM', 'OPEN_NOATTR', 'OPEN_DOWNGRADE', 'CLOSE', 'SETATTR', 'FSINFO', 'RENEW', 'SETCLIENTID', 'SETCLIENTID_CONFIRM', 'LOCK', 'LOCKT', 'LOCKU', 'ACCESS', 'GETATTR', 'LOOKUP', 'LOOKUP_ROOT', 'REMOVE', 'RENAME', 'LINK', 'SYMLINK', 'CREATE', 'PATHCONF', 'STATFS', 'READLINK', 'READDIR', 'SERVER_CAPS', 'DELEGRETURN', 'GETACL', 'SETACL', 'FS_LOCATIONS', 'RELEASE_LOCKOWNER', 'SECINFO', 'FSID_PRESENT', 'EXCHANGE_ID', 'CREATE_SESSION', 'DESTROY_SESSION', 'SEQUENCE', 'GET_LEASE_TIME', 'RECLAIM_COMPLETE', 'LAYOUTGET', 'GETDEVICEINFO', 'LAYOUTCOMMIT', 'LAYOUTRETURN', 'SECINFO_NO_NAME', 'TEST_STATEID', 'FREE_STATEID', 'GETDEVICELIST', 'BIND_CONN_TO_SESSION', 'DESTROY_CLIENTID', 'SEEK', 'ALLOCATE', 'DEALLOCATE', 'LAYOUTSTATS', 'CLONE' ] class DeviceData: """DeviceData objects provide methods for parsing and displaying data for a single mount grabbed from /proc/self/mountstats """ def __init__(self): self.__nfs_data = dict() self.__rpc_data = dict() self.__rpc_data['ops'] = [] def __parse_nfs_line(self, words): if words[0] == 'device': self.__nfs_data['export'] = words[1] self.__nfs_data['mountpoint'] = words[4] self.__nfs_data['fstype'] = words[7] if words[7].find('nfs') != -1 and words[7] != 'nfsd': 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].find('nfs') != -1 and words[6] != 'nfsd': self.__nfs_data['statvers'] = words[7] elif words[0] == 'age:': self.__nfs_data['age'] = int(words[1]) elif words[0] == 'opts:': self.__nfs_data['mountoptions'] = ''.join(words[1:]).split(',') elif words[0] == 'caps:': self.__nfs_data['servercapabilities'] = ''.join(words[1:]).split(',') elif words[0] == 'nfsv4:': self.__nfs_data['nfsv4flags'] = ''.join(words[1:]).split(',') elif words[0] == 'sec:': keys = ''.join(words[1:]).split(',') self.__nfs_data['flavor'] = int(keys[0].split('=')[1]) self.__nfs_data['pseudoflavor'] = 0 if self.__nfs_data['flavor'] == 6: self.__nfs_data['pseudoflavor'] = int(keys[1].split('=')[1]) elif words[0] == 'events:': i = 1 for key in NfsEventCounters: try: self.__nfs_data[key] = int(words[i]) except IndexError as err: self.__nfs_data[key] = 0 i += 1 elif words[0] == 'bytes:': i = 1 for key in NfsByteCounters: self.__nfs_data[key] = int(words[i]) i += 1 def __parse_rpc_line(self, words): if words[0] == 'RPC': self.__rpc_data['statsvers'] = float(words[3]) self.__rpc_data['programversion'] = words[5] elif words[0] == 'xprt:': self.__rpc_data['protocol'] = words[1] if words[1] == 'udp': i = 2 for key in XprtUdpCounters: if i < len(words): self.__rpc_data[key] = int(words[i]) i += 1 elif words[1] == 'tcp': i = 2 for key in XprtTcpCounters: if i < len(words): self.__rpc_data[key] = int(words[i]) i += 1 elif words[1] == 'rdma': i = 2 for key in XprtRdmaCounters: if i < len(words): self.__rpc_data[key] = int(words[i]) i += 1 elif words[0] == 'per-op': self.__rpc_data['per-op'] = words else: op = words[0][:-1] self.__rpc_data['ops'] += [op] self.__rpc_data[op] = [int(word) for word in words[1:]] if len(self.__rpc_data[op]) < 9: self.__rpc_data[op] += [0] def parse_stats(self, lines): """Turn a list of lines from a mount stat file into a dictionary full of stats, keyed by name """ found = False for line in lines: words = line.split() if len(words) == 0: continue if (not found and words[0] != 'RPC'): self.__parse_nfs_line(words) continue 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 """ if self.__nfs_data['fstype'] == 'nfs': return True elif self.__nfs_data['fstype'] == 'nfs4': return True return False def nfs_version(self): if self.is_nfs_mountpoint(): prog, vers = self.__rpc_data['programversion'].split('/') return int(vers) def display_raw_stats(self): """Prints out stats in the same format as /proc/self/mountstats """ print('device %s mounted on %s with fstype %s %s' % \ (self.__nfs_data['export'], self.__nfs_data['mountpoint'], \ self.__nfs_data['fstype'], self.__nfs_data['statvers'])) print('\topts:\t%s' % ','.join(self.__nfs_data['mountoptions'])) print('\tage:\t%d' % self.__nfs_data['age']) print('\tcaps:\t%s' % ','.join(self.__nfs_data['servercapabilities'])) print('\tsec:\tflavor=%d,pseudoflavor=%d' % (self.__nfs_data['flavor'], \ self.__nfs_data['pseudoflavor'])) print('\tevents:\t%s' % " ".join([str(self.__nfs_data[key]) for key in NfsEventCounters])) print('\tbytes:\t%s' % " ".join([str(self.__nfs_data[key]) for key in NfsByteCounters])) print('\tRPC iostats version: %1.1f p/v: %s (nfs)' % (self.__rpc_data['statsvers'], \ self.__rpc_data['programversion'])) if self.__rpc_data['protocol'] == 'udp': print('\txprt:\tudp %s' % " ".join([str(self.__rpc_data[key]) for key in XprtUdpCounters])) elif self.__rpc_data['protocol'] == 'tcp': print('\txprt:\ttcp %s' % " ".join([str(self.__rpc_data[key]) for key in XprtTcpCounters])) elif self.__rpc_data['protocol'] == 'rdma': print('\txprt:\trdma %s' % " ".join([str(self.__rpc_data[key]) for key in XprtRdmaCounters])) else: raise Exception('Unknown RPC transport protocol %s' % self.__rpc_data['protocol']) print('\tper-op statistics') prog, vers = self.__rpc_data['programversion'].split('/') if vers == '3': for op in Nfsv3ops: print('\t%12s: %s' % (op, " ".join(str(x) for x in self.__rpc_data[op]))) elif vers == '4': for op in Nfsv4ops: print('\t%12s: %s' % (op, " ".join(str(x) for x in self.__rpc_data[op]))) else: print('\tnot implemented for version %d' % vers) print() def display_stats_header(self): print('Stats for %s mounted on %s:' % \ (self.__nfs_data['export'], self.__nfs_data['mountpoint'])) print() def display_nfs_options(self): """Pretty-print the NFS options """ print(' NFS mount options: %s' % ','.join(self.__nfs_data['mountoptions'])) print(' NFS server capabilities: %s' % ','.join(self.__nfs_data['servercapabilities'])) if 'nfsv4flags' in self.__nfs_data: print(' NFSv4 capability flags: %s' % ','.join(self.__nfs_data['nfsv4flags'])) if 'pseudoflavor' in self.__nfs_data: print(' NFS security flavor: %d pseudoflavor: %d' % \ (self.__nfs_data['flavor'], self.__nfs_data['pseudoflavor'])) else: print(' NFS security flavor: %d' % self.__nfs_data['flavor']) def display_nfs_events(self): """Pretty-print the NFS event counters """ print() print('Cache events:') print(' data cache invalidated %d times' % self.__nfs_data['datainvalidates']) print(' attribute cache invalidated %d times' % self.__nfs_data['attrinvalidates']) print() print('VFS calls:') print(' VFS requested %d inode revalidations' % self.__nfs_data['inoderevalidates']) print(' VFS requested %d dentry revalidations' % self.__nfs_data['dentryrevalidates']) print() print(' VFS called nfs_readdir() %d times' % self.__nfs_data['vfsreaddir']) print(' VFS called nfs_lookup() %d times' % self.__nfs_data['vfslookup']) print(' VFS called nfs_permission() %d times' % self.__nfs_data['vfspermission']) print(' VFS called nfs_file_open() %d times' % self.__nfs_data['vfsopen']) print(' VFS called nfs_file_flush() %d times' % self.__nfs_data['vfsflush']) print(' VFS called nfs_lock() %d times' % self.__nfs_data['vfslock']) print(' VFS called nfs_fsync() %d times' % self.__nfs_data['vfsfsync']) print(' VFS called nfs_file_release() %d times' % self.__nfs_data['vfsrelease']) print() print('VM calls:') print(' VFS called nfs_readpage() %d times' % self.__nfs_data['vfsreadpage']) print(' VFS called nfs_readpages() %d times' % self.__nfs_data['vfsreadpages']) print(' VFS called nfs_writepage() %d times' % self.__nfs_data['vfswritepage']) print(' VFS called nfs_writepages() %d times' % self.__nfs_data['vfswritepages']) print() print('Generic NFS counters:') print(' File size changing operations:') print(' truncating SETATTRs: %d extending WRITEs: %d' % \ (self.__nfs_data['setattrtrunc'], self.__nfs_data['extendwrite'])) print(' %d silly renames' % self.__nfs_data['sillyrenames']) print(' short reads: %d short writes: %d' % \ (self.__nfs_data['shortreads'], self.__nfs_data['shortwrites'])) print(' NFSERR_DELAYs from server: %d' % self.__nfs_data['delay']) print(' pNFS READs: %d' % self.__nfs_data['pnfsreads']) print(' pNFS WRITEs: %d' % self.__nfs_data['pnfswrites']) def display_nfs_bytes(self): """Pretty-print the NFS event counters """ print() print('NFS byte counts:') print(' applications read %d bytes via read(2)' % self.__nfs_data['normalreadbytes']) print(' applications wrote %d bytes via write(2)' % self.__nfs_data['normalwritebytes']) print(' applications read %d bytes via O_DIRECT read(2)' % self.__nfs_data['directreadbytes']) print(' applications wrote %d bytes via O_DIRECT write(2)' % self.__nfs_data['directwritebytes']) print(' client read %d bytes via NFS READ' % self.__nfs_data['serverreadbytes']) print(' client wrote %d bytes via NFS WRITE' % self.__nfs_data['serverwritebytes']) def display_rpc_generic_stats(self): """Pretty-print the generic RPC stats """ sends = self.__rpc_data['rpcsends'] print('RPC statistics:') print(' %d RPC requests sent, %d RPC replies received (%d XIDs not found)' % \ (sends, self.__rpc_data['rpcreceives'], self.__rpc_data['badxids'])) if sends != 0: print(' average backlog queue length: %d' % \ (float(self.__rpc_data['backlogutil']) / sends)) def display_rpc_op_stats(self): """Pretty-print the per-op stats """ sends = self.__rpc_data['rpcsends'] allstats = [] for op in self.__rpc_data['ops']: allstats.append([op] + self.__rpc_data[op]) print() for stats in sorted(allstats, key=itemgetter(1), reverse=True): count = stats[1] if count != 0: print('%s:' % stats[0]) print('\t%d ops (%d%%)' % \ (count, ((count * 100) / sends)), end=' ') retrans = stats[2] - count if retrans != 0: print('\t%d retrans (%d%%)' % (retrans, ((retrans * 100) / count)), end=' ') print('\t%d major timeouts' % stats[3], end='') if len(stats) >= 10 and stats[9] != 0: print('\t%d errors (%d%%)' % (stats[9], ((stats[9] * 100) / count))) else: print('') print('\tavg bytes sent per op: %d\tavg bytes received per op: %d' % \ (stats[4] / count, stats[5] / count)) print('\tbacklog wait: %f' % (float(stats[6]) / count), end=' ') print('\tRTT: %f' % (float(stats[7]) / count), end=' ') print('\ttotal execute time: %f (milliseconds)' % \ (float(stats[8]) / count)) def client_rpc_stats(self): """Tally high-level rpc stats for the nfsstat command """ sends = 0 trans = 0 authrefrsh = 0 for op in self.__rpc_data['ops']: sends += self.__rpc_data[op][0] trans += self.__rpc_data[op][1] retrans = trans - sends # authrefresh stats don't actually get captured in # /proc/self/mountstats, so we fudge it here authrefrsh = sends return (sends, retrans, authrefrsh) def display_nfsstat_stats(self): """Pretty-print nfsstat-style stats """ sends = 0 for op in self.__rpc_data['ops']: sends += self.__rpc_data[op][0] if sends == 0: return print() vers = self.nfs_version() print('Client nfs v%d' % vers) info = [] for op in self.__rpc_data['ops']: print('%-13s' % str.lower(op)[:12], end='') count = self.__rpc_data[op][0] pct = (count * 100) / sends info.append((count, pct)) if (self.__rpc_data['ops'].index(op) + 1) % 6 == 0: print() for (count, pct) in info: print('%-8u%3u%% ' % (count, pct), end='') print() info = [] print() if len(info) > 0: for (count, pct) in info: print('%-8u%3u%% ' % (count, pct), end='') print() def compare_iostats(self, old_stats): """Return the difference between two sets of stats """ if old_stats.__nfs_data['age'] > self.__nfs_data['age']: return self result = DeviceData() protocol = self.__rpc_data['protocol'] # copy self into result for key, value in self.__nfs_data.items(): result.__nfs_data[key] = value for key, value in self.__rpc_data.items(): result.__rpc_data[key] = value # compute the difference of each item in the list # note the copy loop above does not copy the lists, just # the reference to them. so we build new lists here # for the result object. for op in result.__rpc_data['ops']: 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': for key in XprtUdpCounters: result.__rpc_data[key] -= old_stats.__rpc_data[key] elif protocol == 'tcp': for key in XprtTcpCounters: result.__rpc_data[key] -= old_stats.__rpc_data[key] elif protocol == 'rdma': for key in XprtRdmaCounters: result.__rpc_data[key] -= old_stats.__rpc_data[key] result.__nfs_data['age'] -= old_stats.__nfs_data['age'] for key in NfsEventCounters: result.__nfs_data[key] -= old_stats.__nfs_data[key] for key in NfsByteCounters: result.__nfs_data[key] -= old_stats.__nfs_data[key] return result def setup_accumulator(self, ops): """Initialize a DeviceData instance to tally stats for all mountpoints with the same major version. This is for the nfsstat command. """ if ops == Nfsv3ops: self.__rpc_data['programversion'] = '100003/3' self.__nfs_data['fstype'] = 'nfs' elif ops == Nfsv4ops: self.__rpc_data['programversion'] = '100003/4' self.__nfs_data['fstype'] = 'nfs4' self.__rpc_data['ops'] = ops for op in ops: self.__rpc_data[op] = [0 for i in range(9)] def accumulate_iostats(self, new_stats): """Accumulate counters from all RPC op buckets in new_stats. This is for the nfsstat command. """ for op in new_stats.__rpc_data['ops']: try: self.__rpc_data[op] = list(map(add, self.__rpc_data[op], new_stats.__rpc_data[op])) except KeyError: continue def __print_rpc_op_stats(self, op, sample_time): """Print generic stats for one RPC op """ if op not in self.__rpc_data: return rpc_stats = self.__rpc_data[op] ops = float(rpc_stats[0]) retrans = float(rpc_stats[1] - rpc_stats[0]) kilobytes = float(rpc_stats[3] + rpc_stats[4]) / 1024 queued_for = float(rpc_stats[5]) rtt = float(rpc_stats[6]) exe = float(rpc_stats[7]) if len(rpc_stats) >= 9: errs = int(rpc_stats[8]) # prevent floating point exceptions if ops != 0: kb_per_op = kilobytes / ops retrans_percent = (retrans * 100) / ops rtt_per_op = rtt / ops exe_per_op = exe / ops queued_for_per_op = queued_for / ops if len(rpc_stats) >= 9: errs_percent = (errs * 100) / ops else: kb_per_op = 0.0 retrans_percent = 0.0 rtt_per_op = 0.0 exe_per_op = 0.0 queued_for_per_op = 0.0 errs_percent = 0.0 op += ':' print(format(op.lower(), '<16s'), end='') print(format('ops/s', '>8s'), end='') print(format('kB/s', '>16s'), end='') print(format('kB/op', '>16s'), end='') print(format('retrans', '>16s'), end='') print(format('avg RTT (ms)', '>16s'), end='') print(format('avg exe (ms)', '>16s'), end='') print(format('avg queue (ms)', '>16s'), end='') if len(rpc_stats) >= 9: print(format('errors', '>16s'), end='') print() print(format((ops / sample_time), '>24.3f'), end='') print(format((kilobytes / sample_time), '>16.3f'), end='') print(format(kb_per_op, '>16.3f'), end='') retransmits = '{0:>10.0f} ({1:>3.1f}%)'.format(retrans, retrans_percent).strip() print(format(retransmits, '>16'), end='') print(format(rtt_per_op, '>16.3f'), end='') print(format(exe_per_op, '>16.3f'), end='') print(format(queued_for_per_op, '>16.3f'), end='') if len(rpc_stats) >= 9: errors = '{0:>10.0f} ({1:>3.1f}%)'.format(errs, errs_percent).strip() print(format(errors, '>16'), end='') print() def display_iostats(self, sample_time): """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: backlog = 0.0 print() print('%s mounted on %s:' % \ (self.__nfs_data['export'], self.__nfs_data['mountpoint'])) print() print(format('ops/s', '>16') + format('rpc bklog', '>16')) print(format((sends / sample_time), '>16.3f'), end='') print(format(backlog, '>16.3f')) print() self.__print_rpc_op_stats('READ', sample_time) self.__print_rpc_op_stats('WRITE', sample_time) sys.stdout.flush() def display_xprt_stats(self): """Pretty-print the xprt statistics """ if self.__rpc_data['protocol'] == 'udp': print('\tTransport protocol: udp') print('\tSource port: %d' % self.__rpc_data['port']) print('\tBind count: %d' % self.__rpc_data['bind_count']) print('\tRPC requests: %d' % self.__rpc_data['rpcsends']) print('\tRPC replies: %d' % self.__rpc_data['rpcreceives']) print('\tXIDs not found: %d' % self.__rpc_data['badxids']) print('\tMax slots: %d' % self.__rpc_data['maxslots']) if self.__rpc_data['rpcsends'] != 0: print('\tAvg backlog length: %d' % \ (float(self.__rpc_data['backlogutil']) / self.__rpc_data['rpcsends'])) print('\tAvg send queue length: %d' % \ (float(self.__rpc_data['sendutil']) / self.__rpc_data['rpcsends'])) print('\tAvg pending queue length: %d' % \ (float(self.__rpc_data['pendutil']) / self.__rpc_data['rpcsends'])) elif self.__rpc_data['protocol'] == 'tcp': print('\tTransport protocol: tcp') print('\tSource port: %d' % self.__rpc_data['port']) print('\tBind count: %d' % self.__rpc_data['bind_count']) print('\tConnect count: %d' % self.__rpc_data['connect_count']) print('\tConnect time: %d seconds' % self.__rpc_data['connect_time']) print('\tIdle time: %d seconds' % self.__rpc_data['idle_time']) print('\tRPC requests: %d' % self.__rpc_data['rpcsends']) print('\tRPC replies: %d' % self.__rpc_data['rpcreceives']) print('\tXIDs not found: %d' % self.__rpc_data['badxids']) print('\tMax slots: %d' % self.__rpc_data['maxslots']) if self.__rpc_data['rpcsends'] != 0: print('\tAvg backlog length: %d' % \ (float(self.__rpc_data['backlogutil']) / self.__rpc_data['rpcsends'])) print('\tAvg send queue length: %d' % \ (float(self.__rpc_data['sendutil']) / self.__rpc_data['rpcsends'])) print('\tAvg pending queue length: %d' % \ (float(self.__rpc_data['pendutil']) / self.__rpc_data['rpcsends'])) elif self.__rpc_data['protocol'] == 'rdma': print('\tTransport protocol: rdma') print('\tConnect count: %d' % self.__rpc_data['connect_count']) print('\tConnect time: %d seconds' % self.__rpc_data['connect_time']) print('\tIdle time: %d seconds' % self.__rpc_data['idle_time']) sends = self.__rpc_data['rpcsends'] print('\tRPC requests: %d' % self.__rpc_data['rpcsends']) print('\tRPC replies: %d' % self.__rpc_data['rpcreceives']) print('\tXIDs not found: %d' % self.__rpc_data['badxids']) if self.__rpc_data['rpcsends'] != 0: print('\tAvg backlog length: %d' % \ (float(self.__rpc_data['backlogutil']) / self.__rpc_data['rpcsends'])) print('\tRead segments: %d' % self.__rpc_data['read_segments']) print('\tWrite segments: %d' % self.__rpc_data['write_segments']) print('\tReply segments: %d' % self.__rpc_data['reply_segments']) print('\tRegistered: %d bytes' % self.__rpc_data['total_rdma_req']) print('\tRDMA received: %d bytes' % self.__rpc_data['total_rdma_rep']) print('\tTotal pull-up: %d bytes' % self.__rpc_data['pullup']) print('\tTotal fix-up: %d bytes' % self.__rpc_data['fixup']) print('\tHardway allocations: %d bytes' % self.__rpc_data['hardway']) print('\tFailed marshals: %d' % self.__rpc_data['failed_marshal']) print('\tBad replies: %d' % self.__rpc_data['bad_reply']) """ Counters not present in all kernels """ if 'nomsg_calls' in self.__rpc_data: print('\tRDMA_NOMSG calls: %d' % self.__rpc_data['nomsg_calls']) if 'allocated_mrs' in self.__rpc_data: print('\tAllocated MRs: %d' % self.__rpc_data['allocated_mrs']) if 'recovered_mrs' in self.__rpc_data: print('\tRecovered MRs: %d' % self.__rpc_data['recovered_mrs']) if 'orphaned_mrs' in self.__rpc_data: print('\tOrphaned MRs: %d' % self.__rpc_data['orphaned_mrs']) if 'local_invalidates' in self.__rpc_data: print('\tLocal Invalidates needed: %d' % self.__rpc_data['local_invalidates']) if 'empty_sendctx_q' in self.__rpc_data: print('\tEmpty sendctx queue count: %d' % self.__rpc_data['empty_sendctx_q']) if 'reply_waits_for_send' in self.__rpc_data: print('\tReplies that waited for Send completion: %d' % self.__rpc_data['reply_waits_for_send']) else: raise Exception('Unknown RPC transport protocol %s' % self.__rpc_data['protocol']) def parse_stats_file(f): """pop the contents of a mountstats file into a dictionary, keyed by mount point. each value object is a list of the lines in the mountstats file corresponding to the mount point named in the key. """ ms_dict = dict() key = '' f.seek(0) for line in f.readlines(): words = line.split() if len(words) == 0: continue 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 return ms_dict def print_mountstats(stats, nfs_only, rpc_only, raw, xprt_only): if nfs_only: stats.display_stats_header() stats.display_nfs_options() stats.display_nfs_events() stats.display_nfs_bytes() elif rpc_only: stats.display_stats_header() stats.display_rpc_generic_stats() stats.display_rpc_op_stats() elif raw: stats.display_raw_stats() elif xprt_only: stats.display_stats_header() stats.display_xprt_stats() else: stats.display_stats_header() stats.display_nfs_options() stats.display_nfs_bytes() stats.display_rpc_generic_stats() stats.display_rpc_op_stats() print() def mountstats_command(args): """Mountstats command """ mountstats = parse_stats_file(args.infile) mountpoints = [os.path.normpath(mp) for mp in args.mountpoints] # make certain devices contains only NFS mount points if len(mountpoints) > 0: check = [] for device in mountpoints: stats = DeviceData() try: stats.parse_stats(mountstats[device]) if stats.is_nfs_mountpoint(): check += [device] except KeyError: continue mountpoints = check else: for device, descr in mountstats.items(): stats = DeviceData() stats.parse_stats(descr) if stats.is_nfs_mountpoint(): mountpoints += [device] if len(mountpoints) == 0: print('No NFS mount points were found') return 1 if args.since: old_mountstats = parse_stats_file(args.since) for mp in mountpoints: stats = DeviceData() stats.parse_stats(mountstats[mp]) if not args.since: print_mountstats(stats, args.nfs_only, args.rpc_only, args.raw, args.xprt_only) elif args.since and mp not in old_mountstats: print_mountstats(stats, args.nfs_only, args.rpc_only, args.raw, args.xprt_only) else: old_stats = DeviceData() old_stats.parse_stats(old_mountstats[mp]) diff_stats = stats.compare_iostats(old_stats) print_mountstats(diff_stats, args.nfs_only, args.rpc_only, args.raw, args.xprt_only) args.infile.close() if args.since: args.since.close() return 0 def nfsstat_command(args): """nfsstat-like command for NFS mount points """ mountstats = parse_stats_file(args.infile) mountpoints = [os.path.normpath(mp) for mp in args.mountpoints] v3stats = DeviceData() v3stats.setup_accumulator(Nfsv3ops) v4stats = DeviceData() v4stats.setup_accumulator(Nfsv4ops) # ensure stats get printed if neither v3 nor v4 was specified if args.show_v3 or args.show_v4: show_both = False else: show_both = True # make certain devices contains only NFS mount points if len(mountpoints) > 0: check = [] for device in mountpoints: stats = DeviceData() try: stats.parse_stats(mountstats[device]) if stats.is_nfs_mountpoint(): check += [device] except KeyError: continue mountpoints = check else: for device, descr in mountstats.items(): stats = DeviceData() stats.parse_stats(descr) if stats.is_nfs_mountpoint(): mountpoints += [device] if len(mountpoints) == 0: print('No NFS mount points were found') return 1 if args.since: old_mountstats = parse_stats_file(args.since) for mp in mountpoints: stats = DeviceData() stats.parse_stats(mountstats[mp]) vers = stats.nfs_version() if not args.since: acc_stats = stats elif args.since and mp not in old_mountstats: acc_stats = stats else: old_stats = DeviceData() old_stats.parse_stats(old_mountstats[mp]) acc_stats = stats.compare_iostats(old_stats) if vers == 3 and (show_both or args.show_v3): v3stats.accumulate_iostats(acc_stats) elif vers == 4 and (show_both or args.show_v4): v4stats.accumulate_iostats(acc_stats) sends, retrans, authrefrsh = map(add, v3stats.client_rpc_stats(), v4stats.client_rpc_stats()) print('Client rpc stats:') print('calls retrans authrefrsh') print('%-11u%-11u%-11u' % (sends, retrans, authrefrsh)) if show_both or args.show_v3: v3stats.display_nfsstat_stats() if show_both or args.show_v4: v4stats.display_nfsstat_stats() args.infile.close() if args.since: args.since.close() 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 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) 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) origdevices = [os.path.normpath(mp) for mp in args.mountpoints] if args.since: old_mountstats = parse_stats_file(args.since) else: old_mountstats = None 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: return count = args.count while True: if count is not None: count -= 1 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: args.since.close() return 0 class ICMAction(argparse.Action): """Custom action to deal with interval, count, and mountpoints. """ def __call__(self, parser, namespace, values, option_string=None): if namespace.mountpoints is None: namespace.mountpoints = [] if values is None: return elif (type(values) == type([])): for value in values: self._handle_one(namespace, value) else: self._handle_one(namespace, values) def _handle_one(self, namespace, value): try: intval = int(value) if namespace.infile.name != '/proc/self/mountstats': raise argparse.ArgumentError(self, "not allowed with argument -f/--file or -S/--since") self._handle_int(namespace, intval) except ValueError: namespace.mountpoints.append(value) def _handle_int(self, namespace, value): if namespace.interval is None: namespace.interval = value elif namespace.count is None: namespace.count = value else: raise argparse.ArgumentError(self, "too many integer arguments") def main(): parser = argparse.ArgumentParser(epilog='For specific sub-command help, ' 'run \'mountstats SUB-COMMAND -h|--help\'') subparsers = parser.add_subparsers(help='sub-command help') common_parser = argparse.ArgumentParser(add_help=False) common_parser.add_argument('-v', '--version', action='version', version='mountstats ' + Mountstats_version) common_parser.add_argument('-f', '--file', default=open('/proc/self/mountstats', 'r'), type=argparse.FileType('r'), dest='infile', help='Read stats from %(dest)s instead of /proc/self/mountstats') common_parser.add_argument('-S', '--since', type=argparse.FileType('r'), metavar='SINCEFILE', help='Show difference between current stats and those in SINCEFILE') mountstats_parser = subparsers.add_parser('mountstats', parents=[common_parser], help='Display a combination of per-op RPC statistics, NFS event counts, and NFS byte counts. ' 'This is the default sub-command if no sub-command is given.') group = mountstats_parser.add_mutually_exclusive_group() group.add_argument('-n', '--nfs', action='store_true', dest='nfs_only', help='Display only the NFS statistics') group.add_argument('-r', '--rpc', action='store_true', dest='rpc_only', help='Display only the RPC statistics') group.add_argument('-R', '--raw', action='store_true', help='Display only the raw statistics') group.add_argument('-x', '--xprt', action='store_true', dest='xprt_only', help='Display only the xprt statistics') # The mountpoints argument cannot be moved into the common_parser because # it will screw up the parsing of the iostat arguments (interval and count) mountstats_parser.add_argument('mountpoints', nargs='*', metavar='mountpoint', help='Display statistics for this mountpoint. More than one may be specified. ' 'If absent, statistics for all NFS mountpoints will be generated.') mountstats_parser.set_defaults(func=mountstats_command) nfsstat_parser = subparsers.add_parser('nfsstat', parents=[common_parser], help='Display nfsstat-like statistics.') nfsstat_parser.add_argument('-3', action='store_true', dest='show_v3', help='Show NFS version 3 statistics') nfsstat_parser.add_argument('-4', action='store_true', dest='show_v4', help='Show NFS version 4 statistics') # The mountpoints argument cannot be moved into the common_parser because # it will screw up the parsing of the iostat arguments (interval and count) nfsstat_parser.add_argument('mountpoints', nargs='*', metavar='mountpoint', help='Display statistics for this mountpoint. More than one may be specified. ' 'If absent, statistics for all NFS mountpoints will be generated.') nfsstat_parser.set_defaults(func=nfsstat_command) iostat_parser = subparsers.add_parser('iostat', parents=[common_parser], help='Display iostat-like statistics.') iostat_parser.add_argument('interval', nargs='?', action=ICMAction, help='Number of seconds between reports. If absent, only one report will ' 'be generated.') iostat_parser.add_argument('count', nargs='?', action=ICMAction, help='Number of reports generated at <interval> seconds apart. If absent, ' 'reports will be generated continuously.') # The mountpoints argument cannot be moved into the common_parser because # it will screw up the parsing of the iostat arguments (interval and count) iostat_parser.add_argument('mountpoints', nargs='*', action=ICMAction, metavar='mountpoint', help='Display statsistics for this mountpoint. More than one may be specified. ' 'If absent, statistics for all NFS mountpoints will be generated.') iostat_parser.set_defaults(func=iostat_command) args = parser.parse_args() return args.func(args) try: if __name__ == '__main__': # Run the mounstats sub-command if no sub-command (or the help flag) # is given. If the argparse module ever gets support for optional # (default) sub-commands, then this can be changed. if len(sys.argv) == 1: sys.argv.insert(1, 'mountstats') elif sys.argv[1] not in ['-h', '--help', 'mountstats', 'iostat', 'nfsstat']: sys.argv.insert(1, 'mountstats') res = main() sys.stdout.close() sys.stderr.close() sys.exit(res) except (KeyboardInterrupt, RuntimeError): sys.exit(1) except IOError: pass
Save
cmd:
run