summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorasomers <asomers@FreeBSD.org>2018-02-22 02:16:44 +0000
committerasomers <asomers@FreeBSD.org>2018-02-22 02:16:44 +0000
commitea23fe615e277e8eea8d74a858e19d490d38d673 (patch)
tree847d217f472a95767006f365c945417c5cf9b65f
parentff446e4194b47425a5e6e1d023a6e8162ff91f48 (diff)
downloadFreeBSD-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.cc46
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);
OpenPOWER on IntegriCloud