Skip to content

Commit

Permalink
Fix resilver writes in vdev_indirect_io_start
Browse files Browse the repository at this point in the history
This patch addresses an issue found in ztest where resilver
write zios that were passed to an indirect vdev would end up
being handled as though they were resilver read zios. This
caused issues where the zio->io_abd would be both read to
and written from at the same time, causing asserts to fail.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed by: Matt Ahrens <matt@delphix.com>
Reviewed-by: Serapheim Dimitropoulos <serapheim@delphix.com>
Signed-off-by: Tom Caputi <tcaputi@datto.com>
Closes #8193
  • Loading branch information
Tom Caputi authored and behlendorf committed Dec 13, 2018
1 parent 4b70290 commit 5aa95ba
Showing 1 changed file with 15 additions and 8 deletions.
23 changes: 15 additions & 8 deletions module/zfs/vdev_indirect.c
Expand Up @@ -1265,6 +1265,8 @@ vdev_indirect_read_all(zio_t *zio)
{
indirect_vsd_t *iv = zio->io_vsd;

ASSERT3U(zio->io_type, ==, ZIO_TYPE_READ);

for (indirect_split_t *is = list_head(&iv->iv_splits);
is != NULL; is = list_next(&iv->iv_splits, is)) {
for (int i = 0; i < is->is_children; i++) {
Expand Down Expand Up @@ -1347,7 +1349,8 @@ vdev_indirect_io_start(zio_t *zio)
vdev_indirect_child_io_done, zio));
} else {
iv->iv_split_block = B_TRUE;
if (zio->io_flags & (ZIO_FLAG_SCRUB | ZIO_FLAG_RESILVER)) {
if (zio->io_type == ZIO_TYPE_READ &&
zio->io_flags & (ZIO_FLAG_SCRUB | ZIO_FLAG_RESILVER)) {
/*
* Read all copies. Note that for simplicity,
* we don't bother consulting the DTL in the
Expand All @@ -1356,13 +1359,17 @@ vdev_indirect_io_start(zio_t *zio)
vdev_indirect_read_all(zio);
} else {
/*
* Read one copy of each split segment, from the
* top-level vdev. Since we don't know the
* checksum of each split individually, the child
* zio can't ensure that we get the right data.
* E.g. if it's a mirror, it will just read from a
* random (healthy) leaf vdev. We have to verify
* the checksum in vdev_indirect_io_done().
* If this is a read zio, we read one copy of each
* split segment, from the top-level vdev. Since
* we don't know the checksum of each split
* individually, the child zio can't ensure that
* we get the right data. E.g. if it's a mirror,
* it will just read from a random (healthy) leaf
* vdev. We have to verify the checksum in
* vdev_indirect_io_done().
*
* For write zios, the vdev code will ensure we write
* to all children.
*/
for (indirect_split_t *is = list_head(&iv->iv_splits);
is != NULL; is = list_next(&iv->iv_splits, is)) {
Expand Down

0 comments on commit 5aa95ba

Please sign in to comment.