From ca3a675c746e3ba4da381ee4c3b218028c6dd112 Mon Sep 17 00:00:00 2001 From: Ameer Hamza <106930537+ixhamza@users.noreply.github.com> Date: Fri, 4 Nov 2022 23:33:47 +0500 Subject: [PATCH] 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 Reviewed-by: Tony Hutter Reviewed-by: Richard Yao Reviewed-by: Alexander Motin Reviewed-by: Brian Behlendorf Signed-off-by: Ameer Hamza Closes #14129 --- module/zfs/spa.c | 6 ++++-- .../tests/functional/fault/auto_offline_001_pos.ksh | 5 +++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/module/zfs/spa.c b/module/zfs/spa.c index aa65fb6581..86447d1fdc 100644 --- a/module/zfs/spa.c +++ b/module/zfs/spa.c @@ -6772,10 +6772,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 86916bf906..d7189f2983 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 @@ -123,6 +123,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}