From af63bbd0f0b0c7d47ddd043e54c95a9a056ba8a0 Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Tue, 30 Jan 2018 21:25:43 +0000 Subject: [PATCH] zfsd: Don't spare a vdev that's being replaced If a zfs pool contains a replacing vdev (either created manually by "zpool replace" or by zfsd(8) via autoreplace by physical path) and then new spares get added to the pool, zfsd shouldn't use one to replace the drive that is already being replaced. That's a waste of resources that just slows down the rebuild. PR: 225547 MFC after: 3 weeks Sponsored by: Spectra Logic Corp --- cddl/usr.sbin/zfsd/case_file.cc | 46 ++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/cddl/usr.sbin/zfsd/case_file.cc b/cddl/usr.sbin/zfsd/case_file.cc index c3105853b29c..1ddffae8a884 100644 --- a/cddl/usr.sbin/zfsd/case_file.cc +++ b/cddl/usr.sbin/zfsd/case_file.cc @@ -442,10 +442,38 @@ CaseFile::ReEvaluate(const ZfsEvent &event) return (consumed || closed); } +/* Find a Vdev containing the vdev with the given GUID */ +static nvlist_t* +find_parent(nvlist_t *pool_config, nvlist_t *config, DevdCtl::Guid child_guid) +{ + nvlist_t **vdevChildren; + int error; + unsigned ch, numChildren; + + error = nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_CHILDREN, + &vdevChildren, &numChildren); + + if (error != 0 || numChildren == 0) + return (NULL); + + for (ch = 0; ch < numChildren; ch++) { + nvlist *result; + Vdev vdev(pool_config, vdevChildren[ch]); + + if (vdev.GUID() == child_guid) + return (config); + + result = find_parent(pool_config, vdevChildren[ch], child_guid); + if (result != NULL) + return (result); + } + + return (NULL); +} bool CaseFile::ActivateSpare() { - nvlist_t *config, *nvroot; + nvlist_t *config, *nvroot, *parent_config; nvlist_t **spares; char *devPath, *vdev_type; const char *poolname; @@ -472,6 +500,22 @@ CaseFile::ActivateSpare() { "tree for pool %s", poolname); return (false); } + + parent_config = find_parent(config, nvroot, m_vdevGUID); + if (parent_config != NULL) { + char *parent_type; + + /* + * Don't activate spares for members of a "replacing" vdev. + * They're already dealt with. Sparing them will just drag out + * the resilver process. + */ + error = nvlist_lookup_string(parent_config, + ZPOOL_CONFIG_TYPE, &parent_type); + if (error == 0 && strcmp(parent_type, VDEV_TYPE_REPLACING) == 0) + return (false); + } + nspares = 0; nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, &spares, &nspares);