Skip to content
Permalink
Browse files

Add FreeBSD support to ZoL

- Import FreeBSD specific parts
- Update tests to work on FreeBSD

Signed-off-by: Matt Macy <mmacy@FreeBSD.org>
Signed-off-by: Ryan Moeller <ryan@ixsystems.com>
  • Loading branch information...
kmoore134 authored and mattmacy committed Jan 4, 2019
1 parent 381d91d commit 9db7b8eee131ed77b149ddc3d1e319e3914126d5
Showing 502 changed files with 91,446 additions and 902 deletions.
@@ -64,6 +64,12 @@ cscope.*
*.log
venv

*.so
*.so.debug
*.so.full
*.tmp
*.log

#
# Module leftovers
#
@@ -75,3 +81,9 @@ venv
/module/unicode/zunicode.mod
/module/zcommon/zcommon.mod
/module/zfs/zfs.mod

module/export_syms
module/machine
module/x86
module/zfs.ko.debug
module/zfs.ko.full
@@ -106,6 +106,7 @@ commitcheck:
cstyle:
@find ${top_srcdir} -name build -prune -o -name '*.[hc]' \
! -name 'zfs_config.*' ! -name '*.mod.c' -type f \
! -name '*_if.h' ! -path "*/os/freebsd/*" \
-exec ${top_srcdir}/scripts/cstyle.pl -cpP {} \+

filter_executable = -exec test -x '{}' \; -print
@@ -1,31 +1,72 @@
![img](http://zfsonlinux.org/images/zfs-linux.png)
![img](https://github.com/zfsonfreebsd/ZoF/raw/master/zof-logo.png)

ZFS on Linux is an advanced file system and volume manager which was originally
developed for Solaris and is now maintained by the OpenZFS community.
developed for Solaris and is now maintained by the OpenZFS community. ZoF is
the work to bring FreeBSD support into the ZoL repo.

[![codecov](https://codecov.io/gh/zfsonlinux/zfs/branch/master/graph/badge.svg)](https://codecov.io/gh/zfsonlinux/zfs)
[![coverity](https://scan.coverity.com/projects/1973/badge.svg)](https://scan.coverity.com/projects/zfsonlinux-zfs)

# Official Resources

* [Site](http://zfsonlinux.org)
* [Wiki](https://github.com/zfsonlinux/zfs/wiki)
* [Mailing lists](https://github.com/zfsonlinux/zfs/wiki/Mailing-Lists)
* [ZoF GitHub Site](https://zfsonfreebsd.github.io/ZoF/)
* [ZoL Site](http://zfsonlinux.org)
* [ZoL Wiki](https://github.com/zfsonlinux/zfs/wiki)
* [ZoL Mailing lists](https://github.com/zfsonlinux/zfs/wiki/Mailing-Lists)
* [OpenZFS site](http://open-zfs.org/)

# Installation

Full documentation for installing ZoL on your favorite Linux distribution can
be found at [our site](http://zfsonlinux.org/).
ZoF is available in the FreeBSD ports tree as sysutils/openzfs and
sysutils/openzfs-kmod. It can be installed on FreeBSD stable/12 or later.

# Contribute & Develop
The following dependencies are required to build ZoF from source:
* FreeBSD sources (in /usr/src or elsewhere specified by passing
`--with-freebsd=$path` to `./configure`
* Packages for build:
```
autoconf
automake
autotools
bash
git
gmake
```
* Optional packages for build:
```
python3 # or your preferred Python version
```
* Optional packages for test:
```
base64
fio
hs-ShellCheck
ksh93
py36-flake8 # or your preferred Python version
shuf
sudo
```
The user for running tests must have NOPASSWD sudo permission.

We have a separate document with [contribution guidelines](./.github/CONTRIBUTING.md).
To build and install:
```
# as user
git clone https://github.com/zfsonfreebsd/ZoF
cd ZoF
./autogen.sh
./configure
gmake
# as root
gmake install
```
The ZFS utilities will be installed in /usr/local/sbin/, so make sure your PATH
gets adjusted accordingly.

# Release
Beware that the FreeBSD boot loader does not allow booting from root pools with
encryption active (even if it is not in use), so do not try encryption on a
pool you boot from.

ZFS on Linux is released under a CDDL license.
For more details see the NOTICE, LICENSE and COPYRIGHT files; `UCRL-CODE-235197`
# Issues

Issues can be reported via GitHub's [Issue Tracker](https://github.com/zfsonfreebsd/ZoF).

# Supported Kernels
* The `META` file contains the officially recognized supported kernel versions.
@@ -0,0 +1 @@
theme: jekyll-theme-slate
@@ -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
@@ -54,6 +54,42 @@ import errno
from subprocess import Popen, PIPE
from decimal import Decimal as D

if sys.platform.startswith('freebsd'):
# Requires py27-sysctl on FreeBSD
import sysctl

def load_kstats(namespace):
"""Collect information on a specific subsystem of the ARC"""

base = 'kstat.zfs.misc.%s.' % namespace
return [(kstat.name, D(kstat.value)) for kstat in sysctl.filter(base)]

def load_tunables():
return dict((ctl.name, ctl.value) for ctl in sysctl.filter('vfs.zfs'))

else:

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
@@ -77,15 +113,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'))
@@ -917,18 +944,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 = {}

@@ -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'

@@ -83,58 +80,89 @@ 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

if sys.platform.startswith('freebsd'):
# Requires py36-sysctl on FreeBSD
import sysctl

def get_spl_params():
return get_params(SPL_PATH)
VDEV_CACHE_SIZE = 'vdev.cache_size'

def load_kstats(section):
base = 'kstat.zfs.misc.{section}.'.format(section=section)
# base is removed from the name
fmt = lambda kstat: '{name} : {value}'.format(name=kstat.name[len(base):],
value=kstat.value)
return [fmt(kstat) for kstat in sysctl.filter(base)]

def get_tunable_params():
return get_params(TUNABLES_PATH)
def get_params(base):
cut = 8 # = len('vfs.zfs.')
return {ctl.name[cut:]: str(ctl.value) for ctl in sysctl.filter(base)}

def get_tunable_params():
return get_params('vfs.zfs')

def get_vdev_params():
return get_params(TUNABLES_PATH)
def get_vdev_params():
return get_params('vfs.zfs.vdev')

def get_version_impl(request):
# FreeBSD reports versions for zpl and spa instead of zfs and spl.
name = {'zfs': 'zpl',
'spl': 'spa'}[request]
mib = 'vfs.zfs.version.{}'.format(name)
version = sysctl.filter(mib)[0].value
return '{} version {}'.format(name, 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
else:
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):
@@ -299,10 +327,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 = {}
@@ -382,7 +410,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
@@ -723,6 +751,10 @@ def section_spl(*_):
and/or descriptions. This does not use kstats.
"""

if sys.platform.startswith('freebsd'):
# No SPL support in FreeBSD
return

spls = get_spl_params()
keylist = sorted(spls.keys())
print('Solaris Porting Layer (SPL):')
@@ -779,7 +811,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

0 comments on commit 9db7b8e

Please sign in to comment.
You can’t perform that action at this time.