]> granicus.if.org Git - zfs/commitdiff
Make vdev_set_deferred_resilver() recursive
authorTom Caputi <tcaputi@datto.com>
Wed, 7 Nov 2018 23:33:17 +0000 (18:33 -0500)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Wed, 7 Nov 2018 23:33:17 +0000 (15:33 -0800)
vdev_clear() can call vdev_set_deferred_resilver() with a
non-leaf vdev to setup a deferred resilver. However, this
function is currently written to only handle leaf vdevs.
This bug was introduced with deferred resilvers in 80a91e74.
This patch makes this function recursive so that it can find
appropriate vdevs to resilver and set vdev_resilver_deferred
on them.

Reviewed-by: Matthew Ahrens <mahrens@delphix.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Tom Caputi <tcaputi@datto.com>
Issue #7732
Closes #8082

module/zfs/vdev.c

index 9a7f5e0116fac9a7c249a74a0df97c0be6b0c422..2f28a01c6cfd692a5e8d929f97c2a6cc73f80bfc 100644 (file)
@@ -4598,7 +4598,14 @@ vdev_deadman(vdev_t *vd, char *tag)
 void
 vdev_set_deferred_resilver(spa_t *spa, vdev_t *vd)
 {
-       ASSERT(vd->vdev_ops->vdev_op_leaf);
+       for (uint64_t i = 0; i < vd->vdev_children; i++)
+               vdev_set_deferred_resilver(spa, vd->vdev_child[i]);
+
+       if (!vd->vdev_ops->vdev_op_leaf || !vdev_writeable(vd) ||
+           range_tree_is_empty(vd->vdev_dtl[DTL_MISSING])) {
+               return;
+       }
+
        vd->vdev_resilver_deferred = B_TRUE;
        spa->spa_resilver_deferred = B_TRUE;
 }