diff options
author | asomers <asomers@FreeBSD.org> | 2018-02-22 02:16:44 +0000 |
---|---|---|
committer | asomers <asomers@FreeBSD.org> | 2018-02-22 02:16:44 +0000 |
commit | ea23fe615e277e8eea8d74a858e19d490d38d673 (patch) | |
tree | 847d217f472a95767006f365c945417c5cf9b65f | |
parent | ff446e4194b47425a5e6e1d023a6e8162ff91f48 (diff) | |
download | FreeBSD-src-ea23fe615e277e8eea8d74a858e19d490d38d673.zip FreeBSD-src-ea23fe615e277e8eea8d74a858e19d490d38d673.tar.gz |
MFC r328605:
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
Sponsored by: Spectra Logic Corp
-rw-r--r-- | cddl/usr.sbin/zfsd/case_file.cc | 46 |
1 files changed, 45 insertions, 1 deletions
diff --git a/cddl/usr.sbin/zfsd/case_file.cc b/cddl/usr.sbin/zfsd/case_file.cc index c310585..1ddffae 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); |