]> granicus.if.org Git - zfs/commitdiff
Fix divide by zero during indirect split damage
authorTom Caputi <tcaputi@datto.com>
Wed, 7 Nov 2018 23:44:56 +0000 (18:44 -0500)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Wed, 7 Nov 2018 23:44:56 +0000 (15:44 -0800)
This patch simply ensures that vdev_indirect_splits_damage()
cannot hit a divide by zero exception if a split has no
children with valid data. The normal reconstruction code
path in vdev_indirect_reconstruct_io_done() already has this
check.

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

module/zfs/vdev_indirect.c

index 7863fe9d0f351abc3692f57fbfdd2644af13c148..1bc5676e3ea9205cb866aefdcd53025dfb015951 100644 (file)
@@ -1587,6 +1587,8 @@ vdev_indirect_splits_enumerate_randomly(indirect_vsd_t *iv, zio_t *zio)
 static int
 vdev_indirect_splits_damage(indirect_vsd_t *iv, zio_t *zio)
 {
+       int error;
+
        /* Presume all the copies are unique for initial selection. */
        for (indirect_split_t *is = list_head(&iv->iv_splits);
            is != NULL; is = list_next(&iv->iv_splits, is)) {
@@ -1599,13 +1601,18 @@ vdev_indirect_splits_damage(indirect_vsd_t *iv, zio_t *zio)
                                list_insert_tail(&is->is_unique_child, ic);
                        }
                }
+
+               if (list_is_empty(&is->is_unique_child)) {
+                       error = SET_ERROR(EIO);
+                       goto out;
+               }
        }
 
        /*
         * Set each is_good_child to a randomly-selected child which
         * is known to contain validated data.
         */
-       int error = vdev_indirect_splits_enumerate_randomly(iv, zio);
+       error = vdev_indirect_splits_enumerate_randomly(iv, zio);
        if (error)
                goto out;