diff --git a/cmd/ztest/ztest.c b/cmd/ztest/ztest.c index 0a7ca1c16..572af3e0b 100644 --- a/cmd/ztest/ztest.c +++ b/cmd/ztest/ztest.c @@ -366,7 +366,7 @@ ztest_info_t ztest_info[] = { { ztest_fault_inject, 1, &zopt_sometimes }, { ztest_ddt_repair, 1, &zopt_sometimes }, { ztest_dmu_snapshot_hold, 1, &zopt_sometimes }, - { ztest_reguid, 1, &zopt_sometimes }, + { ztest_reguid, 1, &zopt_rarely }, { ztest_spa_rename, 1, &zopt_rarely }, { ztest_scrub, 1, &zopt_rarely }, { ztest_spa_upgrade, 1, &zopt_rarely }, @@ -4913,6 +4913,14 @@ ztest_fault_inject(ztest_ds_t *zd, uint64_t id) ASSERT(leaves >= 1); + /* + * Grab the name lock as reader. There are some operations + * which don't like to have their vdevs changed while + * they are in progress (i.e. spa_change_guid). Those + * operations will have grabbed the name lock as writer. + */ + (void) rw_enter(&ztest_name_lock, RW_READER); + /* * We need SCL_STATE here because we're going to look at vd0->vdev_tsd. */ @@ -4942,7 +4950,14 @@ ztest_fault_inject(ztest_ds_t *zd, uint64_t id) if (vd0 != NULL && vd0->vdev_top->vdev_islog) islog = B_TRUE; - if (vd0 != NULL && maxfaults != 1) { + /* + * If the top-level vdev needs to be resilvered + * then we only allow faults on the device that is + * resilvering. + */ + if (vd0 != NULL && maxfaults != 1 && + (!vdev_resilver_needed(vd0->vdev_top, NULL, NULL) || + vd0->vdev_resilvering)) { /* * Make vd0 explicitly claim to be unreadable, * or unwriteable, or reach behind its back @@ -4973,6 +4988,7 @@ ztest_fault_inject(ztest_ds_t *zd, uint64_t id) if (sav->sav_count == 0) { spa_config_exit(spa, SCL_STATE, FTAG); + (void) rw_exit(&ztest_name_lock); goto out; } vd0 = sav->sav_vdevs[ztest_random(sav->sav_count)]; @@ -4986,6 +5002,7 @@ ztest_fault_inject(ztest_ds_t *zd, uint64_t id) } spa_config_exit(spa, SCL_STATE, FTAG); + (void) rw_exit(&ztest_name_lock); /* * If we can tolerate two or more faults, or we're dealing diff --git a/module/zfs/spa.c b/module/zfs/spa.c index 6bd640b40..6b9b079df 100644 --- a/module/zfs/spa.c +++ b/module/zfs/spa.c @@ -752,6 +752,7 @@ spa_change_guid(spa_t *spa) int error; uint64_t guid; + mutex_enter(&spa->spa_vdev_top_lock); mutex_enter(&spa_namespace_lock); guid = spa_generate_guid(NULL); @@ -764,6 +765,7 @@ spa_change_guid(spa_t *spa) } mutex_exit(&spa_namespace_lock); + mutex_exit(&spa->spa_vdev_top_lock); return (error); } @@ -4737,7 +4739,6 @@ spa_vdev_detach(spa_t *spa, uint64_t guid, uint64_t pguid, int replace_done) if (pvd->vdev_ops == &vdev_spare_ops) cvd->vdev_unspare = B_FALSE; vdev_remove_parent(cvd); - cvd->vdev_resilvering = B_FALSE; } @@ -5369,6 +5370,13 @@ spa_vdev_resilver_done_hunt(vdev_t *vd) return (oldvd); } + if (vd->vdev_resilvering && vdev_dtl_empty(vd, DTL_MISSING) && + vdev_dtl_empty(vd, DTL_OUTAGE)) { + ASSERT(vd->vdev_ops->vdev_op_leaf); + vd->vdev_resilvering = B_FALSE; + vdev_config_dirty(vd->vdev_top); + } + /* * Check for a completed replacement. We always consider the first * vdev in the list to be the oldest vdev, and the last one to be diff --git a/module/zfs/vdev_file.c b/module/zfs/vdev_file.c index 5eadc560d..c0d062b0e 100644 --- a/module/zfs/vdev_file.c +++ b/module/zfs/vdev_file.c @@ -162,7 +162,6 @@ vdev_file_io_strategy(void *arg) static int vdev_file_io_start(zio_t *zio) { - spa_t *spa = zio->io_spa; vdev_t *vd = zio->io_vd; vdev_file_t *vf = vd->vdev_tsd; @@ -185,8 +184,8 @@ vdev_file_io_start(zio_t *zio) return (ZIO_PIPELINE_CONTINUE); } - spa_taskq_dispatch_ent(spa, ZIO_TYPE_FREE, ZIO_TASKQ_ISSUE, - vdev_file_io_strategy, zio, 0, &zio->io_tqent); + VERIFY3U(taskq_dispatch(system_taskq, vdev_file_io_strategy, zio, + TQ_SLEEP), !=, 0); return (ZIO_PIPELINE_STOP); }