From 5ecbb293c64ee88257e1e21fa155cf75fdd8cbd8 Mon Sep 17 00:00:00 2001 From: Richard Laager Date: Thu, 6 Feb 2020 09:28:20 -0800 Subject: Fix zfs-functions packaging bug This fixes a bug where the generated zfs-functions was being included along with original zfs-functions.in in the make dist tarball. This caused an unfortunate series of events during build/packaging that resulted in the RPM-installed /etc/zfs/zfs-functions listing the paths as: ZFS="/usr/local/sbin/zfs" ZED="/usr/local/sbin/zed" ZPOOL="/usr/local/sbin/zpool" When they should have been: ZFS="/sbin/zfs" ZED="/sbin/zed" ZPOOL="/sbin/zpool" This affects init.d (non-systemd) distros like CentOS 6. /etc/default/zfs and /etc/zfs/zfs-functions are also used by the initramfs, so they need to be built even when init.d support is not. They have been moved to the (new) etc/default and (existing) etc/zfs source directories, respectively. Fixes: #9443 Co-authored-by: Tony Hutter Signed-off-by: Richard Laager --- etc/Makefile.am | 4 +- etc/default/.gitignore | 1 + etc/default/Makefile.am | 12 ++ etc/default/zfs.in | 138 ++++++++++++++ etc/init.d/.gitignore | 1 - etc/init.d/Makefile.am | 16 +- etc/init.d/README.md | 2 +- etc/init.d/zfs-functions.in | 432 -------------------------------------------- etc/init.d/zfs.in | 138 -------------- etc/zfs/.gitignore | 1 + etc/zfs/Makefile.am | 26 ++- etc/zfs/zfs-functions.in | 432 ++++++++++++++++++++++++++++++++++++++++++++ 12 files changed, 617 insertions(+), 586 deletions(-) create mode 100644 etc/default/.gitignore create mode 100644 etc/default/Makefile.am create mode 100644 etc/default/zfs.in delete mode 100644 etc/init.d/zfs-functions.in delete mode 100644 etc/init.d/zfs.in create mode 100644 etc/zfs/.gitignore create mode 100644 etc/zfs/zfs-functions.in (limited to 'etc') diff --git a/etc/Makefile.am b/etc/Makefile.am index 28b955106..67ef94a20 100644 --- a/etc/Makefile.am +++ b/etc/Makefile.am @@ -1,2 +1,2 @@ -SUBDIRS = zfs sudoers.d $(ZFS_INIT_SYSTEMD) $(ZFS_INIT_SYSV) $(ZFS_MODULE_LOAD) -DIST_SUBDIRS = init.d zfs systemd modules-load.d sudoers.d +SUBDIRS = default zfs sudoers.d $(ZFS_INIT_SYSTEMD) $(ZFS_INIT_SYSV) $(ZFS_MODULE_LOAD) +DIST_SUBDIRS = default init.d zfs systemd modules-load.d sudoers.d diff --git a/etc/default/.gitignore b/etc/default/.gitignore new file mode 100644 index 000000000..73304bc2c --- /dev/null +++ b/etc/default/.gitignore @@ -0,0 +1 @@ +zfs diff --git a/etc/default/Makefile.am b/etc/default/Makefile.am new file mode 100644 index 000000000..f35abd8e5 --- /dev/null +++ b/etc/default/Makefile.am @@ -0,0 +1,12 @@ +initconfdir = $(DEFAULT_INITCONF_DIR) +initconf_SCRIPTS = zfs + +EXTRA_DIST = \ + $(top_srcdir)/etc/default/zfs.in + +$(initconf_SCRIPTS):%:%.in Makefile + $(SED) \ + -e 's,@sysconfdir\@,$(sysconfdir),g' \ + $< >'$@' + +CLEANFILES = $(initconf_SCRIPTS) diff --git a/etc/default/zfs.in b/etc/default/zfs.in new file mode 100644 index 000000000..42fc1161c --- /dev/null +++ b/etc/default/zfs.in @@ -0,0 +1,138 @@ +# ZoL userland configuration. + +# NOTE: This file is intended for sysv init and initramfs. +# Changing some of these settings may not make any difference on +# systemd-based setup, e.g. setting ZFS_MOUNT=no will not prevent systemd +# from launching zfs-mount.service during boot. +# See: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=901436 + +# To enable a boolean setting, set it to yes, on, true, or 1. +# Anything else will be interpreted as unset. + +# Run `zfs mount -a` during system start? +ZFS_MOUNT='yes' + +# Run `zfs unmount -a` during system stop? +ZFS_UNMOUNT='yes' + +# Run `zfs share -a` during system start? +# nb: The shareiscsi, sharenfs, and sharesmb dataset properties. +ZFS_SHARE='yes' + +# Run `zfs unshare -a` during system stop? +ZFS_UNSHARE='yes' + +# By default, a verbatim import of all pools is performed at boot based on the +# contents of the default zpool cache file. The contents of the cache are +# managed automatically by the 'zpool import' and 'zpool export' commands. +# +# By setting this to 'yes', the system will instead search all devices for +# pools and attempt to import them all at boot, even those that have been +# exported. Under this mode, the search path can be controlled by the +# ZPOOL_IMPORT_PATH variable and a list of pools that should not be imported +# can be listed in the ZFS_POOL_EXCEPTIONS variable. +# +# Note that importing all visible pools may include pools that you don't +# expect, such as those on removable devices and SANs, and those pools may +# proceed to mount themselves in places you do not want them to. The results +# can be unpredictable and possibly dangerous. Only enable this option if you +# understand this risk and have complete physical control over your system and +# SAN to prevent the insertion of malicious pools. +ZPOOL_IMPORT_ALL_VISIBLE='no' + +# Specify specific path(s) to look for device nodes and/or links for the +# pool import(s). See zpool(8) for more information about this variable. +# It supersedes the old USE_DISK_BY_ID which indicated that it would only +# try '/dev/disk/by-id'. +# The old variable will still work in the code, but is deprecated. +#ZPOOL_IMPORT_PATH="/dev/disk/by-vdev:/dev/disk/by-id" + +# List of pools that should NOT be imported at boot +# when ZPOOL_IMPORT_ALL_VISIBLE is 'yes'. +# This is a space separated list. +#ZFS_POOL_EXCEPTIONS="test2" + +# List of pools that SHOULD be imported at boot by the initramfs +# instead of trying to import all available pools. If this is set +# then ZFS_POOL_EXCEPTIONS is ignored. +# Only applicable for Debian GNU/Linux {dkms,initramfs}. +# This is a semi-colon separated list. +#ZFS_POOL_IMPORT="pool1;pool2" + +# Should the datasets be mounted verbosely? +# A mount counter will be used when mounting if set to 'yes'. +VERBOSE_MOUNT='no' + +# Should we allow overlay mounts? +# This is standard in Linux, but not ZFS which comes from Solaris where this +# is not allowed). +DO_OVERLAY_MOUNTS='no' + +# Any additional option to the 'zfs import' commandline? +# Include '-o' for each option wanted. +# You don't need to put '-f' in here, unless you want it ALL the time. +# Using the option 'zfsforce=1' on the grub/kernel command line will +# do the same, but on a case-to-case basis. +ZPOOL_IMPORT_OPTS="" + +# Full path to the ZFS cache file? +# See "cachefile" in zpool(8). +# The default is "@sysconfdir@/zfs/zpool.cache". +#ZPOOL_CACHE="@sysconfdir@/zfs/zpool.cache" +# +# Setting ZPOOL_CACHE to an empty string ('') AND setting ZPOOL_IMPORT_OPTS to +# "-c @sysconfdir@/zfs/zpool.cache" will _enforce_ the use of a cache file. +# This is needed in some cases (extreme amounts of VDEVs, multipath etc). +# Generally, the use of a cache file is usually not recommended on Linux +# because it sometimes is more trouble than it's worth (laptops with external +# devices or when/if device nodes changes names). +#ZPOOL_IMPORT_OPTS="-c @sysconfdir@/zfs/zpool.cache" +#ZPOOL_CACHE="" + +# Any additional option to the 'zfs mount' command line? +# Include '-o' for each option wanted. +MOUNT_EXTRA_OPTIONS="" + +# Build kernel modules with the --enable-debug switch? +# Only applicable for Debian GNU/Linux {dkms,initramfs}. +ZFS_DKMS_ENABLE_DEBUG='no' + +# Build kernel modules with the --enable-debuginfo switch? +# Only applicable for Debian GNU/Linux {dkms,initramfs}. +ZFS_DKMS_ENABLE_DEBUGINFO='no' + +# Keep debugging symbols in kernel modules? +# Only applicable for Debian GNU/Linux {dkms,initramfs}. +ZFS_DKMS_DISABLE_STRIP='no' + +# Wait for this many seconds in the initrd pre_mountroot? +# This delays startup and should be '0' on most systems. +# Only applicable for Debian GNU/Linux {dkms,initramfs}. +ZFS_INITRD_PRE_MOUNTROOT_SLEEP='0' + +# Wait for this many seconds in the initrd mountroot? +# This delays startup and should be '0' on most systems. This might help on +# systems which have their ZFS root on a USB disk that takes just a little +# longer to be available +# Only applicable for Debian GNU/Linux {dkms,initramfs}. +ZFS_INITRD_POST_MODPROBE_SLEEP='0' + +# List of additional datasets to mount after the root dataset is mounted? +# +# The init script will use the mountpoint specified in the 'mountpoint' +# property value in the dataset to determine where it should be mounted. +# +# This is a space separated list, and will be mounted in the order specified, +# so if one filesystem depends on a previous mountpoint, make sure to put +# them in the right order. +# +# It is not necessary to add filesystems below the root fs here. It is +# taken care of by the initrd script automatically. These are only for +# additional filesystems needed. Such as /opt, /usr/local which is not +# located under the root fs. +# Example: If root FS is 'rpool/ROOT/rootfs', this would make sense. +#ZFS_INITRD_ADDITIONAL_DATASETS="rpool/ROOT/usr rpool/ROOT/var" + +# Optional arguments for the ZFS Event Daemon (ZED). +# See zed(8) for more information on available options. +#ZED_ARGS="-M" diff --git a/etc/init.d/.gitignore b/etc/init.d/.gitignore index 3f16b08ec..43a673d55 100644 --- a/etc/init.d/.gitignore +++ b/etc/init.d/.gitignore @@ -1,4 +1,3 @@ -zfs-functions zfs-import zfs-mount zfs-share diff --git a/etc/init.d/Makefile.am b/etc/init.d/Makefile.am index 953c31fd5..19fa76a2b 100644 --- a/etc/init.d/Makefile.am +++ b/etc/init.d/Makefile.am @@ -1,21 +1,15 @@ initdir = $(DEFAULT_INIT_DIR) init_SCRIPTS = zfs-import zfs-mount zfs-share zfs-zed -initcommondir = $(sysconfdir)/zfs -initcommon_SCRIPTS = zfs-functions - initconfdir = $(DEFAULT_INITCONF_DIR) -initconf_SCRIPTS = zfs EXTRA_DIST = \ - $(top_srcdir)/etc/init.d/zfs-functions.in \ $(top_srcdir)/etc/init.d/zfs-share.in \ $(top_srcdir)/etc/init.d/zfs-import.in \ $(top_srcdir)/etc/init.d/zfs-mount.in \ - $(top_srcdir)/etc/init.d/zfs-zed.in \ - $(top_srcdir)/etc/init.d/zfs.in + $(top_srcdir)/etc/init.d/zfs-zed.in -$(init_SCRIPTS) $(initconf_SCRIPTS) $(initcommon_SCRIPTS):%:%.in Makefile +$(init_SCRIPTS):%:%.in Makefile -(if [ -e /etc/debian_version ]; then \ NFS_SRV=nfs-kernel-server; \ else \ @@ -26,7 +20,8 @@ $(init_SCRIPTS) $(initconf_SCRIPTS) $(initcommon_SCRIPTS):%:%.in Makefile else \ SHELL=/bin/sh; \ fi; \ - $(SED) -e 's,@bindir\@,$(bindir),g' \ + $(SED) \ + -e 's,@bindir\@,$(bindir),g' \ -e 's,@sbindir\@,$(sbindir),g' \ -e 's,@udevdir\@,$(udevdir),g' \ -e 's,@udevruledir\@,$(udevruledir),g' \ @@ -37,7 +32,6 @@ $(init_SCRIPTS) $(initconf_SCRIPTS) $(initcommon_SCRIPTS):%:%.in Makefile -e "s,@SHELL\@,$$SHELL,g" \ -e "s,@NFS_SRV\@,$$NFS_SRV,g" \ $< >'$@'; \ - [ '$@' = 'zfs-functions' -o '$@' = 'zfs' ] || \ chmod +x '$@') -CLEANFILES = $(init_SCRIPTS) $(initcommon_SCRIPTS) $(initconf_SCRIPTS) +CLEANFILES = $(init_SCRIPTS) diff --git a/etc/init.d/README.md b/etc/init.d/README.md index 89edb1da3..ad7c053aa 100644 --- a/etc/init.d/README.md +++ b/etc/init.d/README.md @@ -35,7 +35,7 @@ SUPPORT If you're making your own distribution and you want the scripts to work on that, the biggest problem you'll (probably) have is the part - at the beginning of the "zfs-functions.in" file which sets up the + at the beginning of the "zfs-functions" file which sets up the logging output. INSTALLING INIT SCRIPT LINKS diff --git a/etc/init.d/zfs-functions.in b/etc/init.d/zfs-functions.in deleted file mode 100644 index 043f1b073..000000000 --- a/etc/init.d/zfs-functions.in +++ /dev/null @@ -1,432 +0,0 @@ -# This is a script with common functions etc used by zfs-import, zfs-mount, -# zfs-share and zfs-zed. -# -# It is _NOT_ to be called independently -# -# Released under the 2-clause BSD license. -# -# The original script that acted as a template for this script came from -# the Debian GNU/Linux kFreeBSD ZFS packages (which did not include a -# licensing stansa) in the commit dated Mar 24, 2011: -# https://github.com/zfsonlinux/pkg-zfs/commit/80a3ae582b59c0250d7912ba794dca9e669e605a - -PATH=/sbin:/bin:/usr/bin:/usr/sbin - -# Source function library -if [ -f /etc/rc.d/init.d/functions ]; then - # RedHat and derivates - . /etc/rc.d/init.d/functions -elif [ -L /etc/init.d/functions.sh ]; then - # Gentoo - . /etc/init.d/functions.sh -elif [ -f /lib/lsb/init-functions ]; then - # LSB, Debian GNU/Linux and derivates - . /lib/lsb/init-functions -fi - -# Of course the functions we need are called differently -# on different distributions - it would be way too easy -# otherwise!! -if type log_failure_msg > /dev/null 2>&1 ; then - # LSB functions - fall through - zfs_log_begin_msg() { log_begin_msg "$1"; } - zfs_log_end_msg() { log_end_msg "$1"; } - zfs_log_failure_msg() { log_failure_msg "$1"; } - zfs_log_progress_msg() { log_progress_msg "$1"; } -elif type success > /dev/null 2>&1 ; then - # Fedora/RedHat functions - zfs_set_ifs() { - # For some reason, the init function library have a problem - # with a changed IFS, so this function goes around that. - local tIFS="$1" - if [ -n "$tIFS" ] - then - TMP_IFS="$IFS" - IFS="$tIFS" - fi - } - - zfs_log_begin_msg() { echo -n "$1 "; } - zfs_log_end_msg() { - zfs_set_ifs "$OLD_IFS" - if [ "$1" -eq 0 ]; then - success - else - failure - fi - echo - zfs_set_ifs "$TMP_IFS" - } - zfs_log_failure_msg() { - zfs_set_ifs "$OLD_IFS" - failure - echo - zfs_set_ifs "$TMP_IFS" - } - zfs_log_progress_msg() { echo -n $"$1"; } -elif type einfo > /dev/null 2>&1 ; then - # Gentoo functions - zfs_log_begin_msg() { ebegin "$1"; } - zfs_log_end_msg() { eend "$1"; } - zfs_log_failure_msg() { eend "$1"; } -# zfs_log_progress_msg() { echo -n "$1"; } - zfs_log_progress_msg() { echo -n; } -else - # Unknown - simple substitutes. - zfs_log_begin_msg() { echo -n "$1"; } - zfs_log_end_msg() { - ret=$1 - if [ "$ret" -ge 1 ]; then - echo " failed!" - else - echo " success" - fi - return "$ret" - } - zfs_log_failure_msg() { echo "$1"; } - zfs_log_progress_msg() { echo -n "$1"; } -fi - -# Paths to what we need -ZFS="@sbindir@/zfs" -ZED="@sbindir@/zed" -ZPOOL="@sbindir@/zpool" -ZPOOL_CACHE="@sysconfdir@/zfs/zpool.cache" - -# Sensible defaults -ZFS_MOUNT='yes' -ZFS_UNMOUNT='yes' - -export ZFS ZED ZPOOL ZPOOL_CACHE ZFS_MOUNT ZFS_UNMOUNT - -# Source zfs configuration, overriding the defaults -if [ -f @initconfdir@/zfs ]; then - . @initconfdir@/zfs -fi - -# ---------------------------------------------------- - -zfs_action() -{ - local MSG="$1"; shift - local CMD="$*" - local ret - - zfs_log_begin_msg "$MSG " - $CMD - ret=$? - if [ "$ret" -eq 0 ]; then - zfs_log_end_msg $ret - else - zfs_log_failure_msg $ret - fi - - return $ret -} - -# Returns -# 0 if daemon has been started -# 1 if daemon was already running -# 2 if daemon could not be started -# 3 if unsupported -# -zfs_daemon_start() -{ - local PIDFILE="$1"; shift - local DAEMON_BIN="$1"; shift - local DAEMON_ARGS="$*" - - if type start-stop-daemon > /dev/null 2>&1 ; then - # LSB functions - start-stop-daemon --start --quiet --pidfile "$PIDFILE" \ - --exec "$DAEMON_BIN" --test > /dev/null || return 1 - - start-stop-daemon --start --quiet --exec "$DAEMON_BIN" -- \ - $DAEMON_ARGS || return 2 - - # On Debian GNU/Linux, there's a 'sendsigs' script that will - # kill basically everything quite early and zed is stopped - # much later than that. We don't want zed to be among them, - # so add the zed pid to list of pids to ignore. - if [ -f "$PIDFILE" -a -d /run/sendsigs.omit.d ] - then - ln -sf "$PIDFILE" /run/sendsigs.omit.d/zed - fi - elif type daemon > /dev/null 2>&1 ; then - # Fedora/RedHat functions - daemon --pidfile "$PIDFILE" "$DAEMON_BIN" $DAEMON_ARGS - return $? - else - # Unsupported - return 3 - fi - - return 0 -} - -# Returns -# 0 if daemon has been stopped -# 1 if daemon was already stopped -# 2 if daemon could not be stopped -# 3 if unsupported -# -zfs_daemon_stop() -{ - local PIDFILE="$1" - local DAEMON_BIN="$2" - local DAEMON_NAME="$3" - - if type start-stop-daemon > /dev/null 2>&1 ; then - # LSB functions - start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 \ - --pidfile "$PIDFILE" --name "$DAEMON_NAME" - [ "$?" = 0 ] && rm -f "$PIDFILE" - - return $? - elif type killproc > /dev/null 2>&1 ; then - # Fedora/RedHat functions - killproc -p "$PIDFILE" "$DAEMON_NAME" - [ "$?" = 0 ] && rm -f "$PIDFILE" - - return $? - else - # Unsupported - return 3 - fi - - return 0 -} - -# Returns status -zfs_daemon_status() -{ - local PIDFILE="$1" - local DAEMON_BIN="$2" - local DAEMON_NAME="$3" - - if type status_of_proc > /dev/null 2>&1 ; then - # LSB functions - status_of_proc "$DAEMON_NAME" "$DAEMON_BIN" - return $? - elif type status > /dev/null 2>&1 ; then - # Fedora/RedHat functions - status -p "$PIDFILE" "$DAEMON_NAME" - return $? - else - # Unsupported - return 3 - fi - - return 0 -} - -zfs_daemon_reload() -{ - local PIDFILE="$1" - local DAEMON_NAME="$2" - - if type start-stop-daemon > /dev/null 2>&1 ; then - # LSB functions - start-stop-daemon --stop --signal 1 --quiet \ - --pidfile "$PIDFILE" --name "$DAEMON_NAME" - return $? - elif type killproc > /dev/null 2>&1 ; then - # Fedora/RedHat functions - killproc -p "$PIDFILE" "$DAEMON_NAME" -HUP - return $? - else - # Unsupported - return 3 - fi - - return 0 -} - -zfs_installed() -{ - if [ ! -x "$ZPOOL" ]; then - return 1 - else - # Test if it works (will catch missing/broken libs etc) - "$ZPOOL" -? > /dev/null 2>&1 - return $? - fi - - if [ ! -x "$ZFS" ]; then - return 2 - else - # Test if it works (will catch missing/broken libs etc) - "$ZFS" -? > /dev/null 2>&1 - return $? - fi - - return 0 -} - -# Trigger udev and wait for it to settle. -udev_trigger() -{ - if [ -x /sbin/udevadm ]; then - /sbin/udevadm trigger --action=change --subsystem-match=block - /sbin/udevadm settle - elif [ -x /sbin/udevsettle ]; then - /sbin/udevtrigger - /sbin/udevsettle - fi -} - -# Do a lot of checks to make sure it's 'safe' to continue with the import. -checksystem() -{ - if grep -qiE '(^|[^\\](\\\\)* )zfs=(off|no|0)( |$)' /proc/cmdline; - then - # Called with zfs=(off|no|0) - bail because we don't - # want anything import, mounted or shared. - # HOWEVER, only do this if we're called at the boot up - # (from init), not if we're running interactively (as in - # from the shell - we know what we're doing). - [ -n "$init" ] && exit 3 - fi - - # Check if ZFS is installed. - zfs_installed || return 5 - - # Just make sure that /dev/zfs is created. - udev_trigger - - return 0 -} - -get_root_pool() -{ - set -- $(mount | grep ' on / ') - [ "$5" = "zfs" ] && echo "${1%%/*}" -} - -# Check if a variable is 'yes' (any case) or '1' -# Returns TRUE if set. -check_boolean() -{ - local var="$1" - - echo "$var" | grep -Eiq "^yes$|^on$|^true$|^1$" && return 0 || return 1 -} - -check_module_loaded() -{ - module="$1" - - [ -r "/sys/module/${module}/version" ] && return 0 || return 1 -} - -load_module() -{ - module="$1" - - # Load the zfs module stack - if ! check_module_loaded "$module"; then - if ! /sbin/modprobe "$module"; then - return 5 - fi - fi - return 0 -} - -# first parameter is a regular expression that filters mtab -read_mtab() -{ - local match="$1" - local fs mntpnt fstype opts rest TMPFILE - - # Unset all MTAB_* variables - unset $(env | grep ^MTAB_ | sed 's,=.*,,') - - while read -r fs mntpnt fstype opts rest; do - if echo "$fs $mntpnt $fstype $opts" | grep -qE "$match"; then - # * Fix problems (!?) in the mounts file. It will record - # 'rpool 1' as 'rpool\0401' instead of 'rpool\00401' - # which seems to be the correct (at least as far as - # 'printf' is concerned). - # * We need to use the external echo, because the - # internal one would interpret the backslash code - # (incorrectly), giving us a  instead. - mntpnt=$(/bin/echo "$mntpnt" | sed "s,\\\0,\\\00,g") - fs=$(/bin/echo "$fs" | sed "s,\\\0,\\\00,") - - # Remove 'unwanted' characters. - mntpnt=$(printf '%b\n' "$mntpnt" | sed -e 's,/,,g' \ - -e 's,-,,g' -e 's,\.,,g' -e 's, ,,g') - fs=$(printf '%b\n' "$fs") - - # Set the variable. - eval export MTAB_$mntpnt=\"$fs\" - fi - done < /proc/self/mounts -} - -in_mtab() -{ - local mntpnt="$1" - # Remove 'unwanted' characters. - mntpnt=$(printf '%b\n' "$mntpnt" | sed -e 's,/,,g' \ - -e 's,-,,g' -e 's,\.,,g' -e 's, ,,g') - local var - - var="$(eval echo MTAB_$mntpnt)" - [ "$(eval echo "$""$var")" != "" ] - return "$?" -} - -# first parameter is a regular expression that filters fstab -read_fstab() -{ - local match="$1" - local i var TMPFILE - - # Unset all FSTAB_* variables - unset $(env | grep ^FSTAB_ | sed 's,=.*,,') - - i=0 - while read -r fs mntpnt fstype opts; do - echo "$fs" | egrep -qE '^#|^$' && continue - echo "$mntpnt" | egrep -qE '^none|^swap' && continue - echo "$fstype" | egrep -qE '^swap' && continue - - if echo "$fs $mntpnt $fstype $opts" | grep -qE "$match"; then - eval export FSTAB_dev_$i="$fs" - fs=$(printf '%b\n' "$fs" | sed 's,/,_,g') - eval export FSTAB_$i="$mntpnt" - - i=$((i + 1)) - fi - done < /etc/fstab -} - -in_fstab() -{ - local var - - var="$(eval echo FSTAB_$1)" - [ "${var}" != "" ] - return $? -} - -is_mounted() -{ - local mntpt="$1" - local line - - mount | \ - while read line; do - if echo "$line" | grep -q " on $mntpt "; then - # returns: - # 0 on unsuccessful match - # 1 on a successful match - return 1 - fi - done - - # The negation will flip the subshell return result where the default - # return value is 0 when a match is not found. - return $(( !$? )) -} diff --git a/etc/init.d/zfs.in b/etc/init.d/zfs.in deleted file mode 100644 index 42fc1161c..000000000 --- a/etc/init.d/zfs.in +++ /dev/null @@ -1,138 +0,0 @@ -# ZoL userland configuration. - -# NOTE: This file is intended for sysv init and initramfs. -# Changing some of these settings may not make any difference on -# systemd-based setup, e.g. setting ZFS_MOUNT=no will not prevent systemd -# from launching zfs-mount.service during boot. -# See: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=901436 - -# To enable a boolean setting, set it to yes, on, true, or 1. -# Anything else will be interpreted as unset. - -# Run `zfs mount -a` during system start? -ZFS_MOUNT='yes' - -# Run `zfs unmount -a` during system stop? -ZFS_UNMOUNT='yes' - -# Run `zfs share -a` during system start? -# nb: The shareiscsi, sharenfs, and sharesmb dataset properties. -ZFS_SHARE='yes' - -# Run `zfs unshare -a` during system stop? -ZFS_UNSHARE='yes' - -# By default, a verbatim import of all pools is performed at boot based on the -# contents of the default zpool cache file. The contents of the cache are -# managed automatically by the 'zpool import' and 'zpool export' commands. -# -# By setting this to 'yes', the system will instead search all devices for -# pools and attempt to import them all at boot, even those that have been -# exported. Under this mode, the search path can be controlled by the -# ZPOOL_IMPORT_PATH variable and a list of pools that should not be imported -# can be listed in the ZFS_POOL_EXCEPTIONS variable. -# -# Note that importing all visible pools may include pools that you don't -# expect, such as those on removable devices and SANs, and those pools may -# proceed to mount themselves in places you do not want them to. The results -# can be unpredictable and possibly dangerous. Only enable this option if you -# understand this risk and have complete physical control over your system and -# SAN to prevent the insertion of malicious pools. -ZPOOL_IMPORT_ALL_VISIBLE='no' - -# Specify specific path(s) to look for device nodes and/or links for the -# pool import(s). See zpool(8) for more information about this variable. -# It supersedes the old USE_DISK_BY_ID which indicated that it would only -# try '/dev/disk/by-id'. -# The old variable will still work in the code, but is deprecated. -#ZPOOL_IMPORT_PATH="/dev/disk/by-vdev:/dev/disk/by-id" - -# List of pools that should NOT be imported at boot -# when ZPOOL_IMPORT_ALL_VISIBLE is 'yes'. -# This is a space separated list. -#ZFS_POOL_EXCEPTIONS="test2" - -# List of pools that SHOULD be imported at boot by the initramfs -# instead of trying to import all available pools. If this is set -# then ZFS_POOL_EXCEPTIONS is ignored. -# Only applicable for Debian GNU/Linux {dkms,initramfs}. -# This is a semi-colon separated list. -#ZFS_POOL_IMPORT="pool1;pool2" - -# Should the datasets be mounted verbosely? -# A mount counter will be used when mounting if set to 'yes'. -VERBOSE_MOUNT='no' - -# Should we allow overlay mounts? -# This is standard in Linux, but not ZFS which comes from Solaris where this -# is not allowed). -DO_OVERLAY_MOUNTS='no' - -# Any additional option to the 'zfs import' commandline? -# Include '-o' for each option wanted. -# You don't need to put '-f' in here, unless you want it ALL the time. -# Using the option 'zfsforce=1' on the grub/kernel command line will -# do the same, but on a case-to-case basis. -ZPOOL_IMPORT_OPTS="" - -# Full path to the ZFS cache file? -# See "cachefile" in zpool(8). -# The default is "@sysconfdir@/zfs/zpool.cache". -#ZPOOL_CACHE="@sysconfdir@/zfs/zpool.cache" -# -# Setting ZPOOL_CACHE to an empty string ('') AND setting ZPOOL_IMPORT_OPTS to -# "-c @sysconfdir@/zfs/zpool.cache" will _enforce_ the use of a cache file. -# This is needed in some cases (extreme amounts of VDEVs, multipath etc). -# Generally, the use of a cache file is usually not recommended on Linux -# because it sometimes is more trouble than it's worth (laptops with external -# devices or when/if device nodes changes names). -#ZPOOL_IMPORT_OPTS="-c @sysconfdir@/zfs/zpool.cache" -#ZPOOL_CACHE="" - -# Any additional option to the 'zfs mount' command line? -# Include '-o' for each option wanted. -MOUNT_EXTRA_OPTIONS="" - -# Build kernel modules with the --enable-debug switch? -# Only applicable for Debian GNU/Linux {dkms,initramfs}. -ZFS_DKMS_ENABLE_DEBUG='no' - -# Build kernel modules with the --enable-debuginfo switch? -# Only applicable for Debian GNU/Linux {dkms,initramfs}. -ZFS_DKMS_ENABLE_DEBUGINFO='no' - -# Keep debugging symbols in kernel modules? -# Only applicable for Debian GNU/Linux {dkms,initramfs}. -ZFS_DKMS_DISABLE_STRIP='no' - -# Wait for this many seconds in the initrd pre_mountroot? -# This delays startup and should be '0' on most systems. -# Only applicable for Debian GNU/Linux {dkms,initramfs}. -ZFS_INITRD_PRE_MOUNTROOT_SLEEP='0' - -# Wait for this many seconds in the initrd mountroot? -# This delays startup and should be '0' on most systems. This might help on -# systems which have their ZFS root on a USB disk that takes just a little -# longer to be available -# Only applicable for Debian GNU/Linux {dkms,initramfs}. -ZFS_INITRD_POST_MODPROBE_SLEEP='0' - -# List of additional datasets to mount after the root dataset is mounted? -# -# The init script will use the mountpoint specified in the 'mountpoint' -# property value in the dataset to determine where it should be mounted. -# -# This is a space separated list, and will be mounted in the order specified, -# so if one filesystem depends on a previous mountpoint, make sure to put -# them in the right order. -# -# It is not necessary to add filesystems below the root fs here. It is -# taken care of by the initrd script automatically. These are only for -# additional filesystems needed. Such as /opt, /usr/local which is not -# located under the root fs. -# Example: If root FS is 'rpool/ROOT/rootfs', this would make sense. -#ZFS_INITRD_ADDITIONAL_DATASETS="rpool/ROOT/usr rpool/ROOT/var" - -# Optional arguments for the ZFS Event Daemon (ZED). -# See zed(8) for more information on available options. -#ZED_ARGS="-M" diff --git a/etc/zfs/.gitignore b/etc/zfs/.gitignore new file mode 100644 index 000000000..1b2d752de --- /dev/null +++ b/etc/zfs/.gitignore @@ -0,0 +1 @@ +zfs-functions diff --git a/etc/zfs/Makefile.am b/etc/zfs/Makefile.am index 52f6634df..81567a4fa 100644 --- a/etc/zfs/Makefile.am +++ b/etc/zfs/Makefile.am @@ -6,5 +6,29 @@ pkgsysconf_DATA = \ vdev_id.conf.sas_switch.example \ vdev_id.conf.multipath.example \ vdev_id.conf.scsi.example +pkgsysconf_SCRIPTS = \ + zfs-functions -EXTRA_DIST = $(pkgsysconf_DATA) +EXTRA_DIST = $(pkgsysconf_DATA) \ + zfs-functions.in + +$(pkgsysconf_SCRIPTS):%:%.in Makefile + -(if [ -e /etc/debian_version ]; then \ + NFS_SRV=nfs-kernel-server; \ + else \ + NFS_SRV=nfs; \ + fi; \ + if [ -e /sbin/openrc-run ]; then \ + SHELL=/sbin/openrc-run; \ + else \ + SHELL=/bin/sh; \ + fi; \ + $(SED) \ + -e 's,@sbindir\@,$(sbindir),g' \ + -e 's,@sysconfdir\@,$(sysconfdir),g' \ + -e 's,@initconfdir\@,$(initconfdir),g' \ + $< >'$@'; \ + [ '$@' = 'zfs-functions' ] || \ + chmod +x '$@') + +CLEANFILES = $(pkgsysconf_SCRIPTS) diff --git a/etc/zfs/zfs-functions.in b/etc/zfs/zfs-functions.in new file mode 100644 index 000000000..043f1b073 --- /dev/null +++ b/etc/zfs/zfs-functions.in @@ -0,0 +1,432 @@ +# This is a script with common functions etc used by zfs-import, zfs-mount, +# zfs-share and zfs-zed. +# +# It is _NOT_ to be called independently +# +# Released under the 2-clause BSD license. +# +# The original script that acted as a template for this script came from +# the Debian GNU/Linux kFreeBSD ZFS packages (which did not include a +# licensing stansa) in the commit dated Mar 24, 2011: +# https://github.com/zfsonlinux/pkg-zfs/commit/80a3ae582b59c0250d7912ba794dca9e669e605a + +PATH=/sbin:/bin:/usr/bin:/usr/sbin + +# Source function library +if [ -f /etc/rc.d/init.d/functions ]; then + # RedHat and derivates + . /etc/rc.d/init.d/functions +elif [ -L /etc/init.d/functions.sh ]; then + # Gentoo + . /etc/init.d/functions.sh +elif [ -f /lib/lsb/init-functions ]; then + # LSB, Debian GNU/Linux and derivates + . /lib/lsb/init-functions +fi + +# Of course the functions we need are called differently +# on different distributions - it would be way too easy +# otherwise!! +if type log_failure_msg > /dev/null 2>&1 ; then + # LSB functions - fall through + zfs_log_begin_msg() { log_begin_msg "$1"; } + zfs_log_end_msg() { log_end_msg "$1"; } + zfs_log_failure_msg() { log_failure_msg "$1"; } + zfs_log_progress_msg() { log_progress_msg "$1"; } +elif type success > /dev/null 2>&1 ; then + # Fedora/RedHat functions + zfs_set_ifs() { + # For some reason, the init function library have a problem + # with a changed IFS, so this function goes around that. + local tIFS="$1" + if [ -n "$tIFS" ] + then + TMP_IFS="$IFS" + IFS="$tIFS" + fi + } + + zfs_log_begin_msg() { echo -n "$1 "; } + zfs_log_end_msg() { + zfs_set_ifs "$OLD_IFS" + if [ "$1" -eq 0 ]; then + success + else + failure + fi + echo + zfs_set_ifs "$TMP_IFS" + } + zfs_log_failure_msg() { + zfs_set_ifs "$OLD_IFS" + failure + echo + zfs_set_ifs "$TMP_IFS" + } + zfs_log_progress_msg() { echo -n $"$1"; } +elif type einfo > /dev/null 2>&1 ; then + # Gentoo functions + zfs_log_begin_msg() { ebegin "$1"; } + zfs_log_end_msg() { eend "$1"; } + zfs_log_failure_msg() { eend "$1"; } +# zfs_log_progress_msg() { echo -n "$1"; } + zfs_log_progress_msg() { echo -n; } +else + # Unknown - simple substitutes. + zfs_log_begin_msg() { echo -n "$1"; } + zfs_log_end_msg() { + ret=$1 + if [ "$ret" -ge 1 ]; then + echo " failed!" + else + echo " success" + fi + return "$ret" + } + zfs_log_failure_msg() { echo "$1"; } + zfs_log_progress_msg() { echo -n "$1"; } +fi + +# Paths to what we need +ZFS="@sbindir@/zfs" +ZED="@sbindir@/zed" +ZPOOL="@sbindir@/zpool" +ZPOOL_CACHE="@sysconfdir@/zfs/zpool.cache" + +# Sensible defaults +ZFS_MOUNT='yes' +ZFS_UNMOUNT='yes' + +export ZFS ZED ZPOOL ZPOOL_CACHE ZFS_MOUNT ZFS_UNMOUNT + +# Source zfs configuration, overriding the defaults +if [ -f @initconfdir@/zfs ]; then + . @initconfdir@/zfs +fi + +# ---------------------------------------------------- + +zfs_action() +{ + local MSG="$1"; shift + local CMD="$*" + local ret + + zfs_log_begin_msg "$MSG " + $CMD + ret=$? + if [ "$ret" -eq 0 ]; then + zfs_log_end_msg $ret + else + zfs_log_failure_msg $ret + fi + + return $ret +} + +# Returns +# 0 if daemon has been started +# 1 if daemon was already running +# 2 if daemon could not be started +# 3 if unsupported +# +zfs_daemon_start() +{ + local PIDFILE="$1"; shift + local DAEMON_BIN="$1"; shift + local DAEMON_ARGS="$*" + + if type start-stop-daemon > /dev/null 2>&1 ; then + # LSB functions + start-stop-daemon --start --quiet --pidfile "$PIDFILE" \ + --exec "$DAEMON_BIN" --test > /dev/null || return 1 + + start-stop-daemon --start --quiet --exec "$DAEMON_BIN" -- \ + $DAEMON_ARGS || return 2 + + # On Debian GNU/Linux, there's a 'sendsigs' script that will + # kill basically everything quite early and zed is stopped + # much later than that. We don't want zed to be among them, + # so add the zed pid to list of pids to ignore. + if [ -f "$PIDFILE" -a -d /run/sendsigs.omit.d ] + then + ln -sf "$PIDFILE" /run/sendsigs.omit.d/zed + fi + elif type daemon > /dev/null 2>&1 ; then + # Fedora/RedHat functions + daemon --pidfile "$PIDFILE" "$DAEMON_BIN" $DAEMON_ARGS + return $? + else + # Unsupported + return 3 + fi + + return 0 +} + +# Returns +# 0 if daemon has been stopped +# 1 if daemon was already stopped +# 2 if daemon could not be stopped +# 3 if unsupported +# +zfs_daemon_stop() +{ + local PIDFILE="$1" + local DAEMON_BIN="$2" + local DAEMON_NAME="$3" + + if type start-stop-daemon > /dev/null 2>&1 ; then + # LSB functions + start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 \ + --pidfile "$PIDFILE" --name "$DAEMON_NAME" + [ "$?" = 0 ] && rm -f "$PIDFILE" + + return $? + elif type killproc > /dev/null 2>&1 ; then + # Fedora/RedHat functions + killproc -p "$PIDFILE" "$DAEMON_NAME" + [ "$?" = 0 ] && rm -f "$PIDFILE" + + return $? + else + # Unsupported + return 3 + fi + + return 0 +} + +# Returns status +zfs_daemon_status() +{ + local PIDFILE="$1" + local DAEMON_BIN="$2" + local DAEMON_NAME="$3" + + if type status_of_proc > /dev/null 2>&1 ; then + # LSB functions + status_of_proc "$DAEMON_NAME" "$DAEMON_BIN" + return $? + elif type status > /dev/null 2>&1 ; then + # Fedora/RedHat functions + status -p "$PIDFILE" "$DAEMON_NAME" + return $? + else + # Unsupported + return 3 + fi + + return 0 +} + +zfs_daemon_reload() +{ + local PIDFILE="$1" + local DAEMON_NAME="$2" + + if type start-stop-daemon > /dev/null 2>&1 ; then + # LSB functions + start-stop-daemon --stop --signal 1 --quiet \ + --pidfile "$PIDFILE" --name "$DAEMON_NAME" + return $? + elif type killproc > /dev/null 2>&1 ; then + # Fedora/RedHat functions + killproc -p "$PIDFILE" "$DAEMON_NAME" -HUP + return $? + else + # Unsupported + return 3 + fi + + return 0 +} + +zfs_installed() +{ + if [ ! -x "$ZPOOL" ]; then + return 1 + else + # Test if it works (will catch missing/broken libs etc) + "$ZPOOL" -? > /dev/null 2>&1 + return $? + fi + + if [ ! -x "$ZFS" ]; then + return 2 + else + # Test if it works (will catch missing/broken libs etc) + "$ZFS" -? > /dev/null 2>&1 + return $? + fi + + return 0 +} + +# Trigger udev and wait for it to settle. +udev_trigger() +{ + if [ -x /sbin/udevadm ]; then + /sbin/udevadm trigger --action=change --subsystem-match=block + /sbin/udevadm settle + elif [ -x /sbin/udevsettle ]; then + /sbin/udevtrigger + /sbin/udevsettle + fi +} + +# Do a lot of checks to make sure it's 'safe' to continue with the import. +checksystem() +{ + if grep -qiE '(^|[^\\](\\\\)* )zfs=(off|no|0)( |$)' /proc/cmdline; + then + # Called with zfs=(off|no|0) - bail because we don't + # want anything import, mounted or shared. + # HOWEVER, only do this if we're called at the boot up + # (from init), not if we're running interactively (as in + # from the shell - we know what we're doing). + [ -n "$init" ] && exit 3 + fi + + # Check if ZFS is installed. + zfs_installed || return 5 + + # Just make sure that /dev/zfs is created. + udev_trigger + + return 0 +} + +get_root_pool() +{ + set -- $(mount | grep ' on / ') + [ "$5" = "zfs" ] && echo "${1%%/*}" +} + +# Check if a variable is 'yes' (any case) or '1' +# Returns TRUE if set. +check_boolean() +{ + local var="$1" + + echo "$var" | grep -Eiq "^yes$|^on$|^true$|^1$" && return 0 || return 1 +} + +check_module_loaded() +{ + module="$1" + + [ -r "/sys/module/${module}/version" ] && return 0 || return 1 +} + +load_module() +{ + module="$1" + + # Load the zfs module stack + if ! check_module_loaded "$module"; then + if ! /sbin/modprobe "$module"; then + return 5 + fi + fi + return 0 +} + +# first parameter is a regular expression that filters mtab +read_mtab() +{ + local match="$1" + local fs mntpnt fstype opts rest TMPFILE + + # Unset all MTAB_* variables + unset $(env | grep ^MTAB_ | sed 's,=.*,,') + + while read -r fs mntpnt fstype opts rest; do + if echo "$fs $mntpnt $fstype $opts" | grep -qE "$match"; then + # * Fix problems (!?) in the mounts file. It will record + # 'rpool 1' as 'rpool\0401' instead of 'rpool\00401' + # which seems to be the correct (at least as far as + # 'printf' is concerned). + # * We need to use the external echo, because the + # internal one would interpret the backslash code + # (incorrectly), giving us a  instead. + mntpnt=$(/bin/echo "$mntpnt" | sed "s,\\\0,\\\00,g") + fs=$(/bin/echo "$fs" | sed "s,\\\0,\\\00,") + + # Remove 'unwanted' characters. + mntpnt=$(printf '%b\n' "$mntpnt" | sed -e 's,/,,g' \ + -e 's,-,,g' -e 's,\.,,g' -e 's, ,,g') + fs=$(printf '%b\n' "$fs") + + # Set the variable. + eval export MTAB_$mntpnt=\"$fs\" + fi + done < /proc/self/mounts +} + +in_mtab() +{ + local mntpnt="$1" + # Remove 'unwanted' characters. + mntpnt=$(printf '%b\n' "$mntpnt" | sed -e 's,/,,g' \ + -e 's,-,,g' -e 's,\.,,g' -e 's, ,,g') + local var + + var="$(eval echo MTAB_$mntpnt)" + [ "$(eval echo "$""$var")" != "" ] + return "$?" +} + +# first parameter is a regular expression that filters fstab +read_fstab() +{ + local match="$1" + local i var TMPFILE + + # Unset all FSTAB_* variables + unset $(env | grep ^FSTAB_ | sed 's,=.*,,') + + i=0 + while read -r fs mntpnt fstype opts; do + echo "$fs" | egrep -qE '^#|^$' && continue + echo "$mntpnt" | egrep -qE '^none|^swap' && continue + echo "$fstype" | egrep -qE '^swap' && continue + + if echo "$fs $mntpnt $fstype $opts" | grep -qE "$match"; then + eval export FSTAB_dev_$i="$fs" + fs=$(printf '%b\n' "$fs" | sed 's,/,_,g') + eval export FSTAB_$i="$mntpnt" + + i=$((i + 1)) + fi + done < /etc/fstab +} + +in_fstab() +{ + local var + + var="$(eval echo FSTAB_$1)" + [ "${var}" != "" ] + return $? +} + +is_mounted() +{ + local mntpt="$1" + local line + + mount | \ + while read line; do + if echo "$line" | grep -q " on $mntpt "; then + # returns: + # 0 on unsuccessful match + # 1 on a successful match + return 1 + fi + done + + # The negation will flip the subshell return result where the default + # return value is 0 when a match is not found. + return $(( !$? )) +} -- cgit v1.2.3