2fa9e406ahrens * CDDL HEADER START
3fa9e406ahrens *
4fa9e406ahrens * The contents of this file are subject to the terms of the
5441d80alling * Common Development and Distribution License (the "License").
6441d80alling * You may not use this file except in compliance with the License.
7fa9e406ahrens *
8fa9e406ahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fa9e406ahrens * or http://www.opensolaris.org/os/licensing.
10fa9e406ahrens * See the License for the specific language governing permissions
11fa9e406ahrens * and limitations under the License.
12fa9e406ahrens *
13fa9e406ahrens * When distributing Covered Code, include this CDDL HEADER in each
14fa9e406ahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fa9e406ahrens * If applicable, add the following below this CDDL HEADER, with the
16fa9e406ahrens * fields enclosed by brackets "[]" replaced with your own identifying
17fa9e406ahrens * information: Portions Copyright [yyyy] [name of copyright owner]
18fa9e406ahrens *
19fa9e406ahrens * CDDL HEADER END
20fa9e406ahrens */
2247cb52dJeff Bonwick * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23663207aDon Brady * Copyright (c) 2011, 2018 by Delphix. All rights reserved.
24e9103aaGarrett D'Amore * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
25a7a845eSteven Hartland * Copyright (c) 2013 Steven Hartland. All rights reserved.
26c3d26abMatthew Ahrens * Copyright (c) 2014 Integros [integros.com]
270a05512Jason King * Copyright 2017 Joyent, Inc.
28663207aDon Brady * Copyright (c) 2017, Intel Corporation.
29f06dce2Andrew Stormont * Copyright 2017 RackTop Systems.
30fa9e406ahrens */
33fa9e406ahrens * The objective of this program is to provide a DMU/ZAP/SPA stress test
34fa9e406ahrens * that runs entirely in userland, is easy to use, and easy to extend.
35fa9e406ahrens *
36fa9e406ahrens * The overall design of the ztest program is as follows:
37fa9e406ahrens *
38fa9e406ahrens * (1) For each major functional area (e.g. adding vdevs to a pool,
39fa9e406ahrens *     creating and destroying datasets, reading and writing objects, etc)
40fa9e406ahrens *     we have a simple routine to test that functionality.  These
41fa9e406ahrens *     individual routines do not have to do anything "stressful".
42fa9e406ahrens *
43fa9e406ahrens * (2) We turn these simple functionality tests into a stress test by
44fa9e406ahrens *     running them all in parallel, with as many threads as desired,
45fa9e406ahrens *     and spread across as many datasets, objects, and vdevs as desired.
46fa9e406ahrens *
47fa9e406ahrens * (3) While all this is happening, we inject faults into the pool to
48fa9e406ahrens *     verify that self-healing data really works.
49fa9e406ahrens *
50fa9e406ahrens * (4) Every time we open a dataset, we change its checksum and compression
51fa9e406ahrens *     functions.  Thus even individual objects vary from block to block
52fa9e406ahrens *     in which checksum they use and whether they're compressed.
53fa9e406ahrens *
54fa9e406ahrens * (5) To verify that we never lose on-disk consistency after a crash,
55fa9e406ahrens *     we run the entire test in a child of the main process.
56fa9e406ahrens *     At random times, the child self-immolates with a SIGKILL.
57fa9e406ahrens *     This is the software equivalent of pulling the power cord.
58fa9e406ahrens *     The parent then runs the test again, using the existing
595d7b4d4Matthew Ahrens *     storage pool, as many times as desired. If backwards compatibility
60420dfc9Chris Siden *     testing is enabled ztest will sometimes run the "older" version
61420dfc9Chris Siden *     of ztest after a SIGKILL.
62fa9e406ahrens *
63fa9e406ahrens * (6) To verify that we don't have future leaks or temporal incursions,
64fa9e406ahrens *     many of the functional tests record the transaction group number
65fa9e406ahrens *     as part of their data.  When reading old data, they verify that
66fa9e406ahrens *     the transaction group number is less than the current, open txg.
67fa9e406ahrens *     If you add a new test, please do this if applicable.
68fa9e406ahrens *
69fa9e406ahrens * When run with no arguments, ztest runs for about five minutes and
70fa9e406ahrens * produces no output if successful.  To get a little bit of information,
71fa9e406ahrens * specify -V.  To get more information, specify -VV, and so on.
72fa9e406ahrens *
73fa9e406ahrens * To turn this into an overnight stress test, use -T to specify run time.
74fa9e406ahrens *
75fa9e406ahrens * You can ask more more vdevs [-v], datasets [-d], or threads [-t]
76fa9e406ahrens * to increase the pool capacity, fanout, and overall stress level.
77fa9e406ahrens *
78420dfc9Chris Siden * Use the -k option to set the desired frequency of kills.
79420dfc9Chris Siden *
80420dfc9Chris Siden * When ztest invokes itself it passes all relevant information through a
81420dfc9Chris Siden * temporary file which is mmap-ed in the child process. This allows shared
82420dfc9Chris Siden * memory to survive the exec syscall. The ztest_shared_hdr_t struct is always
83420dfc9Chris Siden * stored at offset 0 of this file and contains information on the size and
84420dfc9Chris Siden * number of shared structures in the file. The information stored in this file
85420dfc9Chris Siden * must remain backwards compatible with older versions of ztest so that
86420dfc9Chris Siden * ztest can invoke them during backwards compatibility testing (-B).
87fa9e406ahrens */
89fa9e406ahrens#include <sys/zfs_context.h>
90fa9e406ahrens#include <sys/spa.h>
91fa9e406ahrens#include <sys/dmu.h>
92fa9e406ahrens#include <sys/txg.h>
932fdbea2Aleksandr Guzovskiy#include <sys/dbuf.h>
94fa9e406ahrens#include <sys/zap.h>
95fa9e406ahrens#include <sys/dmu_objset.h>
96fa9e406ahrens#include <sys/poll.h>
97fa9e406ahrens#include <sys/stat.h>
98fa9e406ahrens#include <sys/time.h>
99fa9e406ahrens#include <sys/wait.h>
100fa9e406ahrens#include <sys/mman.h>
101fa9e406ahrens#include <sys/resource.h>
102fa9e406ahrens#include <sys/zio.h>
103fa9e406ahrens#include <sys/zil.h>
104b24ab67Jeff Bonwick#include <sys/zil_impl.h>
105fa9e406ahrens#include <sys/vdev_impl.h>
106e14bb32Jeff Bonwick#include <sys/vdev_file.h>
107094e47eGeorge Wilson#include <sys/vdev_initialize.h>
108084fd14Brian Behlendorf#include <sys/vdev_trim.h>
109fa9e406ahrens#include <sys/spa_impl.h>
11088ecc94George Wilson#include <sys/metaslab_impl.h>
111fa9e406ahrens#include <sys/dsl_prop.h>
1124f5064bMark J Musante#include <sys/dsl_dataset.h>
1133b2aab1Matthew Ahrens#include <sys/dsl_destroy.h>
1143f9d6adLin Ling#include <sys/dsl_scan.h>
115cde58dbMatthew Ahrens#include <sys/zio_checksum.h>
116fa9e406ahrens#include <sys/refcount.h>
117ad135b5Christopher Siden#include <sys/zfeature.h>
1183b2aab1Matthew Ahrens#include <sys/dsl_userhold.h>
119770499eDan Kimmel#include <sys/abd.h>
120fa9e406ahrens#include <stdio.h>
121004388ecasper#include <stdio_ext.h>
122fa9e406ahrens#include <stdlib.h>
123fa9e406ahrens#include <unistd.h>
124fa9e406ahrens#include <signal.h>
125fa9e406ahrens#include <umem.h>
126fa9e406ahrens#include <dlfcn.h>
127fa9e406ahrens#include <ctype.h>
128fa9e406ahrens#include <math.h>
129fa9e406ahrens#include <sys/fs/zfs.h>
130b24ab67Jeff Bonwick#include <libnvpair.h>
131e0f1c0aOlaf Faaland#include <libzfs.h>
1320a05512Jason King#include <libcmdutils.h>
134741652bEtienne Dechampsstatic int ztest_fd_data = -1;
135741652bEtienne Dechampsstatic int ztest_fd_rand = -1;
136420dfc9Chris Siden
137420dfc9Chris Sidentypedef struct ztest_shared_hdr {
138420dfc9Chris Siden	uint64_t	zh_hdr_size;
139420dfc9Chris Siden	uint64_t	zh_opts_size;
140420dfc9Chris Siden	uint64_t	zh_size;
141420dfc9Chris Siden	uint64_t	zh_stats_size;
142420dfc9Chris Siden	uint64_t	zh_stats_count;
143420dfc9Chris Siden	uint64_t	zh_ds_size;
144420dfc9Chris Siden	uint64_t	zh_ds_count;
145420dfc9Chris Siden} ztest_shared_hdr_t;
146420dfc9Chris Siden
147420dfc9Chris Sidenstatic ztest_shared_hdr_t *ztest_shared_hdr;
148420dfc9Chris Siden
149663207aDon Bradyenum ztest_class_state {
150663207aDon Brady	ZTEST_VDEV_CLASS_OFF,
151663207aDon Brady	ZTEST_VDEV_CLASS_ON,
152663207aDon Brady	ZTEST_VDEV_CLASS_RND
153663207aDon Brady};
154663207aDon Brady
155420dfc9Chris Sidentypedef struct ztest_shared_opts {
1569adfa60Matthew Ahrens	char zo_pool[ZFS_MAX_DATASET_NAME_LEN];
1579adfa60Matthew Ahrens	char zo_dir[ZFS_MAX_DATASET_NAME_LEN];
158420dfc9Chris Siden	char zo_alt_ztest[MAXNAMELEN];
159420dfc9Chris Siden	char zo_alt_libpath[MAXNAMELEN];
160420dfc9Chris Siden	uint64_t zo_vdevs;
161420dfc9Chris Siden	uint64_t zo_vdevtime;
162420dfc9Chris Siden	size_t zo_vdev_size;
163420dfc9Chris Siden	int zo_ashift;
164420dfc9Chris Siden	int zo_mirrors;
165420dfc9Chris Siden	int zo_raidz;
166420dfc9Chris Siden	int zo_raidz_parity;
167420dfc9Chris Siden	int zo_datasets;
168420dfc9Chris Siden	int zo_threads;
169420dfc9Chris Siden	uint64_t zo_passtime;
170420dfc9Chris Siden	uint64_t zo_killrate;
171420dfc9Chris Siden	int zo_verbose;
172420dfc9Chris Siden	int zo_init;
173420dfc9Chris Siden	uint64_t zo_time;
174420dfc9Chris Siden	uint64_t zo_maxloops;
175243952cMatt Ahrens	uint64_t zo_metaslab_force_ganging;
176e0f1c0aOlaf Faaland	int zo_mmp_test;
177663207aDon Brady	int zo_special_vdevs;
178420dfc9Chris Siden} ztest_shared_opts_t;
179420dfc9Chris Siden
180420dfc9Chris Sidenstatic const ztest_shared_opts_t ztest_opts_defaults = {
181420dfc9Chris Siden	.zo_pool = { 'z', 't', 'e', 's', 't', '\0' },
182420dfc9Chris Siden	.zo_dir = { '/', 't', 'm', 'p', '\0' },
183420dfc9Chris Siden	.zo_alt_ztest = { '\0' },
184420dfc9Chris Siden	.zo_alt_libpath = { '\0' },
185420dfc9Chris Siden	.zo_vdevs = 5,
186420dfc9Chris Siden	.zo_ashift = SPA_MINBLOCKSHIFT,
187420dfc9Chris Siden	.zo_mirrors = 2,
188420dfc9Chris Siden	.zo_raidz = 4,
189420dfc9Chris Siden	.zo_raidz_parity = 1,
1908363e80George Wilson	.zo_vdev_size = SPA_MINDEVSIZE * 4,	/* 256m default size */
191420dfc9Chris Siden	.zo_datasets = 7,
192420dfc9Chris Siden	.zo_threads = 23,
193420dfc9Chris Siden	.zo_passtime = 60,		/* 60 seconds */
194420dfc9Chris Siden	.zo_killrate = 70,		/* 70% kill rate */
195420dfc9Chris Siden	.zo_verbose = 0,
196e0f1c0aOlaf Faaland	.zo_mmp_test = 0,
197420dfc9Chris Siden	.zo_init = 1,
198420dfc9Chris Siden	.zo_time = 300,			/* 5 minutes */
199420dfc9Chris Siden	.zo_maxloops = 50,		/* max loops during spa_freeze() */
200663207aDon Brady	.zo_metaslab_force_ganging = 32 << 10,
201663207aDon Brady	.zo_special_vdevs = ZTEST_VDEV_CLASS_RND,
202420dfc9Chris Siden};
203420dfc9Chris Siden
204243952cMatt Ahrensextern uint64_t metaslab_force_ganging;
205420dfc9Chris Sidenextern uint64_t metaslab_df_alloc_threshold;
20669962b5Matthew Ahrensextern uint64_t zfs_deadman_synctime_ms;
20730beaffGeorge Wilsonextern int metaslab_preload_limit;
208dcbf3bdGeorge Wilsonextern boolean_t zfs_compressed_arc_enabled;
209770499eDan Kimmelextern boolean_t zfs_abd_scatter_enabled;
21054811daToomas Soomeextern int dmu_object_alloc_chunk_shift;
21117f1128Serapheim Dimitropoulosextern boolean_t zfs_force_some_double_word_sm_entries;
212a21fe34Brian Behlendorfextern unsigned long zfs_reconstruct_indirect_damage_fraction;
213420dfc9Chris Siden
214420dfc9Chris Sidenstatic ztest_shared_opts_t *ztest_shared_opts;
215420dfc9Chris Sidenstatic ztest_shared_opts_t ztest_opts;
216eb63303Tom Caputistatic char *ztest_wkeydata = "abcdefghijklmnopqrstuvwxyz012345";
217420dfc9Chris Siden
218420dfc9Chris Sidentypedef struct ztest_shared_ds {
219420dfc9Chris Siden	uint64_t	zd_seq;
220420dfc9Chris Siden} ztest_shared_ds_t;
221420dfc9Chris Siden
222420dfc9Chris Sidenstatic ztest_shared_ds_t *ztest_shared_ds;
223420dfc9Chris Siden#define	ZTEST_GET_SHARED_DS(d) (&ztest_shared_ds[d])
225b24ab67Jeff Bonwick#define	BT_MAGIC	0x123456789abcdefULL
226420dfc9Chris Siden#define	MAXFAULTS() \
227420dfc9Chris Siden	(MAX(zs->zs_mirrors, 1) * (ztest_opts.zo_raidz_parity + 1) - 1)
228b24ab67Jeff Bonwick
229b24ab67Jeff Bonwickenum ztest_io_type {
230b24ab67Jeff Bonwick	ZTEST_IO_WRITE_TAG,
231b24ab67Jeff Bonwick	ZTEST_IO_WRITE_PATTERN,
232b24ab67Jeff Bonwick	ZTEST_IO_WRITE_ZEROES,
233b24ab67Jeff Bonwick	ZTEST_IO_TRUNCATE,
234b24ab67Jeff Bonwick	ZTEST_IO_SETATTR,
23580901aeGeorge Wilson	ZTEST_IO_REWRITE,
236b24ab67Jeff Bonwick	ZTEST_IO_TYPES
237b24ab67Jeff Bonwick};
238b24ab67Jeff Bonwick
239e05725bbonwicktypedef struct ztest_block_tag {
240b24ab67Jeff Bonwick	uint64_t	bt_magic;
241e05725bbonwick	uint64_t	bt_objset;
242e05725bbonwick	uint64_t	bt_object;
24354811daToomas Soome	uint64_t	bt_dnodesize;
244e05725bbonwick	uint64_t	bt_offset;
245b24ab67Jeff Bonwick	uint64_t	bt_gen;
246e05725bbonwick	uint64_t	bt_txg;
247b24ab67Jeff Bonwick	uint64_t	bt_crtxg;
248e05725bbonwick} ztest_block_tag_t;
250b24ab67Jeff Bonwicktypedef struct bufwad {
251b24ab67Jeff Bonwick	uint64_t	bw_index;
252b24ab67Jeff Bonwick	uint64_t	bw_txg;
253b24ab67Jeff Bonwick	uint64_t	bw_data;
254b24ab67Jeff Bonwick} bufwad_t;
255b24ab67Jeff Bonwick
256b24ab67Jeff Bonwick/*
2577931524Matthew Ahrens * It would be better to use a rangelock_t per object.  Unfortunately
2587931524Matthew Ahrens * the rangelock_t is not a drop-in replacement for rl_t, because we
2597931524Matthew Ahrens * still need to map from object ID to rangelock_t.
260b24ab67Jeff Bonwick */
261b24ab67Jeff Bonwicktypedef enum {
262b24ab67Jeff Bonwick	RL_READER,
263b24ab67Jeff Bonwick	RL_WRITER,
264b24ab67Jeff Bonwick	RL_APPEND
265b24ab67Jeff Bonwick} rl_type_t;
266b24ab67Jeff Bonwick
267b24ab67Jeff Bonwicktypedef struct rll {
268b24ab67Jeff Bonwick	void		*rll_writer;
269b24ab67Jeff Bonwick	int		rll_readers;
270f06dce2Andrew Stormont	kmutex_t	rll_lock;
271f06dce2Andrew Stormont	kcondvar_t	rll_cv;
272b24ab67Jeff Bonwick} rll_t;
273b24ab67Jeff Bonwick
274b24ab67Jeff Bonwicktypedef struct rl {
275b24ab67Jeff Bonwick	uint64_t	rl_object;
276b24ab67Jeff Bonwick	uint64_t	rl_offset;
277b24ab67Jeff Bonwick	uint64_t	rl_size;
278b24ab67Jeff Bonwick	rll_t		*rl_lock;
279b24ab67Jeff Bonwick} rl_t;
280b24ab67Jeff Bonwick
281b24ab67Jeff Bonwick#define	ZTEST_RANGE_LOCKS	64
282b24ab67Jeff Bonwick#define	ZTEST_OBJECT_LOCKS	64
283b24ab67Jeff Bonwick
284b24ab67Jeff Bonwick/*
285b24ab67Jeff Bonwick * Object descriptor.  Used as a template for object lookup/create/remove.
286b24ab67Jeff Bonwick */
287b24ab67Jeff Bonwicktypedef struct ztest_od {
288b24ab67Jeff Bonwick	uint64_t	od_dir;
289b24ab67Jeff Bonwick	uint64_t	od_object;
290b24ab67Jeff Bonwick	dmu_object_type_t od_type;
291b24ab67Jeff Bonwick	dmu_object_type_t od_crtype;
292b24ab67Jeff Bonwick	uint64_t	od_blocksize;
293b24ab67Jeff Bonwick	uint64_t	od_crblocksize;
29454811daToomas Soome	uint64_t	od_crdnodesize;
295b24ab67Jeff Bonwick	uint64_t	od_gen;
296b24ab67Jeff Bonwick	uint64_t	od_crgen;
2979adfa60Matthew Ahrens	char		od_name[ZFS_MAX_DATASET_NAME_LEN];
298b24ab67Jeff Bonwick} ztest_od_t;
300b24ab67Jeff Bonwick/*
301b24ab67Jeff Bonwick * Per-dataset state.
302b24ab67Jeff Bonwick */
303b24ab67Jeff Bonwicktypedef struct ztest_ds {
304420dfc9Chris Siden	ztest_shared_ds_t *zd_shared;
305b24ab67Jeff Bonwick	objset_t	*zd_os;
306f06dce2Andrew Stormont	krwlock_t	zd_zilog_lock;
307b24ab67Jeff Bonwick	zilog_t		*zd_zilog;
308b24ab67Jeff Bonwick	ztest_od_t	*zd_od;		/* debugging aid */
3099adfa60Matthew Ahrens	char		zd_name[ZFS_MAX_DATASET_NAME_LEN];
310f06dce2Andrew Stormont	kmutex_t	zd_dirobj_lock;
311b24ab67Jeff Bonwick	rll_t		zd_object_lock[ZTEST_OBJECT_LOCKS];
312b24ab67Jeff Bonwick	rll_t		zd_range_lock[ZTEST_RANGE_LOCKS];
313b24ab67Jeff Bonwick} ztest_ds_t;
314b24ab67Jeff Bonwick
315b24ab67Jeff Bonwick/*
316b24ab67Jeff Bonwick * Per-iteration state.
317b24ab67Jeff Bonwick */
318b24ab67Jeff Bonwicktypedef void ztest_func_t(ztest_ds_t *zd, uint64_t id);
319b24ab67Jeff Bonwick
320b24ab67Jeff Bonwicktypedef struct ztest_info {
321b24ab67Jeff Bonwick	ztest_func_t	*zi_func;	/* test function */
322b24ab67Jeff Bonwick	uint64_t	zi_iters;	/* iterations per execution */
323b24ab67Jeff Bonwick	uint64_t	*zi_interval;	/* execute every <interval> seconds */
324b24ab67Jeff Bonwick} ztest_info_t;
326420dfc9Chris Sidentypedef struct ztest_shared_callstate {
327420dfc9Chris Siden	uint64_t	zc_count;	/* per-pass count */
328420dfc9Chris Siden	uint64_t	zc_time;	/* per-pass time */
329420dfc9Chris Siden	uint64_t	zc_next;	/* next time to call this function */
330420dfc9Chris Siden} ztest_shared_callstate_t;
331420dfc9Chris Siden
332420dfc9Chris Sidenstatic ztest_shared_callstate_t *ztest_shared_callstate;
333420dfc9Chris Siden#define	ZTEST_GET_SHARED_CALLSTATE(c) (&ztest_shared_callstate[c])
334420dfc9Chris Siden
336fa9e406ahrens * Note: these aren't static because we want dladdr() to work.
337fa9e406ahrens */
338fa9e406ahrensztest_func_t ztest_dmu_read_write;
339fa9e406ahrensztest_func_t ztest_dmu_write_parallel;
340fa9e406ahrensztest_func_t ztest_dmu_object_alloc_free;
34154811daToomas Soomeztest_func_t ztest_dmu_object_next_chunk;
342d20e665Ricardo M. Correiaztest_func_t ztest_dmu_commit_callbacks;
343fa9e406ahrensztest_func_t ztest_zap;
344fa9e406ahrensztest_func_t ztest_zap_parallel;
345b24ab67Jeff Bonwickztest_func_t ztest_zil_commit;
346c9ba2a4Eric Schrockztest_func_t ztest_zil_remount;
347b24ab67Jeff Bonwickztest_func_t ztest_dmu_read_write_zcopy;
348fa9e406ahrensztest_func_t ztest_dmu_objset_create_destroy;
349b24ab67Jeff Bonwickztest_func_t ztest_dmu_prealloc;
350b24ab67Jeff Bonwickztest_func_t ztest_fzap;
351fa9e406ahrensztest_func_t ztest_dmu_snapshot_create_destroy;
352b24ab67Jeff Bonwickztest_func_t ztest_dsl_prop_get_set;
353b24ab67Jeff Bonwickztest_func_t ztest_spa_prop_get_set;
354fa9e406ahrensztest_func_t ztest_spa_create_destroy;
355fa9e406ahrensztest_func_t ztest_fault_inject;
356b24ab67Jeff Bonwickztest_func_t ztest_ddt_repair;
357b24ab67Jeff Bonwickztest_func_t ztest_dmu_snapshot_hold;
358e0f1c0aOlaf Faalandztest_func_t ztest_mmp_enable_disable;
359b24ab67Jeff Bonwickztest_func_t ztest_scrub;
360b24ab67Jeff Bonwickztest_func_t ztest_dsl_dataset_promote_busy;
361fa9e406ahrensztest_func_t ztest_vdev_attach_detach;
362fa9e406ahrensztest_func_t ztest_vdev_LUN_growth;
363fa9e406ahrensztest_func_t ztest_vdev_add_remove;
364663207aDon Bradyztest_func_t ztest_vdev_class_add;
365e14bb32Jeff Bonwickztest_func_t ztest_vdev_aux_add_remove;
3661195e68Mark J Musanteztest_func_t ztest_split_pool;
367e9103aaGarrett D'Amoreztest_func_t ztest_reguid;
36825345e4George Wilsonztest_func_t ztest_spa_upgrade;
3695cabbc6Prashanth Sreenivasaztest_func_t ztest_device_removal;
3705cabbc6Prashanth Sreenivasaztest_func_t ztest_remap_blocks;
3718671400Serapheim Dimitropoulosztest_func_t ztest_spa_checkpoint_create_discard;
372094e47eGeorge Wilsonztest_func_t ztest_initialize;
373084fd14Brian Behlendorfztest_func_t ztest_trim;
37454811daToomas Soomeztest_func_t ztest_verify_dnode_bt;
376b24ab67Jeff Bonwickuint64_t zopt_always = 0ULL * NANOSEC;		/* all the time */
377b24ab67Jeff Bonwickuint64_t zopt_incessant = 1ULL * NANOSEC / 10;	/* every 1/10 second */
378b24ab67Jeff Bonwickuint64_t zopt_often = 1ULL * NANOSEC;		/* every second */
379b24ab67Jeff Bonwickuint64_t zopt_sometimes = 10ULL * NANOSEC;	/* every 10 seconds */
380b24ab67Jeff Bonwickuint64_t zopt_rarely = 60ULL * NANOSEC;		/* every 60 seconds */
382fa9e406ahrensztest_info_t ztest_info[] = {
383e05725bbonwick	{ ztest_dmu_read_write,			1,	&zopt_always	},
384b24ab67Jeff Bonwick	{ ztest_dmu_write_parallel,		10,	&zopt_always	},
385e05725bbonwick	{ ztest_dmu_object_alloc_free,		1,	&zopt_always	},
38654811daToomas Soome	{ ztest_dmu_object_next_chunk,		1,	&zopt_sometimes	},
387b24ab67Jeff Bonwick	{ ztest_dmu_commit_callbacks,		1,	&zopt_always	},
388e05725bbonwick	{ ztest_zap,				30,	&zopt_always	},
389e05725bbonwick	{ ztest_zap_parallel,			100,	&zopt_always	},
3901195e68Mark J Musante	{ ztest_split_pool,			1,	&zopt_always	},
391b24ab67Jeff Bonwick	{ ztest_zil_commit,			1,	&zopt_incessant	},
392c9ba2a4Eric Schrock	{ ztest_zil_remount,			1,	&zopt_sometimes	},
393b24ab67Jeff Bonwick	{ ztest_dmu_read_write_zcopy,		1,	&zopt_often	},
394b24ab67Jeff Bonwick	{ ztest_dmu_objset_create_destroy,	1,	&zopt_often	},
395b24ab67Jeff Bonwick	{ ztest_dsl_prop_get_set,		1,	&zopt_often	},
396b24ab67Jeff Bonwick	{ ztest_spa_prop_get_set,		1,	&zopt_sometimes	},
397b24ab67Jeff Bonwick#if 0
398b24ab67Jeff Bonwick	{ ztest_dmu_prealloc,			1,	&zopt_sometimes	},
399b24ab67Jeff Bonwick#endif
400b24ab67Jeff Bonwick	{ ztest_fzap,				1,	&zopt_sometimes	},
401b24ab67Jeff Bonwick	{ ztest_dmu_snapshot_create_destroy,	1,	&zopt_sometimes	},
402b24ab67Jeff Bonwick	{ ztest_spa_create_destroy,		1,	&zopt_sometimes	},
403a3874b8Toomas Soome	{ ztest_fault_inject,			1,	&zopt_incessant	},
404b24ab67Jeff Bonwick	{ ztest_ddt_repair,			1,	&zopt_sometimes	},
4055c987a3Chris Kirby	{ ztest_dmu_snapshot_hold,		1,	&zopt_sometimes	},
406e0f1c0aOlaf Faaland	{ ztest_mmp_enable_disable,		1,	&zopt_sometimes	},
4072c1e2b4George Wilson	{ ztest_reguid,				1,	&zopt_rarely	},
408a3874b8Toomas Soome	{ ztest_scrub,				1,	&zopt_often	},
40925345e4George Wilson	{ ztest_spa_upgrade,			1,	&zopt_rarely	},
410b24ab67Jeff Bonwick	{ ztest_dsl_dataset_promote_busy,	1,	&zopt_rarely	},
411a3874b8Toomas Soome	{ ztest_vdev_attach_detach,		1,	&zopt_incessant	},
412e14bb32Jeff Bonwick	{ ztest_vdev_LUN_growth,		1,	&zopt_rarely	},
413420dfc9Chris Siden	{ ztest_vdev_add_remove,		1,
414420dfc9Chris Siden	    &ztest_opts.zo_vdevtime				},
415663207aDon Brady	{ ztest_vdev_class_add,			1,
416663207aDon Brady	    &ztest_opts.zo_vdevtime				},
417420dfc9Chris Siden	{ ztest_vdev_aux_add_remove,		1,
418420dfc9Chris Siden	    &ztest_opts.zo_vdevtime				},
4195cabbc6Prashanth Sreenivasa	{ ztest_device_removal,			1,	&zopt_sometimes	},
4208671400Serapheim Dimitropoulos	{ ztest_remap_blocks,			1,	&zopt_sometimes },
421094e47eGeorge Wilson	{ ztest_spa_checkpoint_create_discard,	1,	&zopt_rarely	},
42254811daToomas Soome	{ ztest_initialize,			1,	&zopt_sometimes },
423084fd14Brian Behlendorf	{ ztest_trim,				1,	&zopt_sometimes },
42454811daToomas Soome	{ ztest_verify_dnode_bt,		1,	&zopt_sometimes }
427fa9e406ahrens#define	ZTEST_FUNCS	(sizeof (ztest_info) / sizeof (ztest_info_t))
430d20e665Ricardo M. Correia * The following struct is used to hold a list of uncalled commit callbacks.
431d20e665Ricardo M. Correia * The callbacks are ordered by txg number.
432d20e665Ricardo M. Correia */
433d20e665Ricardo M. Correiatypedef struct ztest_cb_list {
434f06dce2Andrew Stormont	kmutex_t zcl_callbacks_lock;
435d20e665Ricardo M. Correia	list_t	zcl_callbacks;
436d20e665Ricardo M. Correia} ztest_cb_list_t;
437d20e665Ricardo M. Correia
438d20e665Ricardo M. Correia/*
439fa9e406ahrens * Stuff we need to share writably between parent and child.
440fa9e406ahrens */
441fa9e406ahrenstypedef struct ztest_shared {
442420dfc9Chris Siden	boolean_t	zs_do_init;
443b24ab67Jeff Bonwick	hrtime_t	zs_proc_start;
444b24ab67Jeff Bonwick	hrtime_t	zs_proc_stop;
445b24ab67Jeff Bonwick	hrtime_t	zs_thread_start;
446b24ab67Jeff Bonwick	hrtime_t	zs_thread_stop;
447b24ab67Jeff Bonwick	hrtime_t	zs_thread_kill;
448b24ab67Jeff Bonwick	uint64_t	zs_enospc_count;
44988ecc94George Wilson	uint64_t	zs_vdev_next_leaf;
450e14bb32Jeff Bonwick	uint64_t	zs_vdev_aux;
451fa9e406ahrens	uint64_t	zs_alloc;
452fa9e406ahrens	uint64_t	zs_space;
4531195e68Mark J Musante	uint64_t	zs_splits;
4541195e68Mark J Musante	uint64_t	zs_mirrors;
455420dfc9Chris Siden	uint64_t	zs_metaslab_sz;
456420dfc9Chris Siden	uint64_t	zs_metaslab_df_alloc_threshold;
457420dfc9Chris Siden	uint64_t	zs_guid;
458fa9e406ahrens} ztest_shared_t;
460b24ab67Jeff Bonwick#define	ID_PARALLEL	-1ULL
461b24ab67Jeff Bonwick
462fa9e406ahrensstatic char ztest_dev_template[] = "%s/%s.%llua";
463e14bb32Jeff Bonwickstatic char ztest_aux_template[] = "%s/%s.%s.%llu";
464b24ab67Jeff Bonwickztest_shared_t *ztest_shared;
466420dfc9Chris Sidenstatic spa_t *ztest_spa = NULL;
467420dfc9Chris Sidenstatic ztest_ds_t *ztest_ds;
468420dfc9Chris Siden
469f06dce2Andrew Stormontstatic kmutex_t ztest_vdev_lock;
4703a4b1beMatthew Ahrensstatic boolean_t ztest_device_removal_active = B_FALSE;
47154811daToomas Soomestatic kmutex_t ztest_checkpoint_lock;
472dfbb943George Wilson
473dfbb943George Wilson/*
474dfbb943George Wilson * The ztest_name_lock protects the pool and dataset namespace used by
475dfbb943George Wilson * the individual tests. To modify the namespace, consumers must grab
476dfbb943George Wilson * this lock as writer. Grabbing the lock as reader will ensure that the
477dfbb943George Wilson * namespace does not change while the lock is held.
478dfbb943George Wilson */
479f06dce2Andrew Stormontstatic krwlock_t ztest_name_lock;
481420dfc9Chris Sidenstatic boolean_t ztest_dump_core = B_TRUE;
482e14bb32Jeff Bonwickstatic boolean_t ztest_exiting;
484d20e665Ricardo M. Correia/* Global commit callback list */
485d20e665Ricardo M. Correiastatic ztest_cb_list_t zcl;
486d20e665Ricardo M. Correia
487b24ab67Jeff Bonwickenum ztest_object {
488b24ab67Jeff Bonwick	ZTEST_META_DNODE = 0,
489b24ab67Jeff Bonwick	ZTEST_DIROBJ,
490b24ab67Jeff Bonwick	ZTEST_OBJECTS
491b24ab67Jeff Bonwick};
4931ce825drafstatic void usage(boolean_t) __NORETURN;
496fa9e406ahrens * These libumem hooks provide a reasonable set of defaults for the allocator's
497fa9e406ahrens * debugging facilities.
498fa9e406ahrens */
499fa9e406ahrensconst char *
502fa9e406ahrens	return ("default,verbose"); /* $UMEM_DEBUG setting */
505fa9e406ahrensconst char *
508fa9e406ahrens	return ("fail,contents"); /* $UMEM_LOGGING setting */
511fa9e406ahrens#define	FATAL_MSG_SZ	1024
513fa9e406ahrenschar *fatal_msg;
515fa9e406ahrensstatic void
516fa9e406ahrensfatal(int do_perror, char *message, ...)
518fa9e406ahrens	va_list args;
519fa9e406ahrens	int save_errno = errno;
520fa9e406ahrens	char buf[FATAL_MSG_SZ];
522fa9e406ahrens	(void) fflush(stdout);
524fa9e406ahrens	va_start(args, message);
525fa9e406ahrens	(void) sprintf(buf, "ztest: ");
526fa9e406ahrens	/* LINTED */
527fa9e406ahrens	(void) vsprintf(buf + strlen(buf), message, args);
528fa9e406ahrens	va_end(args);
529fa9e406ahrens	if (do_perror) {
530fa9e406ahrens		(void) snprintf(buf + strlen(buf), FATAL_MSG_SZ - strlen(buf),
531fa9e406ahrens		    ": %s", strerror(save_errno));
532fa9e406ahrens	}
533fa9e406ahrens	(void) fprintf(stderr, "%s\n", buf);
534fa9e406ahrens	fatal_msg = buf;			/* to ease debugging */
535fa9e406ahrens	if (ztest_dump_core)
536fa9e406ahrens		abort();
537fa9e406ahrens	exit(3);
540fa9e406ahrensstatic int
541fa9e406ahrensstr2shift(const char *buf)
543fa9e406ahrens	const char *ends = "BKMGTPEZ";
544fa9e406ahrens	int i;
546fa9e406ahrens	if (buf[0] == '\0')
547fa9e406ahrens		return (0);
548fa9e406ahrens	for (i = 0; i < strlen(ends); i++) {
549fa9e406ahrens		if (toupper(buf[0]) == ends[i])
550fa9e406ahrens			break;
551fa9e406ahrens	}
552f1b4288vb	if (i == strlen(ends)) {
553f1b4288vb		(void) fprintf(stderr, "ztest: invalid bytes suffix: %s\n",
554f1b4288vb		    buf);
555f1b4288vb		usage(B_FALSE);
556f1b4288vb	}
557fa9e406ahrens	if (buf[1] == '\0' || (toupper(buf[1]) == 'B' && buf[2] == '\0')) {
558fa9e406ahrens		return (10*i);
559fa9e406ahrens	}
560f1b4288vb	(void) fprintf(stderr, "ztest: invalid bytes suffix: %s\n", buf);
561f1b4288vb	usage(B_FALSE);
562f1b4288vb	/* NOTREACHED */
565fa9e406ahrensstatic uint64_t
566fa9e406ahrensnicenumtoull(const char *buf)
568fa9e406ahrens	char *end;
569fa9e406ahrens	uint64_t val;
571fa9e406ahrens	val = strtoull(buf, &end, 0);
572fa9e406ahrens	if (end == buf) {
573f1b4288vb		(void) fprintf(stderr, "ztest: bad numeric value: %s\n", buf);
574f1b4288vb		usage(B_FALSE);
575fa9e406ahrens	} else if (end[0] == '.') {
576fa9e406ahrens		double fval = strtod(buf, &end);
577fa9e406ahrens		fval *= pow(2, str2shift(end));
578f1b4288vb		if (fval > UINT64_MAX) {
579f1b4288vb			(void) fprintf(stderr, "ztest: value too large: %s\n",
580f1b4288vb			    buf);
581f1b4288vb			usage(B_FALSE);
582f1b4288vb		}
583fa9e406ahrens		val = (uint64_t)fval;
584fa9e406ahrens	} else {
585fa9e406ahrens		int shift = str2shift(end);
586f1b4288vb		if (shift >= 64 || (val << shift) >> shift != val) {
587f1b4288vb			(void) fprintf(stderr, "ztest: value too large: %s\n",
588f1b4288vb			    buf);
589f1b4288vb			usage(B_FALSE);
590f1b4288vb		}
591fa9e406ahrens		val <<= shift;
592fa9e406ahrens	}
593fa9e406ahrens	return (val);
596fa9e406ahrensstatic void
597f1b4288vbusage(boolean_t requested)
599420dfc9Chris Siden	const ztest_shared_opts_t *zo = &ztest_opts_defaults;
600420dfc9Chris Siden
6010a05512Jason King	char nice_vdev_size[NN_NUMBUF_SZ];
602243952cMatt Ahrens	char nice_force_ganging[NN_NUMBUF_SZ];
603f1b4288vb	FILE *fp = requested ? stdout : stderr;
6050a05512Jason King	nicenum(zo->zo_vdev_size, nice_vdev_size, sizeof (nice_vdev_size));
606243952cMatt Ahrens	nicenum(zo->zo_metaslab_force_ganging, nice_force_ganging,
607243952cMatt Ahrens	    sizeof (nice_force_ganging));
609f1b4288vb	(void) fprintf(fp, "Usage: %s\n"
610fa9e406ahrens	    "\t[-v vdevs (default: %llu)]\n"
611fa9e406ahrens	    "\t[-s size_of_each_vdev (default: %s)]\n"
6122215e99Mark J Musante	    "\t[-a alignment_shift (default: %d)] use 0 for random\n"
613fa9e406ahrens	    "\t[-m mirror_copies (default: %d)]\n"
614fa9e406ahrens	    "\t[-r raidz_disks (default: %d)]\n"
61599653d4eschrock	    "\t[-R raidz_parity (default: %d)]\n"
616fa9e406ahrens	    "\t[-d datasets (default: %d)]\n"
617fa9e406ahrens	    "\t[-t threads (default: %d)]\n"
618fa9e406ahrens	    "\t[-g gang_block_threshold (default: %s)]\n"
6192215e99Mark J Musante	    "\t[-i init_count (default: %d)] initialize pool i times\n"
6202215e99Mark J Musante	    "\t[-k kill_percentage (default: %llu%%)]\n"
621fa9e406ahrens	    "\t[-p pool_name (default: %s)]\n"
6222215e99Mark J Musante	    "\t[-f dir (default: %s)] file directory for vdev files\n"
623e0f1c0aOlaf Faaland	    "\t[-M] Multi-host simulate pool imported on remote host\n"
6242215e99Mark J Musante	    "\t[-V] verbose (use multiple times for ever more blather)\n"
6252215e99Mark J Musante	    "\t[-E] use existing pool instead of creating new one\n"
6262215e99Mark J Musante	    "\t[-T time (default: %llu sec)] total run time\n"
6272215e99Mark J Musante	    "\t[-F freezeloops (default: %llu)] max loops in spa_freeze()\n"
6282215e99Mark J Musante	    "\t[-P passtime (default: %llu sec)] time per pass\n"
629420dfc9Chris Siden	    "\t[-B alt_ztest (default: <none>)] alternate ztest path\n"
630663207aDon Brady	    "\t[-C vdev class state (default: random)] special=on|off|random\n"
6310e60744Pavel Zakharov	    "\t[-o variable=value] ... set global variable to an unsigned\n"
6320e60744Pavel Zakharov	    "\t    32-bit integer value\n"
633f1b4288vb	    "\t[-h] (print help)\n"
634fa9e406ahrens	    "",
635420dfc9Chris Siden	    zo->zo_pool,
636420dfc9Chris Siden	    (u_longlong_t)zo->zo_vdevs,			/* -v */
6370a4e951gw	    nice_vdev_size,				/* -s */
638420dfc9Chris Siden	    zo->zo_ashift,				/* -a */
639420dfc9Chris Siden	    zo->zo_mirrors,				/* -m */
640420dfc9Chris Siden	    zo->zo_raidz,				/* -r */
641420dfc9Chris Siden	    zo->zo_raidz_parity,			/* -R */
642420dfc9Chris Siden	    zo->zo_datasets,				/* -d */
643420dfc9Chris Siden	    zo->zo_threads,				/* -t */
644243952cMatt Ahrens	    nice_force_ganging,				/* -g */
645420dfc9Chris Siden	    zo->zo_init,				/* -i */
646420dfc9Chris Siden	    (u_longlong_t)zo->zo_killrate,		/* -k */
647420dfc9Chris Siden	    zo->zo_pool,				/* -p */
648420dfc9Chris Siden	    zo->zo_dir,					/* -f */
649420dfc9Chris Siden	    (u_longlong_t)zo->zo_time,			/* -T */
650420dfc9Chris Siden	    (u_longlong_t)zo->zo_maxloops,		/* -F */
651420dfc9Chris Siden	    (u_longlong_t)zo->zo_passtime);
652f1b4288vb	exit(requested ? 0 : 1);
655663207aDon Brady
656663207aDon Bradystatic void
657663207aDon Bradyztest_parse_name_value(const char *input, ztest_shared_opts_t *zo)
658663207aDon Brady{
659663207aDon Brady	char name[32];
660663207aDon Brady	char *value;
661663207aDon Brady	int state = ZTEST_VDEV_CLASS_RND;
662663207aDon Brady
663663207aDon Brady	(void) strlcpy(name, input, sizeof (name));
664663207aDon Brady
665663207aDon Brady	value = strchr(name, '=');
666663207aDon Brady	if (value == NULL) {
667663207aDon Brady		(void) fprintf(stderr, "missing value in property=value "
668663207aDon Brady		    "'-C' argument (%s)\n", input);
669663207aDon Brady		usage(B_FALSE);
670663207aDon Brady	}
671663207aDon Brady	*(value) = '\0';
672663207aDon Brady	value++;
673663207aDon Brady
674663207aDon Brady	if (strcmp(value, "on") == 0) {
675663207aDon Brady		state = ZTEST_VDEV_CLASS_ON;
676663207aDon Brady	} else if (strcmp(value, "off") == 0) {
677663207aDon Brady		state = ZTEST_VDEV_CLASS_OFF;
678663207aDon Brady	} else if (strcmp(value, "random") == 0) {
679663207aDon Brady		state = ZTEST_VDEV_CLASS_RND;
680663207aDon Brady	} else {
681663207aDon Brady		(void) fprintf(stderr, "invalid property value '%s'\n", value);
682663207aDon Brady		usage(B_FALSE);
683663207aDon Brady	}
684663207aDon Brady
685663207aDon Brady	if (strcmp(name, "special") == 0) {
686663207aDon Brady		zo->zo_special_vdevs = state;
687663207aDon Brady	} else {
688663207aDon Brady		(void) fprintf(stderr, "invalid property name '%s'\n", name);
689663207aDon Brady		usage(B_FALSE);
690663207aDon Brady	}
691663207aDon Brady	if (zo->zo_verbose >= 3)
692663207aDon Brady		(void) printf("%s vdev state is '%s'\n", name, value);
693663207aDon Brady}
694663207aDon Brady
695fa9e406ahrensstatic void
696fa9e406ahrensprocess_options(int argc, char **argv)
698420dfc9Chris Siden	char *path;
699420dfc9Chris Siden	ztest_shared_opts_t *zo = &ztest_opts;
700420dfc9Chris Siden
701fa9e406ahrens	int opt;
702fa9e406ahrens	uint64_t value;
703420dfc9Chris Siden	char altdir[MAXNAMELEN] = { 0 };
705420dfc9Chris Siden	bcopy(&ztest_opts_defaults, zo, sizeof (*zo));
707fa9e406ahrens	while ((opt = getopt(argc, argv,
708663207aDon Brady	    "v:s:a:m:r:R:d:t:g:i:k:p:f:MVET:P:hF:B:C:o:")) != EOF) {
709fa9e406ahrens		value = 0;
710fa9e406ahrens		switch (opt) {
7113d7072feschrock		case 'v':
7123d7072feschrock		case 's':
7133d7072feschrock		case 'a':
7143d7072feschrock		case 'm':
7153d7072feschrock		case 'r':
7163d7072feschrock		case 'R':
7173d7072feschrock		case 'd':
7183d7072feschrock		case 't':
7193d7072feschrock		case 'g':
7203d7072feschrock		case 'i':
7213d7072feschrock		case 'k':
7223d7072feschrock		case 'T':
7233d7072feschrock		case 'P':
7242215e99Mark J Musante		case 'F':
725fa9e406ahrens			value = nicenumtoull(optarg);
726fa9e406ahrens		}
727fa9e406ahrens		switch (opt) {
7283d7072feschrock		case 'v':
729420dfc9Chris Siden			zo->zo_vdevs = value;
730fa9e406ahrens			break;
7313d7072feschrock		case 's':
732420dfc9Chris Siden			zo->zo_vdev_size = MAX(SPA_MINDEVSIZE, value);
733fa9e406ahrens			break;
7343d7072feschrock		case 'a':
735420dfc9Chris Siden			zo->zo_ashift = value;
736ecc2d60bonwick			break;
7373d7072feschrock		case 'm':
738420dfc9Chris Siden			zo->zo_mirrors = value;
739fa9e406ahrens			break;
7403d7072feschrock		case 'r':
741420dfc9Chris Siden			zo->zo_raidz = MAX(1, value);
742fa9e406ahrens			break;
7433d7072feschrock		case 'R':
744420dfc9Chris Siden			zo->zo_raidz_parity = MIN(MAX(value, 1), 3);
74599653d4eschrock			break;
7463d7072feschrock		case 'd':
747420dfc9Chris Siden			zo->zo_datasets = MAX(1, value);
748fa9e406ahrens			break;
7493d7072feschrock		case 't':
750420dfc9Chris Siden			zo->zo_threads = MAX(1, value);
751fa9e406ahrens			break;
7523d7072feschrock		case 'g':
753243952cMatt Ahrens			zo->zo_metaslab_force_ganging =
754243952cMatt Ahrens			    MAX(SPA_MINBLOCKSIZE << 1, value);
755fa9e406ahrens			break;
7563d7072feschrock		case 'i':
757420dfc9Chris Siden			zo->zo_init = value;
758fa9e406ahrens			break;
7593d7072feschrock		case 'k':
760420dfc9Chris Siden			zo->zo_killrate = value;
761fa9e406ahrens			break;
7623d7072feschrock		case 'p':
763420dfc9Chris Siden			(void) strlcpy(zo->zo_pool, optarg,
764420dfc9Chris Siden			    sizeof (zo->zo_pool));
765fa9e406ahrens			break;
7663d7072feschrock		case 'f':
767420dfc9Chris Siden			path = realpath(optarg, NULL);
768420dfc9Chris Siden			if (path == NULL) {
769420dfc9Chris Siden				(void) fprintf(stderr, "error: %s: %s\n",
770420dfc9Chris Siden				    optarg, strerror(errno));
771420dfc9Chris Siden				usage(B_FALSE);
772420dfc9Chris Siden			} else {
773420dfc9Chris Siden				(void) strlcpy(zo->zo_dir, path,
774420dfc9Chris Siden				    sizeof (zo->zo_dir));
775420dfc9Chris Siden			}
776fa9e406ahrens			break;
777e0f1c0aOlaf Faaland		case 'M':
778e0f1c0aOlaf Faaland			zo->zo_mmp_test = 1;
779e0f1c0aOlaf Faaland			break;
7803d7072feschrock		case 'V':
781420dfc9Chris Siden			zo->zo_verbose++;
782fa9e406ahrens			break;