summaryrefslogtreecommitdiff
path: root/usr/src/cmd/ztest/ztest.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/ztest/ztest.c')
-rw-r--r--usr/src/cmd/ztest/ztest.c91
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;