aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmeer Hamza <[email protected]>2022-11-04 23:33:47 +0500
committerGitHub <[email protected]>2022-11-04 11:33:47 -0700
commitc23738c70eb86a7f04f93292caef2ed977047608 (patch)
tree43f66a5db16fdbf4cc460ce379c80aedaad69ff2
parent73b8f700b68dc1c537781b2bee0f06c2b6d09418 (diff)
zed: Prevent special vdev to be replaced by hot spare
Special vdevs should not be replaced by a hot spare. Log vdevs already support this, extending the functionality for special vdevs. Reviewed-by: Ryan Moeller <[email protected]> Reviewed-by: Tony Hutter <[email protected]> Reviewed-by: Richard Yao <[email protected]> Reviewed-by: Alexander Motin <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Ameer Hamza <[email protected]> Closes #14129
-rw-r--r--module/zfs/spa.c6
-rwxr-xr-xtests/zfs-tests/tests/functional/fault/auto_offline_001_pos.ksh5
2 files changed, 9 insertions, 2 deletions
diff --git a/module/zfs/spa.c b/module/zfs/spa.c
index de5bbcc09..fe7051db2 100644
--- a/module/zfs/spa.c
+++ b/module/zfs/spa.c
@@ -6819,10 +6819,12 @@ spa_vdev_attach(spa_t *spa, uint64_t guid, nvlist_t *nvroot, int replacing,
return (spa_vdev_exit(spa, newrootvd, txg, error));
/*
- * Spares can't replace logs
+ * log, dedup and special vdevs should not be replaced by spares.
*/
- if (oldvd->vdev_top->vdev_islog && newvd->vdev_isspare)
+ if ((oldvd->vdev_top->vdev_alloc_bias != VDEV_BIAS_NONE ||
+ oldvd->vdev_top->vdev_islog) && newvd->vdev_isspare) {
return (spa_vdev_exit(spa, newrootvd, txg, ENOTSUP));
+ }
/*
* A dRAID spare can only replace a child of its parent dRAID vdev.
diff --git a/tests/zfs-tests/tests/functional/fault/auto_offline_001_pos.ksh b/tests/zfs-tests/tests/functional/fault/auto_offline_001_pos.ksh
index 0ab9317c0..c0387e1d3 100755
--- a/tests/zfs-tests/tests/functional/fault/auto_offline_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/fault/auto_offline_001_pos.ksh
@@ -121,6 +121,11 @@ done
# the removed data device
for conf in "${poolconfs[@]}"
do
+ # special vdev can not be replaced by a hot spare
+ if [[ $conf = *"special mirror"* ]]; then
+ continue
+ fi
+
# 1. Create a pool with a spare
log_must zpool create -f $TESTPOOL $conf
block_device_wait ${DEV_DSKDIR}/${removedev}