aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Caputi <[email protected]>2018-12-13 17:18:48 -0500
committerBrian Behlendorf <[email protected]>2018-12-13 14:18:48 -0800
commit5aa95ba0d3502779695341b5f55fa5ba1d3330ff (patch)
tree87db3c6596a476839e0ec2278e4f55e8c15cb427
parent4b702901637ee0be1f654af38c86d0a68593f921 (diff)
Fix resilver writes in vdev_indirect_io_start
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 <[email protected]> Reviewed by: Matt Ahrens <[email protected]> Reviewed-by: Serapheim Dimitropoulos <[email protected]> Signed-off-by: Tom Caputi <[email protected]> Closes #8193
-rw-r--r--module/zfs/vdev_indirect.c23
1 files changed, 15 insertions, 8 deletions
diff --git a/module/zfs/vdev_indirect.c b/module/zfs/vdev_indirect.c
index 1bc5676e3..724457df4 100644
--- a/module/zfs/vdev_indirect.c
+++ b/module/zfs/vdev_indirect.c
@@ -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++) {
@@ -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
@@ -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)) {