]> git.proxmox.com Git - mirror_zfs.git/blobdiff - module/zfs/zio.c
OpenZFS 7614, 9064 - zfs device evacuation/removal
[mirror_zfs.git] / module / zfs / zio.c
index 7544cf4e3a3de6d5ec2a27fdf68ab24ae1633099..5259a0c6f01df9b5bf5d698730d3f6835e3f6cf7 100644 (file)
@@ -506,7 +506,7 @@ error:
         * the io_error. If this was not a speculative zio, create an ereport.
         */
        if (ret == ECKSUM) {
-               ret = SET_ERROR(EIO);
+               zio->io_error = SET_ERROR(EIO);
                if ((zio->io_flags & ZIO_FLAG_SPECULATIVE) == 0) {
                        zfs_ereport_post(FM_EREPORT_ZFS_AUTHENTICATION,
                            spa, NULL, &zio->io_bookmark, zio, 0, 0);
@@ -1018,6 +1018,8 @@ void
 zio_free(spa_t *spa, uint64_t txg, const blkptr_t *bp)
 {
 
+       zfs_blkptr_verify(spa, bp);
+
        /*
         * The check for EMBEDDED is a performance optimization.  We
         * process the free here (by ignoring it) rather than
@@ -1081,7 +1083,7 @@ zio_claim(zio_t *pio, spa_t *spa, uint64_t txg, const blkptr_t *bp,
 {
        zio_t *zio;
 
-       dprintf_bp(bp, "claiming in txg %llu", txg);
+       zfs_blkptr_verify(spa, bp);
 
        if (BP_IS_EMBEDDED(bp))
                return (zio_null(pio, spa, NULL, NULL, NULL, 0));
@@ -1200,8 +1202,26 @@ zio_vdev_child_io(zio_t *pio, blkptr_t *bp, vdev_t *vd, uint64_t offset,
        enum zio_stage pipeline = ZIO_VDEV_CHILD_PIPELINE;
        zio_t *zio;
 
-       ASSERT(vd->vdev_parent ==
-           (pio->io_vd ? pio->io_vd : pio->io_spa->spa_root_vdev));
+       /*
+        * vdev child I/Os do not propagate their error to the parent.
+        * Therefore, for correct operation the caller *must* check for
+        * and handle the error in the child i/o's done callback.
+        * The only exceptions are i/os that we don't care about
+        * (OPTIONAL or REPAIR).
+        */
+       ASSERT((flags & ZIO_FLAG_OPTIONAL) || (flags & ZIO_FLAG_IO_REPAIR) ||
+           done != NULL);
+
+       /*
+        * In the common case, where the parent zio was to a normal vdev,
+        * the child zio must be to a child vdev of that vdev.  Otherwise,
+        * the child zio must be to a top-level vdev.
+        */
+       if (pio->io_vd != NULL && pio->io_vd->vdev_ops != &vdev_indirect_ops) {
+               ASSERT3P(vd->vdev_parent, ==, pio->io_vd);
+       } else {
+               ASSERT3P(vd, ==, vd->vdev_top);
+       }
 
        if (type == ZIO_TYPE_READ && bp != NULL) {
                /*
@@ -1214,10 +1234,12 @@ zio_vdev_child_io(zio_t *pio, blkptr_t *bp, vdev_t *vd, uint64_t offset,
                pio->io_pipeline &= ~ZIO_STAGE_CHECKSUM_VERIFY;
        }
 
-       if (vd->vdev_children == 0)
+       if (vd->vdev_ops->vdev_op_leaf) {
+               ASSERT0(vd->vdev_children);
                offset += VDEV_LABEL_START_SIZE;
+       }
 
-       flags |= ZIO_VDEV_CHILD_FLAGS(pio) | ZIO_FLAG_DONT_PROPAGATE;
+       flags |= ZIO_VDEV_CHILD_FLAGS(pio);
 
        /*
         * If we've decided to do a repair, the write is not speculative --
@@ -1318,6 +1340,8 @@ zio_read_bp_init(zio_t *zio)
        uint64_t psize =
            BP_IS_EMBEDDED(bp) ? BPE_GET_PSIZE(bp) : BP_GET_PSIZE(bp);
 
+       ASSERT3P(zio->io_bp, ==, &zio->io_bp_copy);
+
        if (BP_GET_COMPRESS(bp) != ZIO_COMPRESS_OFF &&
            zio->io_child_type == ZIO_CHILD_LOGICAL &&
            !(zio->io_flags & ZIO_FLAG_RAW_COMPRESS)) {
@@ -1341,6 +1365,7 @@ zio_read_bp_init(zio_t *zio)
                abd_return_buf_copy(zio->io_abd, data, psize);
        } else {
                ASSERT(!BP_IS_EMBEDDED(bp));
+               ASSERT3P(zio->io_bp, ==, &zio->io_bp_copy);
        }
 
        if (!DMU_OT_IS_METADATA(BP_GET_TYPE(bp)) && BP_GET_LEVEL(bp) == 0)
@@ -1614,6 +1639,8 @@ zio_free_bp_init(zio_t *zio)
                        zio->io_pipeline = ZIO_DDT_FREE_PIPELINE;
        }
 
+       ASSERT3P(zio->io_bp, ==, &zio->io_bp_copy);
+
        return (ZIO_PIPELINE_CONTINUE);
 }
 
@@ -2092,7 +2119,7 @@ zio_reexecute(zio_t *pio)
 }
 
 void
-zio_suspend(spa_t *spa, zio_t *zio)
+zio_suspend(spa_t *spa, zio_t *zio, zio_suspend_reason_t reason)
 {
        if (spa_get_failmode(spa) == ZIO_FAILURE_MODE_PANIC)
                fm_panic("Pool '%s' has encountered an uncorrectable I/O "
@@ -2112,7 +2139,7 @@ zio_suspend(spa_t *spa, zio_t *zio)
                    ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE |
                    ZIO_FLAG_GODFATHER);
 
-       spa->spa_suspended = B_TRUE;
+       spa->spa_suspended = reason;
 
        if (zio != NULL) {
                ASSERT(!(zio->io_flags & ZIO_FLAG_GODFATHER));
@@ -2135,7 +2162,7 @@ zio_resume(spa_t *spa)
         * Reexecute all previously suspended i/o.
         */
        mutex_enter(&spa->spa_suspend_lock);
-       spa->spa_suspended = B_FALSE;
+       spa->spa_suspended = ZIO_SUSPEND_NONE;
        cv_broadcast(&spa->spa_suspend_cv);
        pio = spa->spa_suspend_zio_root;
        spa->spa_suspend_zio_root = NULL;
@@ -3447,6 +3474,15 @@ zio_vdev_io_start(zio_t *zio)
        }
 
        ASSERT3P(zio->io_logical, !=, zio);
+       if (zio->io_type == ZIO_TYPE_WRITE && zio->io_vd->vdev_removing) {
+               /*
+                * Note: the code can handle other kinds of writes,
+                * but we don't expect them.
+                */
+               ASSERT(zio->io_flags &
+                   (ZIO_FLAG_PHYSICAL | ZIO_FLAG_SELF_HEAL |
+                   ZIO_FLAG_INDUCE_DAMAGE));
+       }
 
        align = 1ULL << vd->vdev_top->vdev_ashift;
 
@@ -4390,7 +4426,7 @@ zio_done(zio_t *zio)
                         * We'd fail again if we reexecuted now, so suspend
                         * until conditions improve (e.g. device comes online).
                         */
-                       zio_suspend(zio->io_spa, zio);
+                       zio_suspend(zio->io_spa, zio, ZIO_SUSPEND_IOERR);
                } else {
                        /*
                         * Reexecution is potentially a huge amount of work.