diff --git a/module/zfs/vdev_removal.c b/module/zfs/vdev_removal.c index 4ce7b559e11c..549087163a58 100644 --- a/module/zfs/vdev_removal.c +++ b/module/zfs/vdev_removal.c @@ -22,6 +22,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, 2019 by Delphix. All rights reserved. + * Copyright (c) 2019, loli10K . All rights reserved. */ #include @@ -1964,6 +1965,9 @@ spa_vdev_remove_top_check(vdev_t *vd) if (vd != vd->vdev_top) return (SET_ERROR(ENOTSUP)); + if (!vdev_is_concrete(vd)) + return (SET_ERROR(ENOTSUP)); + if (!spa_feature_is_enabled(spa, SPA_FEATURE_DEVICE_REMOVAL)) return (SET_ERROR(ENOTSUP)); diff --git a/tests/runfiles/linux.run b/tests/runfiles/linux.run index 6f015b3b31b9..3e39c165eedc 100644 --- a/tests/runfiles/linux.run +++ b/tests/runfiles/linux.run @@ -794,7 +794,8 @@ tests = ['removal_all_vdev', 'removal_cancel', 'removal_check_space', 'removal_with_remove', 'removal_with_scrub', 'removal_with_send', 'removal_with_send_recv', 'removal_with_snapshot', 'removal_with_write', 'removal_with_zdb', 'remove_expanded', - 'remove_mirror', 'remove_mirror_sanity', 'remove_raidz'] + 'remove_mirror', 'remove_mirror_sanity', 'remove_raidz', + 'remove_indirect'] tags = ['functional', 'removal'] [tests/functional/rename_dirs] diff --git a/tests/zfs-tests/tests/functional/removal/Makefile.am b/tests/zfs-tests/tests/functional/removal/Makefile.am index 686f690e28fa..4cc773463356 100644 --- a/tests/zfs-tests/tests/functional/removal/Makefile.am +++ b/tests/zfs-tests/tests/functional/removal/Makefile.am @@ -29,7 +29,7 @@ dist_pkgdata_SCRIPTS = \ removal_with_send.ksh removal_with_send_recv.ksh \ removal_with_snapshot.ksh removal_with_write.ksh \ removal_with_zdb.ksh remove_mirror.ksh remove_mirror_sanity.ksh \ - remove_raidz.ksh remove_expanded.ksh + remove_raidz.ksh remove_expanded.ksh remove_indirect.ksh dist_pkgdata_DATA = \ removal.kshlib diff --git a/tests/zfs-tests/tests/functional/removal/remove_indirect.ksh b/tests/zfs-tests/tests/functional/removal/remove_indirect.ksh new file mode 100755 index 000000000000..c4ba0d9ac564 --- /dev/null +++ b/tests/zfs-tests/tests/functional/removal/remove_indirect.ksh @@ -0,0 +1,58 @@ +#!/bin/ksh -p +# +# CDDL HEADER START +# +# 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. +# +# CDDL HEADER END +# + +# +# Copyright 2019, loli10K . All rights reserved. +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/removal/removal.kshlib + +# +# DESCRIPTION: +# Device removal cannot remove non-concrete vdevs +# +# STRATEGY: +# 1. Create a pool with removable devices +# 2. Remove a top-level device +# 3. Verify we can't remove the "indirect" vdev created by the first removal +# + +verify_runnable "global" + +function cleanup +{ + destroy_pool $TESTPOOL + log_must rm -f $TEST_BASE_DIR/device-{1,2,3} +} + +log_assert "Device removal should not be able to remove non-concrete vdevs" +log_onexit cleanup + +# 1. Create a pool with removable devices +truncate -s $MINVDEVSIZE $TEST_BASE_DIR/device-{1,2,3} +zpool create $TESTPOOL $TEST_BASE_DIR/device-{1,2,3} + +# 2. Remove a top-level device +log_must zpool remove $TESTPOOL $TEST_BASE_DIR/device-1 +log_must wait_for_removal $TESTPOOL + +# 3. Verify we can't remove the "indirect" vdev created by the first removal +INDIRECT_VDEV=$(zpool list -v -g $TESTPOOL | awk '{if ($2 == "-") { print $1; exit} }') +log_must test -n "$INDIRECT_VDEV" +log_mustnot zpool remove $TESTPOOL $INDIRECT_VDEV + +log_pass "Device removal cannot remove non-concrete vdevs"