aboutsummaryrefslogtreecommitdiffstats
path: root/module/zfs/zio.c
diff options
context:
space:
mode:
authorGeorge Wilson <[email protected]>2019-06-28 15:40:24 -0400
committerBrian Behlendorf <[email protected]>2019-06-28 12:40:23 -0700
commit681a85cb01a9f83b9f742d8fb634edddc68c5679 (patch)
tree039413ee05c67b4c4670d30161c3dbdefa552ff4 /module/zfs/zio.c
parent765d1f0644658d772addeb9b2dd5039ac43177ad (diff)
nopwrites on dmu_sync-ed blocks can result in a panic
After device removal, performing nopwrites on a dmu_sync-ed block will result in a panic. This panic can show up in two ways: 1. an attempt to issue an IOCTL in vdev_indirect_io_start() 2. a failed comparison of zio->io_bp and zio->io_bp_orig in zio_done() To resolve both of these panics, nopwrites of blocks on indirect vdevs should be ignored and new allocations should be performed on concrete vdevs. Reviewed-by: Igor Kozhukhov <[email protected]> Reviewed-by: Pavel Zakharov <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Don Brady <[email protected]> Signed-off-by: George Wilson <[email protected]> Closes #8957
Diffstat (limited to 'module/zfs/zio.c')
-rw-r--r--module/zfs/zio.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/module/zfs/zio.c b/module/zfs/zio.c
index 6454ae5e3..a1771df6f 100644
--- a/module/zfs/zio.c
+++ b/module/zfs/zio.c
@@ -2856,6 +2856,20 @@ zio_nop_write(zio_t *zio)
ASSERT(bcmp(&bp->blk_prop, &bp_orig->blk_prop,
sizeof (uint64_t)) == 0);
+ /*
+ * If we're overwriting a block that is currently on an
+ * indirect vdev, then ignore the nopwrite request and
+ * allow a new block to be allocated on a concrete vdev.
+ */
+ spa_config_enter(zio->io_spa, SCL_VDEV, FTAG, RW_READER);
+ vdev_t *tvd = vdev_lookup_top(zio->io_spa,
+ DVA_GET_VDEV(&bp->blk_dva[0]));
+ if (tvd->vdev_ops == &vdev_indirect_ops) {
+ spa_config_exit(zio->io_spa, SCL_VDEV, FTAG);
+ return (zio);
+ }
+ spa_config_exit(zio->io_spa, SCL_VDEV, FTAG);
+
*bp = *bp_orig;
zio->io_pipeline = ZIO_INTERLOCK_PIPELINE;
zio->io_flags |= ZIO_FLAG_NOPWRITE;