diff options
author | George Wilson <[email protected]> | 2019-06-28 15:40:24 -0400 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2019-06-28 12:40:23 -0700 |
commit | 681a85cb01a9f83b9f742d8fb634edddc68c5679 (patch) | |
tree | 039413ee05c67b4c4670d30161c3dbdefa552ff4 /module/zfs | |
parent | 765d1f0644658d772addeb9b2dd5039ac43177ad (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')
-rw-r--r-- | module/zfs/zio.c | 14 |
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; |