diff options
Diffstat (limited to 'cmd/ztest/ztest.c')
-rw-r--r-- | cmd/ztest/ztest.c | 133 |
1 files changed, 73 insertions, 60 deletions
diff --git a/cmd/ztest/ztest.c b/cmd/ztest/ztest.c index 53cc6c709..4503a3d02 100644 --- a/cmd/ztest/ztest.c +++ b/cmd/ztest/ztest.c @@ -419,10 +419,10 @@ ztest_random(uint64_t range) return (r % range); } +/* ARGSUSED */ static void ztest_record_enospc(char *s) { - dprintf("ENOSPC doing: %s\n", s ? s : "<unknown>"); ztest_shared->zs_enospc_count++; } @@ -698,15 +698,9 @@ ztest_random_compress(void) return ((uint8_t)ztest_random(ZIO_COMPRESS_FUNCTIONS)); } -typedef struct ztest_replay { - objset_t *zr_os; - uint64_t zr_assign; -} ztest_replay_t; - static int -ztest_replay_create(ztest_replay_t *zr, lr_create_t *lr, boolean_t byteswap) +ztest_replay_create(objset_t *os, lr_create_t *lr, boolean_t byteswap) { - objset_t *os = zr->zr_os; dmu_tx_t *tx; int error; @@ -715,7 +709,7 @@ ztest_replay_create(ztest_replay_t *zr, lr_create_t *lr, boolean_t byteswap) tx = dmu_tx_create(os); dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT); - error = dmu_tx_assign(tx, zr->zr_assign); + error = dmu_tx_assign(tx, TXG_WAIT); if (error) { dmu_tx_abort(tx); return (error); @@ -732,16 +726,15 @@ ztest_replay_create(ztest_replay_t *zr, lr_create_t *lr, boolean_t byteswap) (void) printf("replay create of %s object %llu" " in txg %llu = %d\n", osname, (u_longlong_t)lr->lr_doid, - (u_longlong_t)zr->zr_assign, error); + (u_longlong_t)dmu_tx_get_txg(tx), error); } return (error); } static int -ztest_replay_remove(ztest_replay_t *zr, lr_remove_t *lr, boolean_t byteswap) +ztest_replay_remove(objset_t *os, lr_remove_t *lr, boolean_t byteswap) { - objset_t *os = zr->zr_os; dmu_tx_t *tx; int error; @@ -750,7 +743,7 @@ ztest_replay_remove(ztest_replay_t *zr, lr_remove_t *lr, boolean_t byteswap) tx = dmu_tx_create(os); dmu_tx_hold_free(tx, lr->lr_doid, 0, DMU_OBJECT_END); - error = dmu_tx_assign(tx, zr->zr_assign); + error = dmu_tx_assign(tx, TXG_WAIT); if (error) { dmu_tx_abort(tx); return (error); @@ -977,7 +970,7 @@ ztest_vdev_attach_detach(ztest_args_t *za) uint64_t leaves = MAX(zopt_mirrors, 1) * zopt_raidz; uint64_t leaf, top; uint64_t ashift = ztest_get_ashift(); - uint64_t oldguid; + uint64_t oldguid, pguid; size_t oldsize, newsize; char oldpath[MAXPATHLEN], newpath[MAXPATHLEN]; int replacing; @@ -1009,10 +1002,16 @@ ztest_vdev_attach_detach(ztest_args_t *za) * Locate this vdev. */ oldvd = rvd->vdev_child[top]; - if (zopt_mirrors >= 1) + if (zopt_mirrors >= 1) { + ASSERT(oldvd->vdev_ops == &vdev_mirror_ops); + ASSERT(oldvd->vdev_children >= zopt_mirrors); oldvd = oldvd->vdev_child[leaf / zopt_raidz]; - if (zopt_raidz > 1) + } + if (zopt_raidz > 1) { + ASSERT(oldvd->vdev_ops == &vdev_raidz_ops); + ASSERT(oldvd->vdev_children == zopt_raidz); oldvd = oldvd->vdev_child[leaf % zopt_raidz]; + } /* * If we're already doing an attach or replace, oldvd may be a @@ -1020,8 +1019,8 @@ ztest_vdev_attach_detach(ztest_args_t *za) */ while (oldvd->vdev_children != 0) { oldvd_has_siblings = B_TRUE; - ASSERT(oldvd->vdev_children == 2); - oldvd = oldvd->vdev_child[ztest_random(2)]; + ASSERT(oldvd->vdev_children >= 2); + oldvd = oldvd->vdev_child[ztest_random(oldvd->vdev_children)]; } oldguid = oldvd->vdev_guid; @@ -1029,16 +1028,17 @@ ztest_vdev_attach_detach(ztest_args_t *za) oldvd_is_log = oldvd->vdev_top->vdev_islog; (void) strcpy(oldpath, oldvd->vdev_path); pvd = oldvd->vdev_parent; + pguid = pvd->vdev_guid; /* * 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); - error = spa_vdev_detach(spa, oldguid, B_FALSE); - if (error != 0 && error != ENODEV && error != EBUSY) - fatal(0, "detach (%s) returned %d", - oldpath, error); + error = spa_vdev_detach(spa, oldguid, pguid, B_FALSE); + if (error != 0 && error != ENODEV && error != EBUSY && + error != ENOTSUP) + fatal(0, "detach (%s) returned %d", oldpath, error); (void) mutex_unlock(&ztest_shared->zs_vdev_lock); return; } @@ -1138,7 +1138,6 @@ ztest_vdev_attach_detach(ztest_args_t *za) /* * Verify that dynamic LUN growth works as expected. */ -/* ARGSUSED */ void ztest_vdev_LUN_growth(ztest_args_t *za) { @@ -1278,7 +1277,6 @@ ztest_dmu_objset_create_destroy(ztest_args_t *za) zilog_t *zilog; uint64_t seq; uint64_t objects; - ztest_replay_t zr; (void) rw_rdlock(&ztest_shared->zs_name_lock); (void) snprintf(name, 100, "%s/%s_temp_%llu", za->za_pool, za->za_pool, @@ -1295,8 +1293,7 @@ ztest_dmu_objset_create_destroy(ztest_args_t *za) */ if (ztest_random(2) == 0 && dmu_objset_open(name, DMU_OST_OTHER, DS_MODE_OWNER, &os) == 0) { - zr.zr_os = os; - zil_replay(os, &zr, &zr.zr_assign, ztest_replay_vector, NULL); + zil_replay(os, os, ztest_replay_vector); dmu_objset_close(os); } @@ -2059,8 +2056,6 @@ ztest_dmu_write_parallel(ztest_args_t *za) error = dmu_buf_hold(os, ZTEST_DIROBJ, blkoff, FTAG, &db); za->za_dbuf = db; if (error) { - dprintf("dmu_buf_hold(%s, %d, %llx) = %d\n", - osname, ZTEST_DIROBJ, blkoff, error); (void) mutex_unlock(lp); return; } @@ -2071,11 +2066,8 @@ ztest_dmu_write_parallel(ztest_args_t *za) (void) mutex_unlock(lp); - if (error) { - dprintf("dmu_sync(%s, %d, %llx) = %d\n", - osname, ZTEST_DIROBJ, off, error); + if (error) return; - } if (blk.blk_birth == 0) /* concurrent free */ return; @@ -2584,8 +2576,6 @@ ztest_fault_inject(ztest_args_t *za) maxfaults = INT_MAX; /* no limit on cache devices */ } - dprintf("damaging %s and %s\n", path0, pathrand); - spa_config_exit(spa, SCL_STATE, FTAG); if (maxfaults == 0) @@ -2595,10 +2585,13 @@ ztest_fault_inject(ztest_args_t *za) * If we can tolerate two or more faults, randomly online/offline vd0. */ if (maxfaults >= 2 && guid0 != 0) { - if (ztest_random(10) < 6) - (void) vdev_offline(spa, guid0, B_TRUE); - else - (void) vdev_online(spa, guid0, B_FALSE, NULL); + if (ztest_random(10) < 6) { + int flags = (ztest_random(2) == 0 ? + ZFS_OFFLINE_TEMPORARY : 0); + VERIFY(vdev_offline(spa, guid0, flags) != EBUSY); + } else { + (void) vdev_online(spa, guid0, 0, NULL); + } } /* @@ -2853,7 +2846,7 @@ ztest_walk_pool_directory(char *header) static void ztest_spa_import_export(char *oldname, char *newname) { - nvlist_t *config; + nvlist_t *config, *newconfig; uint64_t pool_guid; spa_t *spa; int error; @@ -2875,6 +2868,12 @@ ztest_spa_import_export(char *oldname, char *newname) if (error) fatal(0, "spa_open('%s') = %d", oldname, error); + /* + * Kick off a scrub to tickle scrub/export races. + */ + if (ztest_random(2) == 0) + (void) spa_scrub(spa, POOL_SCRUB_EVERYTHING); + pool_guid = spa_guid(spa); spa_close(spa, FTAG); @@ -2883,13 +2882,20 @@ ztest_spa_import_export(char *oldname, char *newname) /* * Export it. */ - error = spa_export(oldname, &config, B_FALSE); + error = spa_export(oldname, &config, B_FALSE, B_FALSE); if (error) fatal(0, "spa_export('%s') = %d", oldname, error); ztest_walk_pool_directory("pools after export"); /* + * Try to import it. + */ + newconfig = spa_tryimport(config); + ASSERT(newconfig != NULL); + nvlist_free(newconfig); + + /* * Import it under the new name. */ error = spa_import(newname, config, NULL); @@ -2931,22 +2937,25 @@ ztest_spa_import_export(char *oldname, char *newname) nvlist_free(config); } +static void +ztest_resume(spa_t *spa) +{ + if (spa_suspended(spa)) { + spa_vdev_state_enter(spa); + vdev_clear(spa, NULL); + (void) spa_vdev_state_exit(spa, NULL, 0); + zio_resume(spa); + } +} + static void * -ztest_resume(void *arg) +ztest_resume_thread(void *arg) { spa_t *spa = arg; while (!ztest_exiting) { (void) poll(NULL, 0, 1000); - - if (!spa_suspended(spa)) - continue; - - spa_vdev_state_enter(spa); - vdev_clear(spa, NULL); - (void) spa_vdev_state_exit(spa, NULL, 0); - - zio_resume(spa); + ztest_resume(spa); } return (NULL); } @@ -3089,9 +3098,19 @@ ztest_run(char *pool) VERIFY(spa_open(pool, &spa, FTAG) == 0); /* + * We don't expect the pool to suspend unless maxfaults == 0, + * in which case ztest_fault_inject() temporarily takes away + * the only valid replica. + */ + if (zopt_maxfaults == 0) + spa->spa_failmode = ZIO_FAILURE_MODE_WAIT; + else + spa->spa_failmode = ZIO_FAILURE_MODE_PANIC; + + /* * Create a thread to periodically resume suspended I/O. */ - VERIFY(thr_create(0, 0, ztest_resume, spa, THR_BOUND, + VERIFY(thr_create(0, 0, ztest_resume_thread, spa, THR_BOUND, &resume_tid) == 0); /* @@ -3140,7 +3159,6 @@ ztest_run(char *pool) za[t].za_kill = za[0].za_kill; if (t < zopt_datasets) { - ztest_replay_t zr; int test_future = FALSE; (void) rw_rdlock(&ztest_shared->zs_name_lock); (void) snprintf(name, 100, "%s/%s_%d", pool, pool, d); @@ -3164,9 +3182,8 @@ ztest_run(char *pool) (void) rw_unlock(&ztest_shared->zs_name_lock); if (test_future) ztest_dmu_check_future_leak(&za[t]); - zr.zr_os = za[d].za_os; - zil_replay(zr.zr_os, &zr, &zr.zr_assign, - ztest_replay_vector, NULL); + zil_replay(za[d].za_os, za[d].za_os, + ztest_replay_vector); za[d].za_zilog = zil_open(za[d].za_os, NULL); } @@ -3211,6 +3228,7 @@ ztest_run(char *pool) /* Kill the resume thread */ ztest_exiting = B_TRUE; VERIFY(thr_join(resume_tid, NULL, NULL) == 0); + ztest_resume(spa); /* * Right before closing the pool, kick off a bunch of async I/O; @@ -3306,11 +3324,6 @@ main(int argc, char **argv) process_options(argc, argv); - argc -= optind; - argv += optind; - - dprintf_setup(&argc, argv); - /* * Blow away any existing copy of zpool.cache */ |