Skip to content

Commit

Permalink
Isolate code specific to Linux in cmd/
Browse files Browse the repository at this point in the history
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.

Signed-off-by: Ryan Moeller <ryan@ixsystems.com>
  • Loading branch information
Ryan Moeller committed Nov 7, 2019
1 parent 734de7c commit 25ed85d
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 99 deletions.
2 changes: 2 additions & 0 deletions cmd/Makefile.am
Expand Up @@ -5,4 +5,6 @@ if USING_PYTHON
SUBDIRS += arcstat arc_summary dbufstat
endif

if BUILD_LINUX
SUBDIRS += mount_zfs zed zvol_id zvol_wait
endif
45 changes: 24 additions & 21 deletions cmd/arc_summary/arc_summary2
Expand Up @@ -55,6 +55,30 @@ from subprocess import Popen, PIPE
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
alternate_tunable_layout = False

Expand All @@ -77,15 +101,6 @@ def get_Kstat():
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.update(load_kstats('arcstats'))
Kstat.update(load_kstats('zfetchstats'))
Expand Down Expand Up @@ -917,18 +932,6 @@ def _tunable_summary(Kstat):
global show_tunable_descriptions
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()
descriptions = {}

Expand Down
115 changes: 56 additions & 59 deletions cmd/arc_summary/arc_summary3
Expand Up @@ -46,9 +46,6 @@ import time
DESCRIPTION = 'Print ARC and other statistics for ZFS on Linux'
INDENT = ' '*8
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'
TITLE = 'ZFS Subsystem Report'

Expand Down Expand Up @@ -83,58 +80,58 @@ parser.add_argument('-s', '--section', dest='section', help=SECTION_HELP)
ARGS = parser.parse_args()


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():
return get_params(SPL_PATH)


def get_tunable_params():
return get_params(TUNABLES_PATH)


def get_vdev_params():
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()

# 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
if sys.platform.startswith('linux'):
KSTAT_PATH = '/proc/spl/kstat/zfs/'
SPL_PATH = '/sys/module/spl/parameters/'
TUNABLES_PATH = '/sys/module/zfs/parameters/'
VDEV_CACHE_SIZE = 'zfs_vdev_cache_size'

def load_kstats(section):
path = os.path.join(KSTAT_PATH, section)
with open(path) as f:
return list(f)[2:] # Get rid of header

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():
return get_params(SPL_PATH)

def get_tunable_params():
return get_params(TUNABLES_PATH)

def get_vdev_params():
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()

# 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)
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()

def load_kstats(section):
path = os.path.join(PROC_PATH, section)
with open(path) as f:
return list(f)[2:] # Get rid of header
return version


def cleanup_line(single_line):
Expand Down Expand Up @@ -299,10 +296,10 @@ def format_raw_line(name, value):


def get_kstats():
"""Collect information on the ZFS subsystem from the /proc Linux virtual
file system. The step does not perform any further processing, giving us
the option to only work on what is actually needed. The name "kstat" is a
holdover from the Solaris utility of the same name.
"""Collect information on the ZFS subsystem. The step does not perform any
further processing, giving us the option to only work on what is actually
needed. The name "kstat" is a holdover from the Solaris utility of the same
name.
"""

result = {}
Expand Down Expand Up @@ -382,7 +379,7 @@ def get_version(request):

def print_header():
"""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
Expand Down Expand Up @@ -779,7 +776,7 @@ def section_vdev(kstats_dict):
# for details
tunables = get_vdev_params()

if tunables['zfs_vdev_cache_size'] == '0':
if tunables[VDEV_CACHE_SIZE] == '0':
print('VDEV cache disabled, skipping section\n')
return

Expand Down
40 changes: 21 additions & 19 deletions cmd/arcstat/arcstat
Expand Up @@ -54,6 +54,7 @@ import copy
from decimal import Decimal
from signal import signal, SIGINT, SIGWINCH, SIG_DFL


cols = {
# HDR: [Size, Scale, Description]
"time": [8, -1, "Time"],
Expand Down Expand Up @@ -118,6 +119,26 @@ out = 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():
sys.stderr.write("%s\n" % cmd)
sys.stderr.write("Field definitions are as follows:\n")
Expand Down Expand Up @@ -148,25 +169,6 @@ def usage():
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():
global cur
global kstat
Expand Down

0 comments on commit 25ed85d

Please sign in to comment.