ztest.c revision ecc2d604e885a75cc75e647b5641af99d5a6f4a6
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * CDDL HEADER START
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * The contents of this file are subject to the terms of the
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Common Development and Distribution License (the "License").
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * You may not use this file except in compliance with the License.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * or http://www.opensolaris.org/os/licensing.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * See the License for the specific language governing permissions
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * and limitations under the License.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * When distributing Covered Code, include this CDDL HEADER in each
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * If applicable, add the following below this CDDL HEADER, with the
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * fields enclosed by brackets "[]" replaced with your own identifying
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * information: Portions Copyright [yyyy] [name of copyright owner]
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * CDDL HEADER END
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Use is subject to license terms.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#pragma ident "%Z%%M% %I% %E% SMI"
1d32ba663e202c24a5a1f2e5aef83fffb447cb7fJohn Wren Kennedy * The objective of this program is to provide a DMU/ZAP/SPA stress test
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * that runs entirely in userland, is easy to use, and easy to extend.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * The overall design of the ztest program is as follows:
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * (1) For each major functional area (e.g. adding vdevs to a pool,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * creating and destroying datasets, reading and writing objects, etc)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * we have a simple routine to test that functionality. These
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * individual routines do not have to do anything "stressful".
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * (2) We turn these simple functionality tests into a stress test by
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * running them all in parallel, with as many threads as desired,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * and spread across as many datasets, objects, and vdevs as desired.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * (3) While all this is happening, we inject faults into the pool to
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * verify that self-healing data really works.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * (4) Every time we open a dataset, we change its checksum and compression
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * functions. Thus even individual objects vary from block to block
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * in which checksum they use and whether they're compressed.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * (5) To verify that we never lose on-disk consistency after a crash,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * we run the entire test in a child of the main process.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * At random times, the child self-immolates with a SIGKILL.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * This is the software equivalent of pulling the power cord.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * The parent then runs the test again, using the existing
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * storage pool, as many times as desired.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * (6) To verify that we don't have future leaks or temporal incursions,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * many of the functional tests record the transaction group number
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * as part of their data. When reading old data, they verify that
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * the transaction group number is less than the current, open txg.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * If you add a new test, please do this if applicable.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * When run with no arguments, ztest runs for about five minutes and
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * produces no output if successful. To get a little bit of information,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * specify -V. To get more information, specify -VV, and so on.
1d32ba663e202c24a5a1f2e5aef83fffb447cb7fJohn Wren Kennedy * To turn this into an overnight stress test, use -T to specify run time.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * You can ask more more vdevs [-v], datasets [-d], or threads [-t]
1d32ba663e202c24a5a1f2e5aef83fffb447cb7fJohn Wren Kennedy * to increase the pool capacity, fanout, and overall stress level.
1d32ba663e202c24a5a1f2e5aef83fffb447cb7fJohn Wren Kennedy * The -N(okill) option will suppress kills, so each child runs to completion.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * This can be useful when you're trying to distinguish temporal incursions
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * from plain old race conditions.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int zopt_ashift = SPA_MINBLOCKSHIFT;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic size_t zopt_vdev_size = SPA_MINDEVSIZE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic uint64_t zopt_passtime = 60; /* 60 seconds */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic uint64_t zopt_killrate = 70; /* 70% kill rate */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic uint64_t zopt_time = 300; /* 5 minutes */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedytypedef struct ztest_args {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Note: these aren't static because we want dladdr() to work.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyztest_func_t ztest_dmu_objset_create_destroy;
1d32ba663e202c24a5a1f2e5aef83fffb447cb7fJohn Wren Kennedyztest_func_t ztest_dmu_snapshot_create_destroy;
c971037baa5d64dfecf6d87ed602fc3116ebec41Paul Dagnelietypedef struct ztest_info {
1d32ba663e202c24a5a1f2e5aef83fffb447cb7fJohn Wren Kennedy ztest_func_t *zi_func; /* test function */
ac89d1e83d4735655102d06f099fb2d21bf120f6John Kennedy uint64_t *zi_interval; /* execute every <interval> seconds */
ac89d1e83d4735655102d06f099fb2d21bf120f6John Kennedy uint64_t zi_call_target; /* target cumulative total */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyuint64_t zopt_always = 0; /* all the time */
typedef struct ztest_shared {
typedef struct ztest_block_tag {
static int ztest_random_fd;
_umem_logging_init(void)
char *fatal_msg;
if (do_perror) {
if (ztest_dump_core)
abort();
static uint64_t
char *end;
return (val);
usage(void)
static uint64_t
uint64_t r;
if (range == 0)
return (r % range);
ztest_record_enospc(char *s)
int opt;
value = 0;
switch (opt) {
switch (opt) {
zopt_verbose++;
zopt_init = 0;
usage();
static uint64_t
ztest_get_ashift(void)
if (zopt_ashift == 0)
return (zopt_ashift);
static nvlist_t *
int fd;
if (size == 0) {
return (file);
static nvlist_t *
VDEV_TYPE_RAIDZ) == 0);
child, r) == 0);
return (raidz);
static nvlist_t *
VDEV_TYPE_MIRROR) == 0);
child, m) == 0);
return (mirror);
static nvlist_t *
ASSERT(t > 0);
child, t) == 0);
return (root);
int error;
if (error) {
static uint8_t
ztest_random_checksum(void)
return (checksum);
static uint8_t
ztest_random_compress(void)
typedef struct ztest_replay {
int error;
if (byteswap)
if (error) {
return (error);
return (error);
int error;
if (byteswap)
if (error) {
return (error);
return (error);
int error;
if (error)
int error;
else if (error != 0)
static vdev_t *
return (vd);
return (vd);
NULL)
return (mvd);
return (NULL);
int replacing;
int fd;
expected_error = 0;
int fd;
int error;
static uint64_t
#ifndef lint
static uint64_t
int error;
basemode++;
NULL);
if (error) {
if (error) {
seq = 0;
while (objects-- != 0) {
if (error) {
if (error == 0) {
if (error == 0)
if (error)
int error;
return (ERESTART);
return (EINTR);
advance = 0;
if (batchobj == 0) {
sizeof (uint64_t));
if (error) {
for (b = 0; b < batchsize; b++) {
if (object == 0)
for (c = 0; c < bonuslen; c++) {
fatal(0,
if (error) {
if (error) {
object = 0;
if (error) {
if (error) {
for (b = 0; b < batchsize; b++) {
sizeof (uint64_t));
sizeof (uint64_t));
if (error) {
typedef struct bufwad {
} bufwad_t;
typedef struct dmu_read_write_dir {
if (error) {
tx);
if (freeit)
if (error) {
if (freeit) {
if (freeit) {
do_free = 0;
else if (do_free)
if (error) {
if (do_free) {
txg);
if (error) {
int i, ints;
int error;
if (object == 0) {
sizeof (uint64_t));
if (error) {
if (error) {
value[i] = i;
while (--iters >= 0) {
last_txg = 0;
if (error == 0) {
&zl_ints);
for (i = 0; i < ints; i++) {
if (error) {
for (i = 0; i < ints; i++)
if (error)
if (error)
if (error) {
if (error)
if (error)
if (error) {
if (error)
object = 0;
void *data;
while (--iters >= 0) {
if (error) {
txg = 0;
if (error == 0) {
if (error == 0) {
int i, inherit;
int error;
int fd;
if (zopt_maxfaults == 0)
while (--iters != 0) {
int error;
if (error)
if (error != 0)
if (error)
if (error != 0)
int fd;
int error;
guid = 0;
if (error != 0 &&
int status;
char *bin;
if (status == 0)
ztest_dump_core = 0;
int error;
if (error)
if (error)
if (error)
if (error)
return (NULL);
int t, d, error;
for (t = 0; t < ZTEST_SYNC_LOCKS; t++)
if (error)
kernel_fini();
if (error)
for (t = 0; t < zopt_threads; t++) {
d = t % zopt_datasets;
if (t < zopt_datasets) {
(void) rw_unlock(
if (error)
if (error)
t, error);
if (error)
if (t < zopt_datasets) {
kernel_fini();
int error;
if (error)
if (error)
kernel_fini();
int kills = 0;
int iters = 0;
/* Override location of zpool.cache */
* Blow away any existing copy of zpool.cache
if (zopt_init != 0)
for (f = 0; f < ZTEST_FUNCS; f++) {
int status;
char *tmp;
for (f = 0; f < ZTEST_FUNCS; f++) {
exit(0);
kills++;
iters++;
for (f = 0; f < ZTEST_FUNCS; f++) {
kernel_fini();