diff options
12 files changed, 529 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac index 0893af42e..4f180fe53 100644 --- a/configure.ac +++ b/configure.ac @@ -243,6 +243,7 @@ AC_CONFIG_FILES([ tests/zfs-tests/tests/functional/cli_root/zpool_replace/Makefile tests/zfs-tests/tests/functional/cli_root/zpool_scrub/Makefile tests/zfs-tests/tests/functional/cli_root/zpool_set/Makefile + tests/zfs-tests/tests/functional/cli_root/zpool_split/Makefile tests/zfs-tests/tests/functional/cli_root/zpool_status/Makefile tests/zfs-tests/tests/functional/cli_root/zpool_sync/Makefile tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/Makefile diff --git a/lib/libzfs/libzfs_pool.c b/lib/libzfs/libzfs_pool.c index 9659e08b7..3fe0b9e0e 100644 --- a/lib/libzfs/libzfs_pool.c +++ b/lib/libzfs/libzfs_pool.c @@ -3019,7 +3019,7 @@ zpool_vdev_split(zpool_handle_t *zhp, char *newname, nvlist_t **newroot, nvlist_t **varray = NULL, *zc_props = NULL; uint_t c, children, newchildren, lastlog = 0, vcount, found = 0; libzfs_handle_t *hdl = zhp->zpool_hdl; - uint64_t vers; + uint64_t vers, readonly = B_FALSE; boolean_t freelist = B_FALSE, memory_err = B_TRUE; int retval = 0; @@ -3044,6 +3044,14 @@ zpool_vdev_split(zpool_handle_t *zhp, char *newname, nvlist_t **newroot, if ((zc_props = zpool_valid_proplist(hdl, zhp->zpool_name, props, vers, flags, msg)) == NULL) return (-1); + (void) nvlist_lookup_uint64(zc_props, + zpool_prop_to_name(ZPOOL_PROP_READONLY), &readonly); + if (readonly) { + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, + "property %s can only be set at import time"), + zpool_prop_to_name(ZPOOL_PROP_READONLY)); + return (-1); + } } if (nvlist_lookup_nvlist_array(tree, ZPOOL_CONFIG_CHILDREN, &child, diff --git a/tests/runfiles/linux.run b/tests/runfiles/linux.run index b53817b8b..9af97b81f 100644 --- a/tests/runfiles/linux.run +++ b/tests/runfiles/linux.run @@ -407,6 +407,11 @@ tests = ['zpool_set_001_pos', 'zpool_set_002_neg', 'zpool_set_003_neg', 'zpool_set_ashift', 'zpool_set_features'] tags = ['functional', 'cli_root', 'zpool_set'] +[tests/functional/cli_root/zpool_split] +tests = ['zpool_split_cliargs', 'zpool_split_devices', + 'zpool_split_encryption', 'zpool_split_props', 'zpool_split_vdevs'] +tags = ['functional', 'cli_root', 'zpool_split'] + [tests/functional/cli_root/zpool_status] tests = ['zpool_status_001_pos', 'zpool_status_002_pos','zpool_status_003_pos', 'zpool_status_-c_disable', 'zpool_status_-c_homedir', diff --git a/tests/zfs-tests/tests/functional/cli_root/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/Makefile.am index 7ded5f41f..d34b40877 100644 --- a/tests/zfs-tests/tests/functional/cli_root/Makefile.am +++ b/tests/zfs-tests/tests/functional/cli_root/Makefile.am @@ -52,6 +52,7 @@ SUBDIRS = \ zpool_replace \ zpool_scrub \ zpool_set \ + zpool_split \ zpool_status \ zpool_sync \ zpool_upgrade diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_split/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool_split/Makefile.am new file mode 100644 index 000000000..863d1a059 --- /dev/null +++ b/tests/zfs-tests/tests/functional/cli_root/zpool_split/Makefile.am @@ -0,0 +1,12 @@ +include $(top_srcdir)/config/Rules.am + +pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zpool_split + +dist_pkgdata_SCRIPTS = \ + cleanup.ksh \ + setup.ksh \ + zpool_split_cliargs.ksh \ + zpool_split_devices.ksh \ + zpool_split_encryption.ksh \ + zpool_split_props.ksh \ + zpool_split_vdevs.ksh diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_split/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_split/cleanup.ksh new file mode 100755 index 000000000..e78deacd5 --- /dev/null +++ b/tests/zfs-tests/tests/functional/cli_root/zpool_split/cleanup.ksh @@ -0,0 +1,19 @@ +#!/bin/ksh -p +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2018, loli10K <[email protected]>. All rights reserved. +# + +. $STF_SUITE/include/libtest.shlib + +default_cleanup diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_split/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_split/setup.ksh new file mode 100755 index 000000000..4497dbd74 --- /dev/null +++ b/tests/zfs-tests/tests/functional/cli_root/zpool_split/setup.ksh @@ -0,0 +1,17 @@ +#!/bin/ksh -p +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2018, loli10K <[email protected]>. All rights reserved. +# + +. $STF_SUITE/include/libtest.shlib diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_cliargs.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_cliargs.ksh new file mode 100755 index 000000000..4a779a225 --- /dev/null +++ b/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_cliargs.ksh @@ -0,0 +1,79 @@ +#!/bin/ksh -p +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2018, loli10K <[email protected]>. All rights reserved. +# + +. $STF_SUITE/include/libtest.shlib + +# +# DESCRIPTION: +# 'zpool split' should only work with supported options and parameters. +# +# STRATEGY: +# 1. Verify every supported option is accepted +# 2. Verify other unsupported options raise an error +# 3. Verify we cannot split a pool if the destination already exists +# + +verify_runnable "both" + +function cleanup +{ + destroy_pool $TESTPOOL + destroy_pool $TESTPOOL2 + rm -f $DEVICE1 $DEVICE2 $DEVICE3 +} + +function setup_mirror +{ + truncate -s $SPA_MINDEVSIZE $DEVICE1 + truncate -s $SPA_MINDEVSIZE $DEVICE2 + log_must zpool create -f $TESTPOOL mirror $DEVICE1 $DEVICE2 +} + +log_assert "'zpool split' should only work with supported options and parameters." +log_onexit cleanup + +typeset goodopts=( + "" "-g" "-L" "-n" "-P" "-o comment=ok" "-o ro -R /mnt" "-l -R /mnt" "-gLnP") +typeset badopts=( + "-f" "-h" "-x" "-Pp" "-l" "-G" "-o" "-o ro" "-o comment" "-R" "-R dir" "=") + +DEVICE1="$TEST_BASE_DIR/device-1" +DEVICE2="$TEST_BASE_DIR/device-2" +DEVICE3="$TEST_BASE_DIR/device-3" + +# 1. Verify every supported option and/or parameter is accepted +for opt in "${goodopts[@]}" +do + setup_mirror + log_must zpool split $opt $TESTPOOL $TESTPOOL2 + cleanup +done + +# 2. Verify other unsupported options and/or parameters raise an error +setup_mirror +for opt in "${badopts[@]}" +do + log_mustnot zpool split $opt $TESTPOOL $TESTPOOL2 +done +cleanup + +# 3. Verify we cannot split a pool if the destination already exists +setup_mirror +truncate -s $SPA_MINDEVSIZE $DEVICE3 +log_must zpool create $TESTPOOL2 $DEVICE3 +log_mustnot zpool split $TESTPOOL $TESTPOOL2 + +log_pass "'zpool split' only works with supported options and parameters." diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_devices.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_devices.ksh new file mode 100755 index 000000000..c9e9d807b --- /dev/null +++ b/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_devices.ksh @@ -0,0 +1,100 @@ +#!/bin/ksh -p +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2018, loli10K <[email protected]>. All rights reserved. +# + +. $STF_SUITE/include/libtest.shlib + +# +# DESCRIPTION: +# 'zpool split' should use the provided devices to split the pool +# +# STRATEGY: +# 1. Create various (mirror-only) pools +# 2. Verify 'zpool split' can provide a list of devices to be included in the +# new pool. At most one disk from each mirror can be specified. +# + +verify_runnable "both" + +function cleanup +{ + destroy_pool $TESTPOOL + destroy_pool $TESTPOOL2 + rm -f $FILEDEV_PREFIX* +} + +function setup_mirror # <conf> +{ + for filedev in "${fd[@]}"; do + truncate -s $SPA_MINDEVSIZE "$filedev" + done + log_must zpool create -f $TESTPOOL $conf +} + +log_assert "'zpool split' should use the provided devices to split the pool" +log_onexit cleanup + +typeset altroot="$TESTDIR/altroot-$TESTPOOL2" +typeset FILEDEV_PREFIX="$TEST_BASE_DIR/filedev" +typeset -A fd +fd[01]="$FILEDEV_PREFIX-01" +fd[02]="$FILEDEV_PREFIX-02" +fd[03]="$FILEDEV_PREFIX-03" +fd[11]="$FILEDEV_PREFIX-11" +fd[12]="$FILEDEV_PREFIX-12" +fd[13]="$FILEDEV_PREFIX-13" + +# Base pool configurations +typeset poolconfs=("mirror ${fd[01]} ${fd[02]}" + "mirror ${fd[01]} ${fd[02]} ${fd[03]}" + "mirror ${fd[01]} ${fd[02]} mirror ${fd[11]} ${fd[12]}" + "mirror ${fd[01]} ${fd[02]} ${fd[03]} mirror ${fd[11]} ${fd[12]}" + "mirror ${fd[01]} ${fd[02]} mirror ${fd[11]} ${fd[12]} ${fd[13]}" + "mirror ${fd[01]} ${fd[02]} ${fd[03]} mirror ${fd[11]} ${fd[12]} ${fd[13]}" +) +# "good" device specifications +typeset gooddevs=("${fd[01]}" + "${fd[02]}" + "${fd[02]} ${fd[11]}" + "${fd[12]}" + "${fd[02]}" + "${fd[03]} ${fd[12]}" +) +# "bad" device specifications +typeset baddevs=("${fd[01]} ${fd[02]}" + "${fd[02]} ${fd[03]}" + "${fd[02]} baddev" + "baddev ${fd[11]}" + "${fd[11]} ${fd[12]} ${fd[13]}" + "${fd[01]} ${fd[02]} ${fd[13]}" +) + +typeset -i i=0; +while [ $i -lt "${#poolconfs[@]}" ] +do + typeset conf=${poolconfs[$i]} + setup_mirror $conf + log_mustnot zpool split $TESTPOOL $TESTPOOL2 ${baddevs[$i]} + log_must zpool split -R $altroot $TESTPOOL $TESTPOOL2 ${gooddevs[$i]} + # Verify "good" devices ended up in the new pool + log_must poolexists $TESTPOOL2 + for filedev in ${gooddevs[$i]}; do + log_must check_vdev_state $TESTPOOL2 $filedev "" + done + cleanup + ((i = i + 1)) +done + +log_pass "'zpool split' can use the provided devices to split the pool" diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_encryption.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_encryption.ksh new file mode 100755 index 000000000..dc686c73f --- /dev/null +++ b/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_encryption.ksh @@ -0,0 +1,58 @@ +#!/bin/ksh -p +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2018, loli10K <[email protected]>. All rights reserved. +# + +. $STF_SUITE/include/libtest.shlib + +# +# DESCRIPTION: +# 'zpool split' should be able to split encrypted pools +# +# STRATEGY: +# 1. Create an encrypted pool +# 2. Split and re-import the pool, verify altroot is mounted. +# + +verify_runnable "both" + +function cleanup +{ + destroy_pool $TESTPOOL + destroy_pool $TESTPOOL2 + rm -f $DEVICE1 $DEVICE2 +} + +log_assert "'zpool split' should be able to split encrypted pools" +log_onexit cleanup + +DEVICE1="$TEST_BASE_DIR/device-1" +DEVICE2="$TEST_BASE_DIR/device-2" +passphrase="password" +altroot="$TESTDIR/zpool-split-$RANDOM" + +# 1. Create an encrypted pool +truncate -s $SPA_MINDEVSIZE $DEVICE1 +truncate -s $SPA_MINDEVSIZE $DEVICE2 +log_must eval "echo "$passphrase" | zpool create -O encryption=aes-256-ccm " \ + "-O keyformat=passphrase $TESTPOOL mirror $DEVICE1 $DEVICE2" + +# 2. Split and re-import the pool, verify altroot is mounted. +log_must eval "echo "$passphrase" | zpool split -l -R $altroot " \ + "$TESTPOOL $TESTPOOL2" +log_must test "$(get_prop 'encryption' $TESTPOOL2)" == "aes-256-ccm" +log_must test "$(get_pool_prop 'altroot' $TESTPOOL2)" == "$altroot" +log_must mounted $altroot/$TESTPOOL2 + +log_pass "'zpool split' can split encrypted pools" diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_props.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_props.ksh new file mode 100755 index 000000000..90cde544e --- /dev/null +++ b/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_props.ksh @@ -0,0 +1,83 @@ +#!/bin/ksh -p +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2018, loli10K <[email protected]>. All rights reserved. +# + +. $STF_SUITE/include/libtest.shlib + +# +# DESCRIPTION: +# 'zpool split' can set new property values on the new pool +# +# STRATEGY: +# 1. Create a mirror pool +# 2. Verify 'zpool split' can set property values on the new pool, but only if +# they are valid. +# + +verify_runnable "both" + +function cleanup +{ + destroy_pool $TESTPOOL + destroy_pool $TESTPOOL2 + rm -f $DEVICE1 $DEVICE2 +} + +function setup_mirror +{ + truncate -s $SPA_MINDEVSIZE $DEVICE1 + truncate -s $SPA_MINDEVSIZE $DEVICE2 + log_must zpool create -f $TESTPOOL mirror $DEVICE1 $DEVICE2 +} + +log_assert "'zpool split' can set new property values on the new pool" +log_onexit cleanup + +typeset good_props=('comment=text' 'ashift=12' 'multihost=on' + 'listsnapshots=on' 'autoexpand=on' 'autoreplace=on' 'dedupditto=1234' + 'delegation=off' 'failmode=continue') +typeset bad_props=("bootfs=$TESTPOOL2/bootfs" 'version=28' 'ashift=4' + 'allocated=1234' 'capacity=5678' 'dedupditto=42' 'multihost=none' + 'feature@async_destroy=disabled' 'feature@xxx_fake_xxx=enabled' + 'propname=propval' 'readonly=on') + +DEVICE1="$TEST_BASE_DIR/device-1" +DEVICE2="$TEST_BASE_DIR/device-2" + +# Needed to set multihost=on +zgenhostid + +# Verify we can set a combination of valid property values on the new pool +for prop in "${good_props[@]}" +do + propname="$(awk -F= '{print $1}' <<< $prop)" + propval="$(awk -F= '{print $2}' <<< $prop)" + setup_mirror + log_must zpool split -o $prop $TESTPOOL $TESTPOOL2 + log_must zpool import -N -d $TEST_BASE_DIR $TESTPOOL2 + log_must test "$(get_pool_prop $propname $TESTPOOL2)" == "$propval" + cleanup +done + +# Verify we cannot set invalid property values +setup_mirror +zfs create $TESTPOOL/bootfs +for prop in "${bad_props[@]}" +do + log_mustnot zpool split -o $prop $TESTPOOL $TESTPOOL2 + log_mustnot zpool import -N -d $TEST_BASE_DIR $TESTPOOL2 +done + +log_pass "'zpool split' can set new property values on the new pool" diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_vdevs.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_vdevs.ksh new file mode 100755 index 000000000..64032331a --- /dev/null +++ b/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_vdevs.ksh @@ -0,0 +1,145 @@ +#!/bin/ksh -p +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2018, loli10K <[email protected]>. All rights reserved. +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/include/math.shlib + +# +# DESCRIPTION: +# 'zpool split' should only work on mirrors. Every other VDEV layout is not +# supported. +# +# STRATEGY: +# Create pools with various VDEV layouts and verify only mirrors can be split +# + +verify_runnable "both" + +function cleanup +{ + destroy_pool $TESTPOOL + destroy_pool $TESTPOOL2 + rm -f $FILEDEV_PREFIX* +} + +# +# Given a vdev type generate a pool configuration which can be immediately +# used as "zpool create $poolname $config" or "zpool add $poolname $config". +# Supported vdev types are: +# "d" - single disk +# "t" - stripe +# "m" - mirror +# "m3" - 3-way mirror +# "z1" - raidz1 +# "z2" - raidz2 +# "z3" - raidz3 +# "s" - spare +# "l" - log +# "ll" - mirrored log +# "c" - cache +# +function pool_config # <vdev-type> +{ + typeset config="" + typeset -A disks + disks[d]="d1" + disks[t]="t1 t2" + disks[m]="m1 m2" + disks[m3]="m1 m2 m3" + disks[z1]="z1 z2" + disks[z2]="z1 z2 z3" + disks[z3]="z1 z2 z3 z4" + disks[s]="s1" + disks[l]="l1" + disks[ll]="l1 l2" + disks[c]="c1" + case $1 in + d|t) # single disk or stripe + vdev='' ;; + m|m3) # 2-way or 3-way mirror + vdev='mirror';; + z1) # raidz1 + vdev='raidz1';; + z2) # raidz2 + vdev='raidz2';; + z3) # raidz3 + vdev='raidz3';; + s) # spare + vdev='spare';; + l) # log + vdev='log';; + ll) # mirrored log + vdev='log mirror';; + c) # cache + vdev='cache';; + *) + log_fail "setup_pool: unsupported vdev type '$1'" + esac + config="$vdev" + for tok in ${disks[$1]}; do + filedev="$FILEDEV_PREFIX-$tok" + # if $filedev exists we are requesting the same vdev type twice + # in a row (eg. pool of striped mirrors): add a random suffix. + while [[ -f $filedev ]]; do + filedev="$filedev.$RANDOM" + done + truncate -s $SPA_MINDEVSIZE "$filedev" + config="$config $filedev" + done + echo "$config" +} + +log_assert "'zpool split' should work only on mirror VDEVs" +log_onexit cleanup + +# "good" and "bad" pool layouts +# first token is always used with "zpool create" +# second to last tokens, if any, are used with "zpool add" +typeset -a goodconfs=("m" "m l" "m s" "m c" "m m" "m3" "m3 m3" "m m3 l s c") +typeset -a badconfs=("d" "z1" "z2" "z3" "m d" "m3 d" "m z1" "m z2" "m z3") +typeset FILEDEV_PREFIX="$TEST_BASE_DIR/filedev" +typeset altroot="$TESTDIR/altroot-$TESTPOOL2" + +# Create pools with various VDEV layouts and verify only mirrors can be split +for config in "${goodconfs[@]}" +do + create_config="${config%% *}" + add_config="$(awk '{$1= "";print $0}' <<< $config)" + log_must zpool create $TESTPOOL $(pool_config $create_config) + for vdev in $add_config; do + log_must zpool add $TESTPOOL -f $(pool_config $vdev) + done + log_must zpool split -R $altroot $TESTPOOL $TESTPOOL2 + log_must poolexists $TESTPOOL2 + log_must test "$(get_pool_prop 'altroot' $TESTPOOL2)" == "$altroot" + cleanup +done + +# Every other pool layout should *not* be splittable +for config in "${badconfs[@]}" +do + create_config="${config%% *}" + add_config="$(awk '{$1= "";print $0}' <<< $config)" + log_must zpool create $TESTPOOL $(pool_config $create_config) + for vdev in $add_config; do + log_must zpool add $TESTPOOL -f $(pool_config $vdev) + done + log_mustnot zpool split -R $altroot $TESTPOOL $TESTPOOL2 + log_mustnot poolexists $TESTPOOL2 + cleanup +done + +log_pass "'zpool split' works only on mirror VDEVs" |