aboutsummaryrefslogtreecommitdiff
path: root/cddl/usr.sbin
diff options
context:
space:
mode:
authorAlan Somers <asomers@FreeBSD.org>2018-01-30 21:25:43 +0000
committerAlan Somers <asomers@FreeBSD.org>2018-01-30 21:25:43 +0000
commitaf63bbd0f0b0c7d47ddd043e54c95a9a056ba8a0 (patch)
tree12d6a87ad832874446d7730e663b7f0b4c953297 /cddl/usr.sbin
parent71e9130584c0320784db1d65974003bf5a0ed301 (diff)
downloadsrc-af63bbd0f0b0c7d47ddd043e54c95a9a056ba8a0.tar.gz
src-af63bbd0f0b0c7d47ddd043e54c95a9a056ba8a0.zip
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
Notes
Notes: svn path=/head/; revision=328605
Diffstat (limited to 'cddl/usr.sbin')
-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 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);