diff options
Diffstat (limited to 'usr/src/cmd/ztest/ztest.c')
-rw-r--r-- | usr/src/cmd/ztest/ztest.c | 91 |
1 files changed, 81 insertions, 10 deletions
diff --git a/usr/src/cmd/ztest/ztest.c b/usr/src/cmd/ztest/ztest.c index d338ee4cab..1fde9cbe6d 100644 --- a/usr/src/cmd/ztest/ztest.c +++ b/usr/src/cmd/ztest/ztest.c @@ -341,6 +341,8 @@ ztest_func_t ztest_vdev_aux_add_remove; ztest_func_t ztest_split_pool; ztest_func_t ztest_reguid; ztest_func_t ztest_spa_upgrade; +ztest_func_t ztest_device_removal; +ztest_func_t ztest_remap_blocks; uint64_t zopt_always = 0ULL * NANOSEC; /* all the time */ uint64_t zopt_incessant = 1ULL * NANOSEC / 10; /* every 1/10 second */ @@ -382,6 +384,8 @@ ztest_info_t ztest_info[] = { &ztest_opts.zo_vdevtime }, { ztest_vdev_aux_add_remove, 1, &ztest_opts.zo_vdevtime }, + { ztest_device_removal, 1, &zopt_sometimes }, + { ztest_remap_blocks, 1, &zopt_sometimes } }; #define ZTEST_FUNCS (sizeof (ztest_info) / sizeof (ztest_info_t)) @@ -784,10 +788,10 @@ ztest_kill(ztest_shared_t *zs) /* * Before we kill off ztest, make sure that the config is updated. - * See comment above spa_config_sync(). + * See comment above spa_write_cachefile(). */ mutex_enter(&spa_namespace_lock); - spa_config_sync(ztest_spa, B_FALSE, B_FALSE); + spa_write_cachefile(ztest_spa, B_FALSE, B_FALSE); mutex_exit(&spa_namespace_lock); zfs_dbgmsg_print(FTAG); @@ -1014,7 +1018,7 @@ ztest_random_vdev_top(spa_t *spa, boolean_t log_ok) do { top = ztest_random(rvd->vdev_children); tvd = rvd->vdev_child[top]; - } while (tvd->vdev_ishole || (tvd->vdev_islog && !log_ok) || + } while (!vdev_is_concrete(tvd) || (tvd->vdev_islog && !log_ok) || tvd->vdev_mg == NULL || tvd->vdev_mg->mg_class == NULL); return (top); @@ -2783,7 +2787,19 @@ ztest_vdev_attach_detach(ztest_ds_t *zd, uint64_t id) VERIFY(mutex_lock(&ztest_vdev_lock) == 0); leaves = MAX(zs->zs_mirrors, 1) * ztest_opts.zo_raidz; - spa_config_enter(spa, SCL_VDEV, FTAG, RW_READER); + spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER); + + /* + * If a vdev is in the process of being removed, its removal may + * finish while we are in progress, leading to an unexpected error + * value. Don't bother trying to attach while we are in the middle + * of removal. + */ + if (spa->spa_vdev_removal != NULL) { + spa_config_exit(spa, SCL_ALL, FTAG); + VERIFY(mutex_unlock(&ztest_vdev_lock) == 0); + return; + } /* * Decide whether to do an attach or a replace. @@ -2836,7 +2852,7 @@ ztest_vdev_attach_detach(ztest_ds_t *zd, uint64_t id) * If oldvd has siblings, then half of the time, detach it. */ if (oldvd_has_siblings && ztest_random(2) == 0) { - spa_config_exit(spa, SCL_VDEV, FTAG); + spa_config_exit(spa, SCL_ALL, FTAG); error = spa_vdev_detach(spa, oldguid, pguid, B_FALSE); if (error != 0 && error != ENODEV && error != EBUSY && error != ENOTSUP) @@ -2863,6 +2879,10 @@ ztest_vdev_attach_detach(ztest_ds_t *zd, uint64_t id) } if (newvd) { + /* + * Reopen to ensure the vdev's asize field isn't stale. + */ + vdev_reopen(newvd); newsize = vdev_get_min_asize(newvd); } else { /* @@ -2900,7 +2920,7 @@ ztest_vdev_attach_detach(ztest_ds_t *zd, uint64_t id) else expected_error = 0; - spa_config_exit(spa, SCL_VDEV, FTAG); + spa_config_exit(spa, SCL_ALL, FTAG); /* * Build the nvlist describing newpath. @@ -2938,6 +2958,26 @@ ztest_vdev_attach_detach(ztest_ds_t *zd, uint64_t id) VERIFY(mutex_unlock(&ztest_vdev_lock) == 0); } +/* ARGSUSED */ +void +ztest_device_removal(ztest_ds_t *zd, uint64_t id) +{ + spa_t *spa = ztest_spa; + vdev_t *vd; + uint64_t guid; + + VERIFY(mutex_lock(&ztest_vdev_lock) == 0); + + spa_config_enter(spa, SCL_VDEV, FTAG, RW_READER); + vd = vdev_lookup_top(spa, ztest_random_vdev_top(spa, B_FALSE)); + guid = vd->vdev_guid; + spa_config_exit(spa, SCL_VDEV, FTAG); + + (void) spa_vdev_remove(spa, guid, B_FALSE); + + VERIFY(mutex_unlock(&ztest_vdev_lock) == 0); +} + /* * Callback function which expands the physical size of the vdev. */ @@ -3066,6 +3106,18 @@ ztest_vdev_LUN_growth(ztest_ds_t *zd, uint64_t id) VERIFY(mutex_lock(&ztest_vdev_lock) == 0); spa_config_enter(spa, SCL_STATE, spa, RW_READER); + /* + * If there is a vdev removal in progress, it could complete while + * we are running, in which case we would not be able to verify + * that the metaslab_class space increased (because it decreases + * when the device removal completes). + */ + if (spa->spa_vdev_removal != NULL) { + spa_config_exit(spa, SCL_STATE, FTAG); + VERIFY(mutex_unlock(&ztest_vdev_lock) == 0); + return; + } + top = ztest_random_vdev_top(spa, B_TRUE); tvd = spa->spa_root_vdev->vdev_child[top]; @@ -3157,16 +3209,18 @@ ztest_vdev_LUN_growth(ztest_ds_t *zd, uint64_t id) /* * Make sure we were able to grow the vdev. */ - if (new_ms_count <= old_ms_count) - fatal(0, "LUN expansion failed: ms_count %llu <= %llu\n", + if (new_ms_count <= old_ms_count) { + fatal(0, "LUN expansion failed: ms_count %llu < %llu\n", old_ms_count, new_ms_count); + } /* * Make sure we were able to grow the pool. */ - if (new_class_space <= old_class_space) - fatal(0, "LUN expansion failed: class_space %llu <= %llu\n", + if (new_class_space <= old_class_space) { + fatal(0, "LUN expansion failed: class_space %llu < %llu\n", old_class_space, new_class_space); + } if (ztest_opts.zo_verbose >= 5) { char oldnumbuf[NN_NUMBUF_SZ], newnumbuf[NN_NUMBUF_SZ]; @@ -4639,6 +4693,20 @@ ztest_dsl_prop_get_set(ztest_ds_t *zd, uint64_t id) /* ARGSUSED */ void +ztest_remap_blocks(ztest_ds_t *zd, uint64_t id) +{ + (void) rw_rdlock(&ztest_name_lock); + + int error = dmu_objset_remap_indirects(zd->zd_name); + if (error == ENOSPC) + error = 0; + ASSERT0(error); + + (void) rw_unlock(&ztest_name_lock); +} + +/* ARGSUSED */ +void ztest_spa_prop_get_set(ztest_ds_t *zd, uint64_t id) { nvlist_t *props = NULL; @@ -4888,6 +4956,9 @@ ztest_fault_inject(ztest_ds_t *zd, uint64_t id) */ vdev_file_t *vf = vd0->vdev_tsd; + zfs_dbgmsg("injecting fault to vdev %llu; maxfaults=%d", + (long long)vd0->vdev_id, (int)maxfaults); + if (vf != NULL && ztest_random(3) == 0) { (void) close(vf->vf_vnode->v_fd); vf->vf_vnode->v_fd = -1; |