diff options
author | Brian Behlendorf <[email protected]> | 2009-01-15 14:04:39 -0800 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2009-01-15 14:04:39 -0800 |
commit | a2e601c6e31492c0b2c6a000bfbeb2403cf4e7e0 (patch) | |
tree | 82af11dc45cb488550fe976a90b1f54649ef3150 /module/zfs/zio.c | |
parent | ca4fc6ef6303fb2164ff963353dd8dced0484ffe (diff) | |
parent | fb5f0bc83330c8a0236c4d34a23723ac1974971a (diff) |
Merge commit 'refs/top-bases/gcc-cast' into gcc-cast
Diffstat (limited to 'module/zfs/zio.c')
-rw-r--r-- | module/zfs/zio.c | 30 |
1 files changed, 27 insertions, 3 deletions
diff --git a/module/zfs/zio.c b/module/zfs/zio.c index d347920ea..62af799f5 100644 --- a/module/zfs/zio.c +++ b/module/zfs/zio.c @@ -767,7 +767,8 @@ zio_read_bp_init(zio_t *zio) { blkptr_t *bp = zio->io_bp; - if (BP_GET_COMPRESS(bp) != ZIO_COMPRESS_OFF && zio->io_logical == zio) { + if (BP_GET_COMPRESS(bp) != ZIO_COMPRESS_OFF && + zio->io_logical == zio && !(zio->io_flags & ZIO_FLAG_RAW)) { uint64_t csize = BP_GET_PSIZE(bp); void *cbuf = zio_buf_alloc(csize); @@ -1790,7 +1791,30 @@ zio_vdev_io_start(zio_t *zio) ASSERT(P2PHASE(zio->io_offset, align) == 0); ASSERT(P2PHASE(zio->io_size, align) == 0); - ASSERT(zio->io_type != ZIO_TYPE_WRITE || (spa_mode & FWRITE)); + ASSERT(zio->io_type != ZIO_TYPE_WRITE || spa_writeable(spa)); + + /* + * If this is a repair I/O, and there's no self-healing involved -- + * that is, we're just resilvering what we expect to resilver -- + * then don't do the I/O unless zio's txg is actually in vd's DTL. + * This prevents spurious resilvering with nested replication. + * For example, given a mirror of mirrors, (A+B)+(C+D), if only + * A is out of date, we'll read from C+D, then use the data to + * resilver A+B -- but we don't actually want to resilver B, just A. + * The top-level mirror has no way to know this, so instead we just + * discard unnecessary repairs as we work our way down the vdev tree. + * The same logic applies to any form of nested replication: + * ditto + mirror, RAID-Z + replacing, etc. This covers them all. + */ + if ((zio->io_flags & ZIO_FLAG_IO_REPAIR) && + !(zio->io_flags & ZIO_FLAG_SELF_HEAL) && + zio->io_txg != 0 && /* not a delegated i/o */ + !vdev_dtl_contains(vd, DTL_PARTIAL, zio->io_txg, 1)) { + ASSERT(zio->io_type == ZIO_TYPE_WRITE); + ASSERT(zio->io_delegate_list == NULL); + zio_vdev_io_bypass(zio); + return (ZIO_PIPELINE_CONTINUE); + } if (vd->vdev_ops->vdev_op_leaf && (zio->io_type == ZIO_TYPE_READ || zio->io_type == ZIO_TYPE_WRITE)) { @@ -1806,7 +1830,6 @@ zio_vdev_io_start(zio_t *zio) zio_interrupt(zio); return (ZIO_PIPELINE_STOP); } - } return (vd->vdev_ops->vdev_op_io_start(zio)); @@ -2157,6 +2180,7 @@ zio_done(zio_t *zio) if ((zio->io_type == ZIO_TYPE_READ || zio->io_type == ZIO_TYPE_FREE) && zio->io_error == ENXIO && + spa->spa_load_state == SPA_LOAD_NONE && spa_get_failmode(spa) != ZIO_FAILURE_MODE_CONTINUE) zio->io_reexecute |= ZIO_REEXECUTE_SUSPEND; |