From 2a9c6b81292b03502b069b28095d00fd58d68172 Mon Sep 17 00:00:00 2001 From: James Lee Date: Fri, 18 Sep 2015 17:24:29 -0400 Subject: [PATCH] zfs-import: Use cache file to reimport pools at boot This change modifies the import service to use the default cache file to reimport pools at boot. This fixes code that exhaustively searched the entire system and imported all visible pools. Using the cache file is in keeping with the way ZFS has always worked, and is how it is written in the man page (zpool(1M,8)): All pools in this cache are automatically imported when the system boots. Importantly, the cache contains important information for importing multipath devices, and helps control which pools get imported in more dynamic environments like SANs, which may have thousands of visible and constantly changing pools, which the ZFS_POOL_EXCEPTIONS variable is not equipped to handle. The change also stops the service from exporting pools at shutdown. Exporting pools is only meant to be performed by the administrator of the system. Closes #3777 Closes #3526 --- etc/init.d/zfs-import.in | 264 ++------------------------------------- etc/init.d/zfs.in | 11 -- 2 files changed, 12 insertions(+), 263 deletions(-) diff --git a/etc/init.d/zfs-import.in b/etc/init.d/zfs-import.in index a3d6c1442cee..5251e39b121f 100755 --- a/etc/init.d/zfs-import.in +++ b/etc/init.d/zfs-import.in @@ -1,11 +1,10 @@ #!@SHELL@ # -# zfs-import This script will import/export zfs pools. +# zfs-import This script will reimport ZFS pools. # # chkconfig: 2345 01 99 -# description: This script will import/export zfs pools during system -# boot/shutdown. -# It is also responsible for all userspace zfs services. +# description: This script will reimport previously imported ZFS pools +# during system boot. # probe: true # ### BEGIN INIT INFO @@ -16,8 +15,8 @@ # Default-Stop: 0 1 6 # X-Start-Before: checkfs # X-Stop-After: zfs-mount -# Short-Description: Import ZFS pools -# Description: Run the `zpool import` or `zpool export` commands. +# Short-Description: Reimport ZFS pools +# Description: Run the `zpool import` command. ### END INIT INFO # # NOTE: Not having '$local_fs' on Required-Start but only on Required-Stop @@ -43,246 +42,16 @@ do_depend() keyword -lxc -openvz -prefix -vserver } -# Support function to get a list of all pools, separated with ';' -find_pools() -{ - local CMD="$*" - local pools - - pools=$($CMD 2> /dev/null | \ - grep -E "pool:|^[a-zA-Z0-9]" | \ - sed 's@.*: @@' | \ - sort | \ - while read pool; do \ - echo -n "$pool;" - done) - - echo "${pools%%;}" # Return without the last ';'. -} - -# Import all pools +# Reimport all previously imported pools do_import() { - local already_imported available_pools pool npools - local exception dir ZPOOL_IMPORT_PATH RET=0 r=1 - - # In case not shutdown cleanly. - [ -n "$init" ] && rm -f /etc/dfs/sharetab - - # Just simplify code later on. - if [ -n "$USE_DISK_BY_ID" -a "$USE_DISK_BY_ID" != 'yes' ] - then - # It's something, but not 'yes' so it's no good to us. - unset USE_DISK_BY_ID - fi - - # Find list of already imported pools. - already_imported=$(find_pools "$ZPOOL" list -H -oname) - available_pools=$(find_pools "$ZPOOL" import) - - # Just in case - seen it happen (that a pool isn't visable/found - # with a simple "zpool import" but only when using the "-d" - # option or setting ZPOOL_IMPORT_PATH). - if [ -d "/dev/disk/by-id" ] - then - npools=$(find_pools "$ZPOOL" import -d /dev/disk/by-id) - if [ -n "$npools" ] - then - # Because we have found extra pool(s) here, which wasn't - # found 'normaly', we need to force USE_DISK_BY_ID to - # make sure we're able to actually import it/them later. - USE_DISK_BY_ID='yes' - - if [ -n "$available_pools" ] - then - # Filter out duplicates (pools found with the simpl - # "zpool import" but which is also found with the - # "zpool import -d ..."). - npools=$(echo "$npools" | sed "s,$available_pools,,") - - # Add the list to the existing list of - # available pools - available_pools="$available_pools;$npools" - else - available_pools="$npools" - fi - fi - fi - - # Filter out any exceptions... - if [ -n "$ZFS_POOL_EXCEPTIONS" ] - then - local found="" - local apools="" - OLD_IFS="$IFS" ; IFS=";" - - for pool in $available_pools - do - for exception in $ZFS_POOL_EXCEPTIONS - do - [ "$pool" = "$exception" ] && continue 2 - found="$pool" - done - - if [ -n "$found" ] - then - if [ -n "$apools" ] - then - apools="$apools;$pool" - else - apools="$pool" - fi - fi - done - - IFS="$OLD_IFS" - available_pools="$apools" - fi - - # For backwards compability, make sure that ZPOOL_IMPORT_PATH is set - # to something we can use later with the real import(s). We want to - # make sure we find all by* dirs, BUT by-vdev should be first (if it - # exists). - if [ -n "$USE_DISK_BY_ID" -a -z "$ZPOOL_IMPORT_PATH" ] + if [ -f "$ZPOOL_CACHE" ] then - local dirs - dirs="$(for dir in $(echo /dev/disk/by-*) - do - # Ignore by-vdev here - we wan't it first! - echo "$dir" | grep -q /by-vdev && continue - [ ! -d "$dir" ] && continue - - echo -n "$dir:" - done | sed 's,:$,,g')" - - if [ -d "/dev/disk/by-vdev" ] - then - # Add by-vdev at the beginning. - ZPOOL_IMPORT_PATH="/dev/disk/by-vdev:" - fi - - # Help with getting LUKS partitions etc imported. - if [ -d "/dev/mapper" ]; then - if [ -n "$ZPOOL_IMPORT_PATH" ]; then - ZPOOL_IMPORT_PATH="$ZPOOL_IMPORT_PATH:/dev/mapper:" - else - ZPOOL_IMPORT_PATH="/dev/mapper:" - fi - fi - - # ... and /dev at the very end, just for good measure. - ZPOOL_IMPORT_PATH="$ZPOOL_IMPORT_PATH$dirs:/dev" + zfs_action "Reimporting ZFS pool(s)" \ + "$ZPOOL" import -c "$ZPOOL_CACHE" -N -a fi - # Needs to be exported for "zpool" to catch it. - [ -n "$ZPOOL_IMPORT_PATH" ] && export ZPOOL_IMPORT_PATH - - # Mount all availible pools (except those set in ZFS_POOL_EXCEPTIONS. - # - # If not interactive (run from init - variable init='/sbin/init') - # we get ONE line for all pools being imported, with just a dot - # as status for each pool. - # Example: Importing ZFS pool(s)... [OK] - # - # If it IS interactive (started from the shell manually), then we - # get one line per pool importing. - # Example: Importing ZFS pool pool1 [OK] - # Importing ZFS pool pool2 [OK] - # [etc] - [ -n "$init" ] && zfs_log_begin_msg "Importing ZFS pool(s)" - OLD_IFS="$IFS" ; IFS=";" - for pool in $available_pools - do - [ -z "$pool" ] && continue - - # We have pools that haven't been imported - import them - if [ -n "$init" ] - then - # Not interactive - a dot for each pool. - # Except on Gentoo where this doesn't work. - zfs_log_progress_msg "." - else - # Interactive - one 'Importing ...' line per pool - zfs_log_begin_msg "Importing ZFS pool $pool" - fi - - # Import by using ZPOOL_IMPORT_PATH (either set above or in - # the config file) _or_ with the 'built in' default search - # paths. This is the prefered way. - "$ZPOOL" import -N "$pool" 2> /dev/null - r="$?" ; RET=$((RET + r)) - if [ "$r" -eq 0 ] - then - # Output success and process the next pool - [ -z "$init" ] && zfs_log_end_msg 0 - continue - fi - # We don't want a fail msg here, we're going to try import - # using the cache file soon and that might succeed. - [ ! -f "$ZPOOL_CACHE" ] && zfs_log_end_msg "$RET" - - if [ "$r" -gt 0 -a -f "$ZPOOL_CACHE" ] - then - # Failed to import without a cache file. Try WITH... - if [ -z "$init" -a "$VERBOSE_MOUNT" = 'yes' ] - then - # Interactive + Verbose = more information - zfs_log_progress_msg " using cache file" - fi - - "$ZPOOL" import -c "$ZPOOL_CACHE" -N "$pool" 2> /dev/null - r="$?" ; RET=$((RET + r)) - if [ "$r" -eq 0 ] - then - [ -z "$init" ] && zfs_log_end_msg 0 - continue 3 # Next pool - fi - zfs_log_end_msg "$RET" - fi - done - [ -n "$init" ] && zfs_log_end_msg "$RET" - - IFS="$OLD_IFS" - [ -n "$already_imported" -a -z "$available_pools" ] && return 0 - - return "$RET" -} - -# Export all pools -do_export() -{ - local already_imported pool root_pool RET r - RET=0 - - root_pool=$(get_root_pool) - - [ -n "$init" ] && zfs_log_begin_msg "Exporting ZFS pool(s)" - - # Find list of already imported pools. - already_imported=$(find_pools "$ZPOOL" list -H -oname) - - OLD_IFS="$IFS" ; IFS=";" - for pool in $already_imported; do - [ "$pool" = "$root_pool" ] && continue - - if [ -z "$init" ] - then - # Interactive - one 'Importing ...' line per pool - zfs_log_begin_msg "Exporting ZFS pool $pool" - else - # Not interactive - a dot for each pool. - zfs_log_progress_msg "." - fi - - "$ZPOOL" export "$pool" - r="$?" ; RET=$((RET + r)) - [ -z "$init" ] && zfs_log_end_msg "$r" - done - IFS="$OLD_IFS" - - [ -n "$init" ] && zfs_log_end_msg "$RET" - - return "$RET" + return 0 } # Output the status and list of pools @@ -324,14 +93,6 @@ do_start() fi } -do_stop() -{ - # Check to see if the module is even loaded. - check_module_loaded "zfs" || exit 0 - - do_export -} - # ---------------------------------------------------- if [ ! -e /etc/gentoo-release ] @@ -341,7 +102,7 @@ then do_start ;; stop) - do_stop + # no-op ;; status) do_status @@ -351,7 +112,7 @@ then ;; *) [ -n "$1" ] && echo "Error: Unknown command $1." - echo "Usage: $0 {start|stop|status}" + echo "Usage: $0 {start|status}" exit 3 ;; esac @@ -361,6 +122,5 @@ else # Create wrapper functions since Gentoo don't use the case part. depend() { do_depend; } start() { do_start; } - stop() { do_stop; } status() { do_status; } fi diff --git a/etc/init.d/zfs.in b/etc/init.d/zfs.in index d81abfef56c4..0a770d55896d 100644 --- a/etc/init.d/zfs.in +++ b/etc/init.d/zfs.in @@ -13,13 +13,6 @@ ZFS_SHARE='yes' # Run `zfs unshare -a` during system stop? ZFS_UNSHARE='yes' -# 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" - # Should the datasets be mounted verbosely? # A mount counter will be used when mounting if set to 'yes'. VERBOSE_MOUNT='no' @@ -73,10 +66,6 @@ ZFS_INITRD_POST_MODPROBE_SLEEP='0' # Example: If root FS is 'rpool/ROOT/rootfs', this would make sense. #ZFS_INITRD_ADDITIONAL_DATASETS="rpool/ROOT/usr rpool/ROOT/var" -# List of pools that should NOT be imported at boot? -# This is a space separated list. -#ZFS_POOL_EXCEPTIONS="test2" - # Optional arguments for the ZFS Event Daemon (ZED). # See zed(8) for more information on available options. #ZED_ARGS="-M"