Isolate code specific to Linux in cmd/
Use sys.platform to choose the correct implementation of functions and values of variables for the platform being run on. Reword some comments to avoid describing implementation details in the wrong places. Reviewed-by: Kjeld Schouten <kjeld@schouten-lebbing.nl> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Jorgen Lundman <lundman@lundman.net> Signed-off-by: Ryan Moeller <ryan@ixsystems.com> Closes #9561
This commit is contained in:
parent
6c7023a532
commit
2f1ca8a32a
|
@ -5,4 +5,6 @@ if USING_PYTHON
|
||||||
SUBDIRS += arcstat arc_summary dbufstat
|
SUBDIRS += arcstat arc_summary dbufstat
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if BUILD_LINUX
|
||||||
SUBDIRS += mount_zfs zed zvol_id zvol_wait
|
SUBDIRS += mount_zfs zed zvol_id zvol_wait
|
||||||
|
endif
|
||||||
|
|
|
@ -55,6 +55,30 @@ from subprocess import Popen, PIPE
|
||||||
from decimal import Decimal as D
|
from decimal import Decimal as D
|
||||||
|
|
||||||
|
|
||||||
|
if sys.platform.startswith('linux'):
|
||||||
|
|
||||||
|
def load_kstats(namespace):
|
||||||
|
"""Collect information on a specific subsystem of the ARC"""
|
||||||
|
|
||||||
|
kstat = 'kstat.zfs.misc.%s.%%s' % namespace
|
||||||
|
path = '/proc/spl/kstat/zfs/%s' % namespace
|
||||||
|
with open(path) as f:
|
||||||
|
entries = [line.strip().split() for line in f][2:] # Skip header
|
||||||
|
return [(kstat % name, D(value)) for name, _, value in entries]
|
||||||
|
|
||||||
|
def load_tunables():
|
||||||
|
basepath = '/sys/module/zfs/parameters'
|
||||||
|
tunables = {}
|
||||||
|
for name in os.listdir(basepath):
|
||||||
|
if not name:
|
||||||
|
continue
|
||||||
|
path = '%s/%s' % (basepath, name)
|
||||||
|
with open(path) as f:
|
||||||
|
value = f.read()
|
||||||
|
tunables[name] = value.strip()
|
||||||
|
return tunables
|
||||||
|
|
||||||
|
|
||||||
show_tunable_descriptions = False
|
show_tunable_descriptions = False
|
||||||
alternate_tunable_layout = False
|
alternate_tunable_layout = False
|
||||||
|
|
||||||
|
@ -77,15 +101,6 @@ def get_Kstat():
|
||||||
of the same name.
|
of the same name.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def load_kstats(namespace):
|
|
||||||
"""Collect information on a specific subsystem of the ARC"""
|
|
||||||
|
|
||||||
kstat = 'kstat.zfs.misc.%s.%%s' % namespace
|
|
||||||
path = '/proc/spl/kstat/zfs/%s' % namespace
|
|
||||||
with open(path) as f:
|
|
||||||
entries = [line.strip().split() for line in f][2:] # Skip header
|
|
||||||
return [(kstat % name, D(value)) for name, _, value in entries]
|
|
||||||
|
|
||||||
Kstat = {}
|
Kstat = {}
|
||||||
Kstat.update(load_kstats('arcstats'))
|
Kstat.update(load_kstats('arcstats'))
|
||||||
Kstat.update(load_kstats('zfetchstats'))
|
Kstat.update(load_kstats('zfetchstats'))
|
||||||
|
@ -917,18 +932,6 @@ def _tunable_summary(Kstat):
|
||||||
global show_tunable_descriptions
|
global show_tunable_descriptions
|
||||||
global alternate_tunable_layout
|
global alternate_tunable_layout
|
||||||
|
|
||||||
def load_tunables():
|
|
||||||
basepath = '/sys/module/zfs/parameters'
|
|
||||||
tunables = {}
|
|
||||||
for name in os.listdir(basepath):
|
|
||||||
if not name:
|
|
||||||
continue
|
|
||||||
path = '%s/%s' % (basepath, name)
|
|
||||||
with open(path) as f:
|
|
||||||
value = f.read()
|
|
||||||
tunables[name] = value.strip()
|
|
||||||
return tunables
|
|
||||||
|
|
||||||
tunables = load_tunables()
|
tunables = load_tunables()
|
||||||
descriptions = {}
|
descriptions = {}
|
||||||
|
|
||||||
|
|
|
@ -46,9 +46,6 @@ import time
|
||||||
DESCRIPTION = 'Print ARC and other statistics for ZFS on Linux'
|
DESCRIPTION = 'Print ARC and other statistics for ZFS on Linux'
|
||||||
INDENT = ' '*8
|
INDENT = ' '*8
|
||||||
LINE_LENGTH = 72
|
LINE_LENGTH = 72
|
||||||
PROC_PATH = '/proc/spl/kstat/zfs/'
|
|
||||||
SPL_PATH = '/sys/module/spl/parameters/'
|
|
||||||
TUNABLES_PATH = '/sys/module/zfs/parameters/'
|
|
||||||
DATE_FORMAT = '%a %b %d %H:%M:%S %Y'
|
DATE_FORMAT = '%a %b %d %H:%M:%S %Y'
|
||||||
TITLE = 'ZFS Subsystem Report'
|
TITLE = 'ZFS Subsystem Report'
|
||||||
|
|
||||||
|
@ -83,58 +80,58 @@ parser.add_argument('-s', '--section', dest='section', help=SECTION_HELP)
|
||||||
ARGS = parser.parse_args()
|
ARGS = parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
def get_params(basepath):
|
if sys.platform.startswith('linux'):
|
||||||
"""Collect information on the Solaris Porting Layer (SPL) or the
|
KSTAT_PATH = '/proc/spl/kstat/zfs/'
|
||||||
tunables, depending on the PATH given. Does not check if PATH is
|
SPL_PATH = '/sys/module/spl/parameters/'
|
||||||
legal.
|
TUNABLES_PATH = '/sys/module/zfs/parameters/'
|
||||||
"""
|
VDEV_CACHE_SIZE = 'zfs_vdev_cache_size'
|
||||||
result = {}
|
|
||||||
for name in os.listdir(basepath):
|
def load_kstats(section):
|
||||||
path = os.path.join(basepath, name)
|
path = os.path.join(KSTAT_PATH, section)
|
||||||
with open(path) as f:
|
with open(path) as f:
|
||||||
value = f.read()
|
return list(f)[2:] # Get rid of header
|
||||||
result[name] = value.strip()
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
def get_params(basepath):
|
||||||
|
"""Collect information on the Solaris Porting Layer (SPL) or the
|
||||||
|
tunables, depending on the PATH given. Does not check if PATH is
|
||||||
|
legal.
|
||||||
|
"""
|
||||||
|
result = {}
|
||||||
|
for name in os.listdir(basepath):
|
||||||
|
path = os.path.join(basepath, name)
|
||||||
|
with open(path) as f:
|
||||||
|
value = f.read()
|
||||||
|
result[name] = value.strip()
|
||||||
|
return result
|
||||||
|
|
||||||
def get_spl_params():
|
def get_spl_params():
|
||||||
return get_params(SPL_PATH)
|
return get_params(SPL_PATH)
|
||||||
|
|
||||||
|
def get_tunable_params():
|
||||||
|
return get_params(TUNABLES_PATH)
|
||||||
|
|
||||||
def get_tunable_params():
|
def get_vdev_params():
|
||||||
return get_params(TUNABLES_PATH)
|
return get_params(TUNABLES_PATH)
|
||||||
|
|
||||||
|
def get_version_impl(request):
|
||||||
|
# The original arc_summary called /sbin/modinfo/{spl,zfs} to get
|
||||||
|
# the version information. We switch to /sys/module/{spl,zfs}/version
|
||||||
|
# to make sure we get what is really loaded in the kernel
|
||||||
|
command = ["cat", "/sys/module/{0}/version".format(request)]
|
||||||
|
req = request.upper()
|
||||||
|
|
||||||
def get_vdev_params():
|
# The recommended way to do this is with subprocess.run(). However,
|
||||||
return get_params(TUNABLES_PATH)
|
# some installed versions of Python are < 3.5, so we offer them
|
||||||
|
# the option of doing it the old way (for now)
|
||||||
|
if 'run' in dir(subprocess):
|
||||||
|
info = subprocess.run(command, stdout=subprocess.PIPE,
|
||||||
|
universal_newlines=True)
|
||||||
|
version = info.stdout.strip()
|
||||||
|
else:
|
||||||
|
info = subprocess.check_output(command, universal_newlines=True)
|
||||||
|
version = info.strip()
|
||||||
|
|
||||||
|
return version
|
||||||
def get_version_impl(request):
|
|
||||||
# The original arc_summary called /sbin/modinfo/{spl,zfs} to get
|
|
||||||
# the version information. We switch to /sys/module/{spl,zfs}/version
|
|
||||||
# to make sure we get what is really loaded in the kernel
|
|
||||||
command = ["cat", "/sys/module/{0}/version".format(request)]
|
|
||||||
req = request.upper()
|
|
||||||
|
|
||||||
# The recommended way to do this is with subprocess.run(). However,
|
|
||||||
# some installed versions of Python are < 3.5, so we offer them
|
|
||||||
# the option of doing it the old way (for now)
|
|
||||||
info = ''
|
|
||||||
if 'run' in dir(subprocess):
|
|
||||||
info = subprocess.run(command, stdout=subprocess.PIPE,
|
|
||||||
universal_newlines=True)
|
|
||||||
version = info.stdout.strip()
|
|
||||||
else:
|
|
||||||
info = subprocess.check_output(command, universal_newlines=True)
|
|
||||||
version = info.strip()
|
|
||||||
|
|
||||||
return version
|
|
||||||
|
|
||||||
|
|
||||||
def load_kstats(section):
|
|
||||||
path = os.path.join(PROC_PATH, section)
|
|
||||||
with open(path) as f:
|
|
||||||
return list(f)[2:] # Get rid of header
|
|
||||||
|
|
||||||
|
|
||||||
def cleanup_line(single_line):
|
def cleanup_line(single_line):
|
||||||
|
@ -299,10 +296,10 @@ def format_raw_line(name, value):
|
||||||
|
|
||||||
|
|
||||||
def get_kstats():
|
def get_kstats():
|
||||||
"""Collect information on the ZFS subsystem from the /proc Linux virtual
|
"""Collect information on the ZFS subsystem. The step does not perform any
|
||||||
file system. The step does not perform any further processing, giving us
|
further processing, giving us the option to only work on what is actually
|
||||||
the option to only work on what is actually needed. The name "kstat" is a
|
needed. The name "kstat" is a holdover from the Solaris utility of the same
|
||||||
holdover from the Solaris utility of the same name.
|
name.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
result = {}
|
result = {}
|
||||||
|
@ -382,7 +379,7 @@ def get_version(request):
|
||||||
|
|
||||||
def print_header():
|
def print_header():
|
||||||
"""Print the initial heading with date and time as well as info on the
|
"""Print the initial heading with date and time as well as info on the
|
||||||
Linux and ZFS versions. This is not called for the graph.
|
kernel and ZFS versions. This is not called for the graph.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# datetime is now recommended over time but we keep the exact formatting
|
# datetime is now recommended over time but we keep the exact formatting
|
||||||
|
@ -779,7 +776,7 @@ def section_vdev(kstats_dict):
|
||||||
# for details
|
# for details
|
||||||
tunables = get_vdev_params()
|
tunables = get_vdev_params()
|
||||||
|
|
||||||
if tunables['zfs_vdev_cache_size'] == '0':
|
if tunables[VDEV_CACHE_SIZE] == '0':
|
||||||
print('VDEV cache disabled, skipping section\n')
|
print('VDEV cache disabled, skipping section\n')
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,7 @@ import copy
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from signal import signal, SIGINT, SIGWINCH, SIG_DFL
|
from signal import signal, SIGINT, SIGWINCH, SIG_DFL
|
||||||
|
|
||||||
|
|
||||||
cols = {
|
cols = {
|
||||||
# HDR: [Size, Scale, Description]
|
# HDR: [Size, Scale, Description]
|
||||||
"time": [8, -1, "Time"],
|
"time": [8, -1, "Time"],
|
||||||
|
@ -118,6 +119,26 @@ out = None
|
||||||
kstat = None
|
kstat = None
|
||||||
|
|
||||||
|
|
||||||
|
if sys.platform.startswith('linux'):
|
||||||
|
def kstat_update():
|
||||||
|
global kstat
|
||||||
|
|
||||||
|
k = [line.strip() for line in open('/proc/spl/kstat/zfs/arcstats')]
|
||||||
|
|
||||||
|
if not k:
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
del k[0:2]
|
||||||
|
kstat = {}
|
||||||
|
|
||||||
|
for s in k:
|
||||||
|
if not s:
|
||||||
|
continue
|
||||||
|
|
||||||
|
name, unused, value = s.split()
|
||||||
|
kstat[name] = Decimal(value)
|
||||||
|
|
||||||
|
|
||||||
def detailed_usage():
|
def detailed_usage():
|
||||||
sys.stderr.write("%s\n" % cmd)
|
sys.stderr.write("%s\n" % cmd)
|
||||||
sys.stderr.write("Field definitions are as follows:\n")
|
sys.stderr.write("Field definitions are as follows:\n")
|
||||||
|
@ -148,25 +169,6 @@ def usage():
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
def kstat_update():
|
|
||||||
global kstat
|
|
||||||
|
|
||||||
k = [line.strip() for line in open('/proc/spl/kstat/zfs/arcstats')]
|
|
||||||
|
|
||||||
if not k:
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
del k[0:2]
|
|
||||||
kstat = {}
|
|
||||||
|
|
||||||
for s in k:
|
|
||||||
if not s:
|
|
||||||
continue
|
|
||||||
|
|
||||||
name, unused, value = s.split()
|
|
||||||
kstat[name] = Decimal(value)
|
|
||||||
|
|
||||||
|
|
||||||
def snap_stats():
|
def snap_stats():
|
||||||
global cur
|
global cur
|
||||||
global kstat
|
global kstat
|
||||||
|
|
Loading…
Reference in New Issue