]> git.proxmox.com Git - mirror_zfs.git/commitdiff
Add 'zpool split' coverage to the ZFS Test Suite
authorLOLi <loli10K@users.noreply.github.com>
Thu, 12 Apr 2018 17:57:24 +0000 (19:57 +0200)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Thu, 12 Apr 2018 17:57:24 +0000 (10:57 -0700)
This change adds five new tests to the ZTS:

 * zpool_split_cliargs: verify command line options and arguments
 * zpool_split_devices: verify zpool split accepts a device list
 * zpool_split_encryption: verify zpool can split encrypted pools
 * zpool_split_props: verify zpool split can set property values
 * zpool_split_vdevs: verify vdev layout when splitting the pool

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: loli10K <ezomori.nozomu@gmail.com>
Closes #7409

12 files changed:
configure.ac
lib/libzfs/libzfs_pool.c
tests/runfiles/linux.run
tests/zfs-tests/tests/functional/cli_root/Makefile.am
tests/zfs-tests/tests/functional/cli_root/zpool_split/Makefile.am [new file with mode: 0644]
tests/zfs-tests/tests/functional/cli_root/zpool_split/cleanup.ksh [new file with mode: 0755]
tests/zfs-tests/tests/functional/cli_root/zpool_split/setup.ksh [new file with mode: 0755]
tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_cliargs.ksh [new file with mode: 0755]
tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_devices.ksh [new file with mode: 0755]
tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_encryption.ksh [new file with mode: 0755]
tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_props.ksh [new file with mode: 0755]
tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_vdevs.ksh [new file with mode: 0755]

index 0893af42ed5ecc2ae936203c10b3a794a22bf1cd..4f180fe53db20a4484ccbf3f85efc44019ed79ff 100644 (file)
@@ -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
index 9659e08b77c85e0abbcfe1b1600321deb29dbfe5..3fe0b9e0ee44c6968e1c0be1bc286eca1d6c2327 100644 (file)
@@ -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,
index b53817b8ba17ea26f4fe4884caba383a2908c1df..9af97b81f19de6a799f78cfdd844a0dac31f6c59 100644 (file)
@@ -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',
index 7ded5f41f5fb49ec2e42ae17b047471fb01f2f42..d34b408774fe306a4ad09b6651caa7f58b2c28fd 100644 (file)
@@ -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 (file)
index 0000000..863d1a0
--- /dev/null
@@ -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 (executable)
index 0000000..e78deac
--- /dev/null
@@ -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 <ezomori.nozomu@gmail.com>. 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 (executable)
index 0000000..4497dbd
--- /dev/null
@@ -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 <ezomori.nozomu@gmail.com>. 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 (executable)
index 0000000..4a779a2
--- /dev/null
@@ -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 <ezomori.nozomu@gmail.com>. 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 (executable)
index 0000000..c9e9d80
--- /dev/null
@@ -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 <ezomori.nozomu@gmail.com>. 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 (executable)
index 0000000..dc686c7
--- /dev/null
@@ -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 <ezomori.nozomu@gmail.com>. 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 (executable)
index 0000000..90cde54
--- /dev/null
@@ -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 <ezomori.nozomu@gmail.com>. 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 (executable)
index 0000000..6403233
--- /dev/null
@@ -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 <ezomori.nozomu@gmail.com>. 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"