Changeset View
Changeset View
Standalone View
Standalone View
sys/contrib/openzfs/cmd/ztest/ztest.c
Show First 20 Lines • Show All 992 Lines • ▼ Show 20 Lines | if (strlen(altdir) > 0) { | ||||
char *bin; | char *bin; | ||||
char *ztest; | char *ztest; | ||||
char *isa; | char *isa; | ||||
int isalen; | int isalen; | ||||
cmd = umem_alloc(MAXPATHLEN, UMEM_NOFAIL); | cmd = umem_alloc(MAXPATHLEN, UMEM_NOFAIL); | ||||
realaltdir = umem_alloc(MAXPATHLEN, UMEM_NOFAIL); | realaltdir = umem_alloc(MAXPATHLEN, UMEM_NOFAIL); | ||||
VERIFY(NULL != realpath(getexecname(), cmd)); | VERIFY3P(NULL, !=, realpath(getexecname(), cmd)); | ||||
if (0 != access(altdir, F_OK)) { | if (0 != access(altdir, F_OK)) { | ||||
ztest_dump_core = B_FALSE; | ztest_dump_core = B_FALSE; | ||||
fatal(B_TRUE, "invalid alternate ztest path: %s", | fatal(B_TRUE, "invalid alternate ztest path: %s", | ||||
altdir); | altdir); | ||||
} | } | ||||
VERIFY(NULL != realpath(altdir, realaltdir)); | VERIFY3P(NULL, !=, realpath(altdir, realaltdir)); | ||||
/* | /* | ||||
* 'cmd' should be of the form "<anything>/usr/bin/<isa>/ztest". | * 'cmd' should be of the form "<anything>/usr/bin/<isa>/ztest". | ||||
* We want to extract <isa> to determine if we should use | * We want to extract <isa> to determine if we should use | ||||
* 32 or 64 bit binaries. | * 32 or 64 bit binaries. | ||||
*/ | */ | ||||
bin = strstr(cmd, "/usr/bin/"); | bin = strstr(cmd, "/usr/bin/"); | ||||
ztest = strstr(bin, "/ztest"); | ztest = strstr(bin, "/ztest"); | ||||
▲ Show 20 Lines • Show All 101 Lines • ▼ Show 20 Lines | if (size != 0 && !draid_spare) { | ||||
int fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0666); | int fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0666); | ||||
if (fd == -1) | if (fd == -1) | ||||
fatal(1, "can't open %s", path); | fatal(1, "can't open %s", path); | ||||
if (ftruncate(fd, size) != 0) | if (ftruncate(fd, size) != 0) | ||||
fatal(1, "can't ftruncate %s", path); | fatal(1, "can't ftruncate %s", path); | ||||
(void) close(fd); | (void) close(fd); | ||||
} | } | ||||
VERIFY0(nvlist_alloc(&file, NV_UNIQUE_NAME, 0)); | file = fnvlist_alloc(); | ||||
VERIFY0(nvlist_add_string(file, ZPOOL_CONFIG_TYPE, | fnvlist_add_string(file, ZPOOL_CONFIG_TYPE, | ||||
draid_spare ? VDEV_TYPE_DRAID_SPARE : VDEV_TYPE_FILE)); | draid_spare ? VDEV_TYPE_DRAID_SPARE : VDEV_TYPE_FILE); | ||||
VERIFY0(nvlist_add_string(file, ZPOOL_CONFIG_PATH, path)); | fnvlist_add_string(file, ZPOOL_CONFIG_PATH, path); | ||||
VERIFY0(nvlist_add_uint64(file, ZPOOL_CONFIG_ASHIFT, ashift)); | fnvlist_add_uint64(file, ZPOOL_CONFIG_ASHIFT, ashift); | ||||
umem_free(pathbuf, MAXPATHLEN); | umem_free(pathbuf, MAXPATHLEN); | ||||
return (file); | return (file); | ||||
} | } | ||||
static nvlist_t * | static nvlist_t * | ||||
make_vdev_raid(char *path, char *aux, char *pool, size_t size, | make_vdev_raid(char *path, char *aux, char *pool, size_t size, | ||||
uint64_t ashift, int r) | uint64_t ashift, int r) | ||||
{ | { | ||||
nvlist_t *raid, **child; | nvlist_t *raid, **child; | ||||
int c; | int c; | ||||
if (r < 2) | if (r < 2) | ||||
return (make_vdev_file(path, aux, pool, size, ashift)); | return (make_vdev_file(path, aux, pool, size, ashift)); | ||||
child = umem_alloc(r * sizeof (nvlist_t *), UMEM_NOFAIL); | child = umem_alloc(r * sizeof (nvlist_t *), UMEM_NOFAIL); | ||||
for (c = 0; c < r; c++) | for (c = 0; c < r; c++) | ||||
child[c] = make_vdev_file(path, aux, pool, size, ashift); | child[c] = make_vdev_file(path, aux, pool, size, ashift); | ||||
VERIFY0(nvlist_alloc(&raid, NV_UNIQUE_NAME, 0)); | raid = fnvlist_alloc(); | ||||
VERIFY0(nvlist_add_string(raid, ZPOOL_CONFIG_TYPE, | fnvlist_add_string(raid, ZPOOL_CONFIG_TYPE, | ||||
ztest_opts.zo_raid_type)); | ztest_opts.zo_raid_type); | ||||
VERIFY0(nvlist_add_uint64(raid, ZPOOL_CONFIG_NPARITY, | fnvlist_add_uint64(raid, ZPOOL_CONFIG_NPARITY, | ||||
ztest_opts.zo_raid_parity)); | ztest_opts.zo_raid_parity); | ||||
VERIFY0(nvlist_add_nvlist_array(raid, ZPOOL_CONFIG_CHILDREN, | fnvlist_add_nvlist_array(raid, ZPOOL_CONFIG_CHILDREN, child, r); | ||||
child, r)); | |||||
if (strcmp(ztest_opts.zo_raid_type, VDEV_TYPE_DRAID) == 0) { | if (strcmp(ztest_opts.zo_raid_type, VDEV_TYPE_DRAID) == 0) { | ||||
uint64_t ndata = ztest_opts.zo_draid_data; | uint64_t ndata = ztest_opts.zo_draid_data; | ||||
uint64_t nparity = ztest_opts.zo_raid_parity; | uint64_t nparity = ztest_opts.zo_raid_parity; | ||||
uint64_t nspares = ztest_opts.zo_draid_spares; | uint64_t nspares = ztest_opts.zo_draid_spares; | ||||
uint64_t children = ztest_opts.zo_raid_children; | uint64_t children = ztest_opts.zo_raid_children; | ||||
uint64_t ngroups = 1; | uint64_t ngroups = 1; | ||||
/* | /* | ||||
* Calculate the minimum number of groups required to fill a | * Calculate the minimum number of groups required to fill a | ||||
* slice. This is the LCM of the stripe width (data + parity) | * slice. This is the LCM of the stripe width (data + parity) | ||||
* and the number of data drives (children - spares). | * and the number of data drives (children - spares). | ||||
*/ | */ | ||||
while (ngroups * (ndata + nparity) % (children - nspares) != 0) | while (ngroups * (ndata + nparity) % (children - nspares) != 0) | ||||
ngroups++; | ngroups++; | ||||
/* Store the basic dRAID configuration. */ | /* Store the basic dRAID configuration. */ | ||||
fnvlist_add_uint64(raid, ZPOOL_CONFIG_DRAID_NDATA, ndata); | fnvlist_add_uint64(raid, ZPOOL_CONFIG_DRAID_NDATA, ndata); | ||||
fnvlist_add_uint64(raid, ZPOOL_CONFIG_DRAID_NSPARES, nspares); | fnvlist_add_uint64(raid, ZPOOL_CONFIG_DRAID_NSPARES, nspares); | ||||
fnvlist_add_uint64(raid, ZPOOL_CONFIG_DRAID_NGROUPS, ngroups); | fnvlist_add_uint64(raid, ZPOOL_CONFIG_DRAID_NGROUPS, ngroups); | ||||
} | } | ||||
for (c = 0; c < r; c++) | for (c = 0; c < r; c++) | ||||
nvlist_free(child[c]); | fnvlist_free(child[c]); | ||||
umem_free(child, r * sizeof (nvlist_t *)); | umem_free(child, r * sizeof (nvlist_t *)); | ||||
return (raid); | return (raid); | ||||
} | } | ||||
static nvlist_t * | static nvlist_t * | ||||
make_vdev_mirror(char *path, char *aux, char *pool, size_t size, | make_vdev_mirror(char *path, char *aux, char *pool, size_t size, | ||||
uint64_t ashift, int r, int m) | uint64_t ashift, int r, int m) | ||||
{ | { | ||||
nvlist_t *mirror, **child; | nvlist_t *mirror, **child; | ||||
int c; | int c; | ||||
if (m < 1) | if (m < 1) | ||||
return (make_vdev_raid(path, aux, pool, size, ashift, r)); | return (make_vdev_raid(path, aux, pool, size, ashift, r)); | ||||
child = umem_alloc(m * sizeof (nvlist_t *), UMEM_NOFAIL); | child = umem_alloc(m * sizeof (nvlist_t *), UMEM_NOFAIL); | ||||
for (c = 0; c < m; c++) | for (c = 0; c < m; c++) | ||||
child[c] = make_vdev_raid(path, aux, pool, size, ashift, r); | child[c] = make_vdev_raid(path, aux, pool, size, ashift, r); | ||||
VERIFY(nvlist_alloc(&mirror, NV_UNIQUE_NAME, 0) == 0); | mirror = fnvlist_alloc(); | ||||
VERIFY(nvlist_add_string(mirror, ZPOOL_CONFIG_TYPE, | fnvlist_add_string(mirror, ZPOOL_CONFIG_TYPE, VDEV_TYPE_MIRROR); | ||||
VDEV_TYPE_MIRROR) == 0); | fnvlist_add_nvlist_array(mirror, ZPOOL_CONFIG_CHILDREN, child, m); | ||||
VERIFY(nvlist_add_nvlist_array(mirror, ZPOOL_CONFIG_CHILDREN, | |||||
child, m) == 0); | |||||
for (c = 0; c < m; c++) | for (c = 0; c < m; c++) | ||||
nvlist_free(child[c]); | fnvlist_free(child[c]); | ||||
umem_free(child, m * sizeof (nvlist_t *)); | umem_free(child, m * sizeof (nvlist_t *)); | ||||
return (mirror); | return (mirror); | ||||
} | } | ||||
static nvlist_t * | static nvlist_t * | ||||
make_vdev_root(char *path, char *aux, char *pool, size_t size, uint64_t ashift, | make_vdev_root(char *path, char *aux, char *pool, size_t size, uint64_t ashift, | ||||
const char *class, int r, int m, int t) | const char *class, int r, int m, int t) | ||||
{ | { | ||||
nvlist_t *root, **child; | nvlist_t *root, **child; | ||||
int c; | int c; | ||||
boolean_t log; | boolean_t log; | ||||
ASSERT(t > 0); | ASSERT3S(t, >, 0); | ||||
log = (class != NULL && strcmp(class, "log") == 0); | log = (class != NULL && strcmp(class, "log") == 0); | ||||
child = umem_alloc(t * sizeof (nvlist_t *), UMEM_NOFAIL); | child = umem_alloc(t * sizeof (nvlist_t *), UMEM_NOFAIL); | ||||
for (c = 0; c < t; c++) { | for (c = 0; c < t; c++) { | ||||
child[c] = make_vdev_mirror(path, aux, pool, size, ashift, | child[c] = make_vdev_mirror(path, aux, pool, size, ashift, | ||||
r, m); | r, m); | ||||
VERIFY(nvlist_add_uint64(child[c], ZPOOL_CONFIG_IS_LOG, | fnvlist_add_uint64(child[c], ZPOOL_CONFIG_IS_LOG, log); | ||||
log) == 0); | |||||
if (class != NULL && class[0] != '\0') { | if (class != NULL && class[0] != '\0') { | ||||
ASSERT(m > 1 || log); /* expecting a mirror */ | ASSERT(m > 1 || log); /* expecting a mirror */ | ||||
VERIFY(nvlist_add_string(child[c], | fnvlist_add_string(child[c], | ||||
ZPOOL_CONFIG_ALLOCATION_BIAS, class) == 0); | ZPOOL_CONFIG_ALLOCATION_BIAS, class); | ||||
} | } | ||||
} | } | ||||
VERIFY(nvlist_alloc(&root, NV_UNIQUE_NAME, 0) == 0); | root = fnvlist_alloc(); | ||||
VERIFY(nvlist_add_string(root, ZPOOL_CONFIG_TYPE, VDEV_TYPE_ROOT) == 0); | fnvlist_add_string(root, ZPOOL_CONFIG_TYPE, VDEV_TYPE_ROOT); | ||||
VERIFY(nvlist_add_nvlist_array(root, aux ? aux : ZPOOL_CONFIG_CHILDREN, | fnvlist_add_nvlist_array(root, aux ? aux : ZPOOL_CONFIG_CHILDREN, | ||||
child, t) == 0); | child, t); | ||||
for (c = 0; c < t; c++) | for (c = 0; c < t; c++) | ||||
nvlist_free(child[c]); | fnvlist_free(child[c]); | ||||
umem_free(child, t * sizeof (nvlist_t *)); | umem_free(child, t * sizeof (nvlist_t *)); | ||||
return (root); | return (root); | ||||
} | } | ||||
/* | /* | ||||
* Find a random spa version. Returns back a random spa version in the | * Find a random spa version. Returns back a random spa version in the | ||||
Show All 14 Lines | ztest_random_spa_version(uint64_t initial_version) | ||||
ASSERT(SPA_VERSION_IS_SUPPORTED(version)); | ASSERT(SPA_VERSION_IS_SUPPORTED(version)); | ||||
return (version); | return (version); | ||||
} | } | ||||
static int | static int | ||||
ztest_random_blocksize(void) | ztest_random_blocksize(void) | ||||
{ | { | ||||
ASSERT(ztest_spa->spa_max_ashift != 0); | ASSERT3U(ztest_spa->spa_max_ashift, !=, 0); | ||||
/* | /* | ||||
* Choose a block size >= the ashift. | * Choose a block size >= the ashift. | ||||
* If the SPA supports new MAXBLOCKSIZE, test up to 1MB blocks. | * If the SPA supports new MAXBLOCKSIZE, test up to 1MB blocks. | ||||
*/ | */ | ||||
int maxbs = SPA_OLD_MAXBLOCKSHIFT; | int maxbs = SPA_OLD_MAXBLOCKSHIFT; | ||||
if (spa_maxblocksize(ztest_spa) == SPA_MAXBLOCKSIZE) | if (spa_maxblocksize(ztest_spa) == SPA_MAXBLOCKSIZE) | ||||
maxbs = 20; | maxbs = 20; | ||||
▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | |||||
static uint64_t | static uint64_t | ||||
ztest_random_vdev_top(spa_t *spa, boolean_t log_ok) | ztest_random_vdev_top(spa_t *spa, boolean_t log_ok) | ||||
{ | { | ||||
uint64_t top; | uint64_t top; | ||||
vdev_t *rvd = spa->spa_root_vdev; | vdev_t *rvd = spa->spa_root_vdev; | ||||
vdev_t *tvd; | vdev_t *tvd; | ||||
ASSERT(spa_config_held(spa, SCL_ALL, RW_READER) != 0); | ASSERT3U(spa_config_held(spa, SCL_ALL, RW_READER), !=, 0); | ||||
do { | do { | ||||
top = ztest_random(rvd->vdev_children); | top = ztest_random(rvd->vdev_children); | ||||
tvd = rvd->vdev_child[top]; | tvd = rvd->vdev_child[top]; | ||||
} while (!vdev_is_concrete(tvd) || (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); | tvd->vdev_mg == NULL || tvd->vdev_mg->mg_class == NULL); | ||||
return (top); | return (top); | ||||
▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | |||||
static int | static int | ||||
ztest_spa_prop_set_uint64(zpool_prop_t prop, uint64_t value) | ztest_spa_prop_set_uint64(zpool_prop_t prop, uint64_t value) | ||||
{ | { | ||||
spa_t *spa = ztest_spa; | spa_t *spa = ztest_spa; | ||||
nvlist_t *props = NULL; | nvlist_t *props = NULL; | ||||
int error; | int error; | ||||
VERIFY(nvlist_alloc(&props, NV_UNIQUE_NAME, 0) == 0); | props = fnvlist_alloc(); | ||||
VERIFY(nvlist_add_uint64(props, zpool_prop_to_name(prop), value) == 0); | fnvlist_add_uint64(props, zpool_prop_to_name(prop), value); | ||||
error = spa_prop_set(spa, props); | error = spa_prop_set(spa, props); | ||||
nvlist_free(props); | fnvlist_free(props); | ||||
if (error == ENOSPC) { | if (error == ENOSPC) { | ||||
ztest_record_enospc(FTAG); | ztest_record_enospc(FTAG); | ||||
return (error); | return (error); | ||||
} | } | ||||
ASSERT0(error); | ASSERT0(error); | ||||
return (error); | return (error); | ||||
▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | ztest_rll_init(rll_t *rll) | ||||
rll->rll_readers = 0; | rll->rll_readers = 0; | ||||
mutex_init(&rll->rll_lock, NULL, MUTEX_DEFAULT, NULL); | mutex_init(&rll->rll_lock, NULL, MUTEX_DEFAULT, NULL); | ||||
cv_init(&rll->rll_cv, NULL, CV_DEFAULT, NULL); | cv_init(&rll->rll_cv, NULL, CV_DEFAULT, NULL); | ||||
} | } | ||||
static void | static void | ||||
ztest_rll_destroy(rll_t *rll) | ztest_rll_destroy(rll_t *rll) | ||||
{ | { | ||||
ASSERT(rll->rll_writer == NULL); | ASSERT3P(rll->rll_writer, ==, NULL); | ||||
ASSERT(rll->rll_readers == 0); | ASSERT0(rll->rll_readers); | ||||
mutex_destroy(&rll->rll_lock); | mutex_destroy(&rll->rll_lock); | ||||
cv_destroy(&rll->rll_cv); | cv_destroy(&rll->rll_cv); | ||||
} | } | ||||
static void | static void | ||||
ztest_rll_lock(rll_t *rll, rl_type_t type) | ztest_rll_lock(rll_t *rll, rl_type_t type) | ||||
{ | { | ||||
mutex_enter(&rll->rll_lock); | mutex_enter(&rll->rll_lock); | ||||
Show All 12 Lines | |||||
} | } | ||||
static void | static void | ||||
ztest_rll_unlock(rll_t *rll) | ztest_rll_unlock(rll_t *rll) | ||||
{ | { | ||||
mutex_enter(&rll->rll_lock); | mutex_enter(&rll->rll_lock); | ||||
if (rll->rll_writer) { | if (rll->rll_writer) { | ||||
ASSERT(rll->rll_readers == 0); | ASSERT0(rll->rll_readers); | ||||
rll->rll_writer = NULL; | rll->rll_writer = NULL; | ||||
} else { | } else { | ||||
ASSERT(rll->rll_readers != 0); | ASSERT3S(rll->rll_readers, >, 0); | ||||
ASSERT(rll->rll_writer == NULL); | ASSERT3P(rll->rll_writer, ==, NULL); | ||||
rll->rll_readers--; | rll->rll_readers--; | ||||
} | } | ||||
if (rll->rll_writer == NULL && rll->rll_readers == 0) | if (rll->rll_writer == NULL && rll->rll_readers == 0) | ||||
cv_broadcast(&rll->rll_cv); | cv_broadcast(&rll->rll_cv); | ||||
mutex_exit(&rll->rll_lock); | mutex_exit(&rll->rll_lock); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 89 Lines • ▼ Show 20 Lines | ztest_tx_assign(dmu_tx_t *tx, uint64_t txg_how, const char *tag) | ||||
int error; | int error; | ||||
/* | /* | ||||
* Attempt to assign tx to some transaction group. | * Attempt to assign tx to some transaction group. | ||||
*/ | */ | ||||
error = dmu_tx_assign(tx, txg_how); | error = dmu_tx_assign(tx, txg_how); | ||||
if (error) { | if (error) { | ||||
if (error == ERESTART) { | if (error == ERESTART) { | ||||
ASSERT(txg_how == TXG_NOWAIT); | ASSERT3U(txg_how, ==, TXG_NOWAIT); | ||||
dmu_tx_wait(tx); | dmu_tx_wait(tx); | ||||
} else { | } else { | ||||
ASSERT3U(error, ==, ENOSPC); | ASSERT3U(error, ==, ENOSPC); | ||||
ztest_record_enospc(tag); | ztest_record_enospc(tag); | ||||
} | } | ||||
dmu_tx_abort(tx); | dmu_tx_abort(tx); | ||||
return (0); | return (0); | ||||
} | } | ||||
txg = dmu_tx_get_txg(tx); | txg = dmu_tx_get_txg(tx); | ||||
ASSERT(txg != 0); | ASSERT3U(txg, !=, 0); | ||||
return (txg); | return (txg); | ||||
} | } | ||||
static void | static void | ||||
ztest_bt_generate(ztest_block_tag_t *bt, objset_t *os, uint64_t object, | ztest_bt_generate(ztest_block_tag_t *bt, objset_t *os, uint64_t object, | ||||
uint64_t dnodesize, uint64_t offset, uint64_t gen, uint64_t txg, | uint64_t dnodesize, uint64_t offset, uint64_t gen, uint64_t txg, | ||||
uint64_t crtxg) | uint64_t crtxg) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 206 Lines • ▼ Show 20 Lines | ztest_replay_create(void *arg1, void *arg2, boolean_t byteswap) | ||||
dmu_tx_t *tx; | dmu_tx_t *tx; | ||||
uint64_t txg; | uint64_t txg; | ||||
int error = 0; | int error = 0; | ||||
int bonuslen; | int bonuslen; | ||||
if (byteswap) | if (byteswap) | ||||
byteswap_uint64_array(lr, sizeof (*lr)); | byteswap_uint64_array(lr, sizeof (*lr)); | ||||
ASSERT(lr->lr_doid == ZTEST_DIROBJ); | ASSERT3U(lr->lr_doid, ==, ZTEST_DIROBJ); | ||||
ASSERT(name[0] != '\0'); | ASSERT3S(name[0], !=, '\0'); | ||||
tx = dmu_tx_create(os); | tx = dmu_tx_create(os); | ||||
dmu_tx_hold_zap(tx, lr->lr_doid, B_TRUE, name); | dmu_tx_hold_zap(tx, lr->lr_doid, B_TRUE, name); | ||||
if (lr->lrz_type == DMU_OT_ZAP_OTHER) { | if (lr->lrz_type == DMU_OT_ZAP_OTHER) { | ||||
dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, B_TRUE, NULL); | dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, B_TRUE, NULL); | ||||
} else { | } else { | ||||
dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT); | dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT); | ||||
} | } | ||||
txg = ztest_tx_assign(tx, TXG_WAIT, FTAG); | txg = ztest_tx_assign(tx, TXG_WAIT, FTAG); | ||||
if (txg == 0) | if (txg == 0) | ||||
return (ENOSPC); | return (ENOSPC); | ||||
ASSERT(dmu_objset_zil(os)->zl_replay == !!lr->lr_foid); | ASSERT3U(dmu_objset_zil(os)->zl_replay, ==, !!lr->lr_foid); | ||||
bonuslen = DN_BONUS_SIZE(lr->lrz_dnodesize); | bonuslen = DN_BONUS_SIZE(lr->lrz_dnodesize); | ||||
if (lr->lrz_type == DMU_OT_ZAP_OTHER) { | if (lr->lrz_type == DMU_OT_ZAP_OTHER) { | ||||
if (lr->lr_foid == 0) { | if (lr->lr_foid == 0) { | ||||
lr->lr_foid = zap_create_dnsize(os, | lr->lr_foid = zap_create_dnsize(os, | ||||
lr->lrz_type, lr->lrz_bonustype, | lr->lrz_type, lr->lrz_bonustype, | ||||
bonuslen, lr->lrz_dnodesize, tx); | bonuslen, lr->lrz_dnodesize, tx); | ||||
} else { | } else { | ||||
Show All 15 Lines | ztest_replay_create(void *arg1, void *arg2, boolean_t byteswap) | ||||
if (error) { | if (error) { | ||||
ASSERT3U(error, ==, EEXIST); | ASSERT3U(error, ==, EEXIST); | ||||
ASSERT(zd->zd_zilog->zl_replay); | ASSERT(zd->zd_zilog->zl_replay); | ||||
dmu_tx_commit(tx); | dmu_tx_commit(tx); | ||||
return (error); | return (error); | ||||
} | } | ||||
ASSERT(lr->lr_foid != 0); | ASSERT3U(lr->lr_foid, !=, 0); | ||||
if (lr->lrz_type != DMU_OT_ZAP_OTHER) | if (lr->lrz_type != DMU_OT_ZAP_OTHER) | ||||
VERIFY3U(0, ==, dmu_object_set_blocksize(os, lr->lr_foid, | VERIFY0(dmu_object_set_blocksize(os, lr->lr_foid, | ||||
lr->lrz_blocksize, lr->lrz_ibshift, tx)); | lr->lrz_blocksize, lr->lrz_ibshift, tx)); | ||||
VERIFY3U(0, ==, dmu_bonus_hold(os, lr->lr_foid, FTAG, &db)); | VERIFY0(dmu_bonus_hold(os, lr->lr_foid, FTAG, &db)); | ||||
bbt = ztest_bt_bonus(db); | bbt = ztest_bt_bonus(db); | ||||
dmu_buf_will_dirty(db, tx); | dmu_buf_will_dirty(db, tx); | ||||
ztest_bt_generate(bbt, os, lr->lr_foid, lr->lrz_dnodesize, -1ULL, | ztest_bt_generate(bbt, os, lr->lr_foid, lr->lrz_dnodesize, -1ULL, | ||||
lr->lr_gen, txg, txg); | lr->lr_gen, txg, txg); | ||||
ztest_fill_unused_bonus(db, bbt, lr->lr_foid, os, lr->lr_gen); | ztest_fill_unused_bonus(db, bbt, lr->lr_foid, os, lr->lr_gen); | ||||
dmu_buf_rele(db, FTAG); | dmu_buf_rele(db, FTAG); | ||||
VERIFY3U(0, ==, zap_add(os, lr->lr_doid, name, sizeof (uint64_t), 1, | VERIFY0(zap_add(os, lr->lr_doid, name, sizeof (uint64_t), 1, | ||||
&lr->lr_foid, tx)); | &lr->lr_foid, tx)); | ||||
(void) ztest_log_create(zd, tx, lr); | (void) ztest_log_create(zd, tx, lr); | ||||
dmu_tx_commit(tx); | dmu_tx_commit(tx); | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
ztest_replay_remove(void *arg1, void *arg2, boolean_t byteswap) | ztest_replay_remove(void *arg1, void *arg2, boolean_t byteswap) | ||||
{ | { | ||||
ztest_ds_t *zd = arg1; | ztest_ds_t *zd = arg1; | ||||
lr_remove_t *lr = arg2; | lr_remove_t *lr = arg2; | ||||
char *name = (void *)(lr + 1); /* name follows lr */ | char *name = (void *)(lr + 1); /* name follows lr */ | ||||
objset_t *os = zd->zd_os; | objset_t *os = zd->zd_os; | ||||
dmu_object_info_t doi; | dmu_object_info_t doi; | ||||
dmu_tx_t *tx; | dmu_tx_t *tx; | ||||
uint64_t object, txg; | uint64_t object, txg; | ||||
if (byteswap) | if (byteswap) | ||||
byteswap_uint64_array(lr, sizeof (*lr)); | byteswap_uint64_array(lr, sizeof (*lr)); | ||||
ASSERT(lr->lr_doid == ZTEST_DIROBJ); | ASSERT3U(lr->lr_doid, ==, ZTEST_DIROBJ); | ||||
ASSERT(name[0] != '\0'); | ASSERT3S(name[0], !=, '\0'); | ||||
VERIFY3U(0, ==, | VERIFY0( | ||||
zap_lookup(os, lr->lr_doid, name, sizeof (object), 1, &object)); | zap_lookup(os, lr->lr_doid, name, sizeof (object), 1, &object)); | ||||
ASSERT(object != 0); | ASSERT3U(object, !=, 0); | ||||
ztest_object_lock(zd, object, RL_WRITER); | ztest_object_lock(zd, object, RL_WRITER); | ||||
VERIFY3U(0, ==, dmu_object_info(os, object, &doi)); | VERIFY0(dmu_object_info(os, object, &doi)); | ||||
tx = dmu_tx_create(os); | tx = dmu_tx_create(os); | ||||
dmu_tx_hold_zap(tx, lr->lr_doid, B_FALSE, name); | dmu_tx_hold_zap(tx, lr->lr_doid, B_FALSE, name); | ||||
dmu_tx_hold_free(tx, object, 0, DMU_OBJECT_END); | dmu_tx_hold_free(tx, object, 0, DMU_OBJECT_END); | ||||
txg = ztest_tx_assign(tx, TXG_WAIT, FTAG); | txg = ztest_tx_assign(tx, TXG_WAIT, FTAG); | ||||
if (txg == 0) { | if (txg == 0) { | ||||
ztest_object_unlock(zd, object); | ztest_object_unlock(zd, object); | ||||
return (ENOSPC); | return (ENOSPC); | ||||
} | } | ||||
if (doi.doi_type == DMU_OT_ZAP_OTHER) { | if (doi.doi_type == DMU_OT_ZAP_OTHER) { | ||||
VERIFY3U(0, ==, zap_destroy(os, object, tx)); | VERIFY0(zap_destroy(os, object, tx)); | ||||
} else { | } else { | ||||
VERIFY3U(0, ==, dmu_object_free(os, object, tx)); | VERIFY0(dmu_object_free(os, object, tx)); | ||||
} | } | ||||
VERIFY3U(0, ==, zap_remove(os, lr->lr_doid, name, tx)); | VERIFY0(zap_remove(os, lr->lr_doid, name, tx)); | ||||
(void) ztest_log_remove(zd, tx, lr, object); | (void) ztest_log_remove(zd, tx, lr, object); | ||||
dmu_tx_commit(tx); | dmu_tx_commit(tx); | ||||
ztest_object_unlock(zd, object); | ztest_object_unlock(zd, object); | ||||
return (0); | return (0); | ||||
Show All 35 Lines | if (bt->bt_magic == BSWAP_64(BT_MAGIC)) | ||||
byteswap_uint64_array(bt, sizeof (*bt)); | byteswap_uint64_array(bt, sizeof (*bt)); | ||||
if (bt->bt_magic != BT_MAGIC) | if (bt->bt_magic != BT_MAGIC) | ||||
bt = NULL; | bt = NULL; | ||||
ztest_object_lock(zd, lr->lr_foid, RL_READER); | ztest_object_lock(zd, lr->lr_foid, RL_READER); | ||||
rl = ztest_range_lock(zd, lr->lr_foid, offset, length, RL_WRITER); | rl = ztest_range_lock(zd, lr->lr_foid, offset, length, RL_WRITER); | ||||
VERIFY3U(0, ==, dmu_bonus_hold(os, lr->lr_foid, FTAG, &db)); | VERIFY0(dmu_bonus_hold(os, lr->lr_foid, FTAG, &db)); | ||||
dmu_object_info_from_db(db, &doi); | dmu_object_info_from_db(db, &doi); | ||||
bbt = ztest_bt_bonus(db); | bbt = ztest_bt_bonus(db); | ||||
ASSERT3U(bbt->bt_magic, ==, BT_MAGIC); | ASSERT3U(bbt->bt_magic, ==, BT_MAGIC); | ||||
gen = bbt->bt_gen; | gen = bbt->bt_gen; | ||||
crtxg = bbt->bt_crtxg; | crtxg = bbt->bt_crtxg; | ||||
lrtxg = lr->lr_common.lrc_txg; | lrtxg = lr->lr_common.lrc_txg; | ||||
Show All 17 Lines | ztest_replay_write(void *arg1, void *arg2, boolean_t byteswap) | ||||
} | } | ||||
if (bt != NULL) { | if (bt != NULL) { | ||||
/* | /* | ||||
* Usually, verify the old data before writing new data -- | * Usually, verify the old data before writing new data -- | ||||
* but not always, because we also want to verify correct | * but not always, because we also want to verify correct | ||||
* behavior when the data was not recently read into cache. | * behavior when the data was not recently read into cache. | ||||
*/ | */ | ||||
ASSERT(offset % doi.doi_data_block_size == 0); | ASSERT0(offset % doi.doi_data_block_size); | ||||
if (ztest_random(4) != 0) { | if (ztest_random(4) != 0) { | ||||
int prefetch = ztest_random(2) ? | int prefetch = ztest_random(2) ? | ||||
DMU_READ_PREFETCH : DMU_READ_NO_PREFETCH; | DMU_READ_PREFETCH : DMU_READ_NO_PREFETCH; | ||||
ztest_block_tag_t rbt; | ztest_block_tag_t rbt; | ||||
VERIFY(dmu_read(os, lr->lr_foid, offset, | VERIFY(dmu_read(os, lr->lr_foid, offset, | ||||
sizeof (rbt), &rbt, prefetch) == 0); | sizeof (rbt), &rbt, prefetch) == 0); | ||||
if (rbt.bt_magic == BT_MAGIC) { | if (rbt.bt_magic == BT_MAGIC) { | ||||
▲ Show 20 Lines • Show All 64 Lines • ▼ Show 20 Lines | ztest_replay_truncate(void *arg1, void *arg2, boolean_t byteswap) | ||||
txg = ztest_tx_assign(tx, TXG_WAIT, FTAG); | txg = ztest_tx_assign(tx, TXG_WAIT, FTAG); | ||||
if (txg == 0) { | if (txg == 0) { | ||||
ztest_range_unlock(rl); | ztest_range_unlock(rl); | ||||
ztest_object_unlock(zd, lr->lr_foid); | ztest_object_unlock(zd, lr->lr_foid); | ||||
return (ENOSPC); | return (ENOSPC); | ||||
} | } | ||||
VERIFY(dmu_free_range(os, lr->lr_foid, lr->lr_offset, | VERIFY0(dmu_free_range(os, lr->lr_foid, lr->lr_offset, | ||||
lr->lr_length, tx) == 0); | lr->lr_length, tx)); | ||||
(void) ztest_log_truncate(zd, tx, lr); | (void) ztest_log_truncate(zd, tx, lr); | ||||
dmu_tx_commit(tx); | dmu_tx_commit(tx); | ||||
ztest_range_unlock(rl); | ztest_range_unlock(rl); | ||||
ztest_object_unlock(zd, lr->lr_foid); | ztest_object_unlock(zd, lr->lr_foid); | ||||
Show All 11 Lines | ztest_replay_setattr(void *arg1, void *arg2, boolean_t byteswap) | ||||
ztest_block_tag_t *bbt; | ztest_block_tag_t *bbt; | ||||
uint64_t txg, lrtxg, crtxg, dnodesize; | uint64_t txg, lrtxg, crtxg, dnodesize; | ||||
if (byteswap) | if (byteswap) | ||||
byteswap_uint64_array(lr, sizeof (*lr)); | byteswap_uint64_array(lr, sizeof (*lr)); | ||||
ztest_object_lock(zd, lr->lr_foid, RL_WRITER); | ztest_object_lock(zd, lr->lr_foid, RL_WRITER); | ||||
VERIFY3U(0, ==, dmu_bonus_hold(os, lr->lr_foid, FTAG, &db)); | VERIFY0(dmu_bonus_hold(os, lr->lr_foid, FTAG, &db)); | ||||
tx = dmu_tx_create(os); | tx = dmu_tx_create(os); | ||||
dmu_tx_hold_bonus(tx, lr->lr_foid); | dmu_tx_hold_bonus(tx, lr->lr_foid); | ||||
txg = ztest_tx_assign(tx, TXG_WAIT, FTAG); | txg = ztest_tx_assign(tx, TXG_WAIT, FTAG); | ||||
if (txg == 0) { | if (txg == 0) { | ||||
dmu_buf_rele(db, FTAG); | dmu_buf_rele(db, FTAG); | ||||
ztest_object_unlock(zd, lr->lr_foid); | ztest_object_unlock(zd, lr->lr_foid); | ||||
return (ENOSPC); | return (ENOSPC); | ||||
} | } | ||||
bbt = ztest_bt_bonus(db); | bbt = ztest_bt_bonus(db); | ||||
ASSERT3U(bbt->bt_magic, ==, BT_MAGIC); | ASSERT3U(bbt->bt_magic, ==, BT_MAGIC); | ||||
crtxg = bbt->bt_crtxg; | crtxg = bbt->bt_crtxg; | ||||
lrtxg = lr->lr_common.lrc_txg; | lrtxg = lr->lr_common.lrc_txg; | ||||
dnodesize = bbt->bt_dnodesize; | dnodesize = bbt->bt_dnodesize; | ||||
if (zd->zd_zilog->zl_replay) { | if (zd->zd_zilog->zl_replay) { | ||||
ASSERT(lr->lr_size != 0); | ASSERT3U(lr->lr_size, !=, 0); | ||||
ASSERT(lr->lr_mode != 0); | ASSERT3U(lr->lr_mode, !=, 0); | ||||
ASSERT(lrtxg != 0); | ASSERT3U(lrtxg, !=, 0); | ||||
} else { | } else { | ||||
/* | /* | ||||
* Randomly change the size and increment the generation. | * Randomly change the size and increment the generation. | ||||
*/ | */ | ||||
lr->lr_size = (ztest_random(db->db_size / sizeof (*bbt)) + 1) * | lr->lr_size = (ztest_random(db->db_size / sizeof (*bbt)) + 1) * | ||||
sizeof (*bbt); | sizeof (*bbt); | ||||
lr->lr_mode = bbt->bt_gen + 1; | lr->lr_mode = bbt->bt_gen + 1; | ||||
ASSERT(lrtxg == 0); | ASSERT0(lrtxg); | ||||
} | } | ||||
/* | /* | ||||
* Verify that the current bonus buffer is not newer than our txg. | * Verify that the current bonus buffer is not newer than our txg. | ||||
*/ | */ | ||||
ztest_bt_verify(bbt, os, lr->lr_foid, dnodesize, -1ULL, lr->lr_mode, | ztest_bt_verify(bbt, os, lr->lr_foid, dnodesize, -1ULL, lr->lr_mode, | ||||
MAX(txg, lrtxg), crtxg); | MAX(txg, lrtxg), crtxg); | ||||
▲ Show 20 Lines • Show All 105 Lines • ▼ Show 20 Lines | ztest_get_data(void *arg, lr_write_t *lr, char *buf, struct lwb *lwb, | ||||
zgd->zgd_private = zd; | zgd->zgd_private = zd; | ||||
if (buf != NULL) { /* immediate write */ | if (buf != NULL) { /* immediate write */ | ||||
zgd->zgd_lr = (struct zfs_locked_range *)ztest_range_lock(zd, | zgd->zgd_lr = (struct zfs_locked_range *)ztest_range_lock(zd, | ||||
object, offset, size, RL_READER); | object, offset, size, RL_READER); | ||||
error = dmu_read(os, object, offset, size, buf, | error = dmu_read(os, object, offset, size, buf, | ||||
DMU_READ_NO_PREFETCH); | DMU_READ_NO_PREFETCH); | ||||
ASSERT(error == 0); | ASSERT0(error); | ||||
} else { | } else { | ||||
size = doi.doi_data_block_size; | size = doi.doi_data_block_size; | ||||
if (ISP2(size)) { | if (ISP2(size)) { | ||||
offset = P2ALIGN(offset, size); | offset = P2ALIGN(offset, size); | ||||
} else { | } else { | ||||
ASSERT(offset < size); | ASSERT3U(offset, <, size); | ||||
offset = 0; | offset = 0; | ||||
} | } | ||||
zgd->zgd_lr = (struct zfs_locked_range *)ztest_range_lock(zd, | zgd->zgd_lr = (struct zfs_locked_range *)ztest_range_lock(zd, | ||||
object, offset, size, RL_READER); | object, offset, size, RL_READER); | ||||
error = dmu_buf_hold(os, object, offset, zgd, &db, | error = dmu_buf_hold(os, object, offset, zgd, &db, | ||||
DMU_READ_NO_PREFETCH); | DMU_READ_NO_PREFETCH); | ||||
if (error == 0) { | if (error == 0) { | ||||
blkptr_t *bp = &lr->lr_blkptr; | blkptr_t *bp = &lr->lr_blkptr; | ||||
zgd->zgd_db = db; | zgd->zgd_db = db; | ||||
zgd->zgd_bp = bp; | zgd->zgd_bp = bp; | ||||
ASSERT(db->db_offset == offset); | ASSERT3U(db->db_offset, ==, offset); | ||||
ASSERT(db->db_size == size); | ASSERT3U(db->db_size, ==, size); | ||||
error = dmu_sync(zio, lr->lr_common.lrc_txg, | error = dmu_sync(zio, lr->lr_common.lrc_txg, | ||||
ztest_get_done, zgd); | ztest_get_done, zgd); | ||||
if (error == 0) | if (error == 0) | ||||
return (0); | return (0); | ||||
} | } | ||||
} | } | ||||
Show All 37 Lines | ztest_lookup(ztest_ds_t *zd, ztest_od_t *od, int count) | ||||
ASSERT(MUTEX_HELD(&zd->zd_dirobj_lock)); | ASSERT(MUTEX_HELD(&zd->zd_dirobj_lock)); | ||||
for (i = 0; i < count; i++, od++) { | for (i = 0; i < count; i++, od++) { | ||||
od->od_object = 0; | od->od_object = 0; | ||||
error = zap_lookup(zd->zd_os, od->od_dir, od->od_name, | error = zap_lookup(zd->zd_os, od->od_dir, od->od_name, | ||||
sizeof (uint64_t), 1, &od->od_object); | sizeof (uint64_t), 1, &od->od_object); | ||||
if (error) { | if (error) { | ||||
ASSERT(error == ENOENT); | ASSERT3S(error, ==, ENOENT); | ||||
ASSERT(od->od_object == 0); | ASSERT0(od->od_object); | ||||
missing++; | missing++; | ||||
} else { | } else { | ||||
dmu_buf_t *db; | dmu_buf_t *db; | ||||
ztest_block_tag_t *bbt; | ztest_block_tag_t *bbt; | ||||
dmu_object_info_t doi; | dmu_object_info_t doi; | ||||
ASSERT(od->od_object != 0); | ASSERT3U(od->od_object, !=, 0); | ||||
ASSERT(missing == 0); /* there should be no gaps */ | ASSERT0(missing); /* there should be no gaps */ | ||||
ztest_object_lock(zd, od->od_object, RL_READER); | ztest_object_lock(zd, od->od_object, RL_READER); | ||||
VERIFY3U(0, ==, dmu_bonus_hold(zd->zd_os, | VERIFY0(dmu_bonus_hold(zd->zd_os, od->od_object, | ||||
od->od_object, FTAG, &db)); | FTAG, &db)); | ||||
dmu_object_info_from_db(db, &doi); | dmu_object_info_from_db(db, &doi); | ||||
bbt = ztest_bt_bonus(db); | bbt = ztest_bt_bonus(db); | ||||
ASSERT3U(bbt->bt_magic, ==, BT_MAGIC); | ASSERT3U(bbt->bt_magic, ==, BT_MAGIC); | ||||
od->od_type = doi.doi_type; | od->od_type = doi.doi_type; | ||||
od->od_blocksize = doi.doi_data_block_size; | od->od_blocksize = doi.doi_data_block_size; | ||||
od->od_gen = bbt->bt_gen; | od->od_gen = bbt->bt_gen; | ||||
dmu_buf_rele(db, FTAG); | dmu_buf_rele(db, FTAG); | ||||
ztest_object_unlock(zd, od->od_object); | ztest_object_unlock(zd, od->od_object); | ||||
Show All 26 Lines | for (i = 0; i < count; i++, od++) { | ||||
lr->lrz_blocksize = od->od_crblocksize; | lr->lrz_blocksize = od->od_crblocksize; | ||||
lr->lrz_ibshift = ztest_random_ibshift(); | lr->lrz_ibshift = ztest_random_ibshift(); | ||||
lr->lrz_bonustype = DMU_OT_UINT64_OTHER; | lr->lrz_bonustype = DMU_OT_UINT64_OTHER; | ||||
lr->lrz_dnodesize = od->od_crdnodesize; | lr->lrz_dnodesize = od->od_crdnodesize; | ||||
lr->lr_gen = od->od_crgen; | lr->lr_gen = od->od_crgen; | ||||
lr->lr_crtime[0] = time(NULL); | lr->lr_crtime[0] = time(NULL); | ||||
if (ztest_replay_create(zd, lr, B_FALSE) != 0) { | if (ztest_replay_create(zd, lr, B_FALSE) != 0) { | ||||
ASSERT(missing == 0); | ASSERT0(missing); | ||||
od->od_object = 0; | od->od_object = 0; | ||||
missing++; | missing++; | ||||
} else { | } else { | ||||
od->od_object = lr->lr_foid; | od->od_object = lr->lr_foid; | ||||
od->od_type = od->od_crtype; | od->od_type = od->od_crtype; | ||||
od->od_blocksize = od->od_crblocksize; | od->od_blocksize = od->od_crblocksize; | ||||
od->od_gen = od->od_crgen; | od->od_gen = od->od_crgen; | ||||
ASSERT(od->od_object != 0); | ASSERT3U(od->od_object, !=, 0); | ||||
} | } | ||||
ztest_lr_free(lr, sizeof (*lr), od->od_name); | ztest_lr_free(lr, sizeof (*lr), od->od_name); | ||||
} | } | ||||
return (missing); | return (missing); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 134 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
int err; | int err; | ||||
ztest_block_tag_t wbt; | ztest_block_tag_t wbt; | ||||
dmu_object_info_t doi; | dmu_object_info_t doi; | ||||
enum ztest_io_type io_type; | enum ztest_io_type io_type; | ||||
uint64_t blocksize; | uint64_t blocksize; | ||||
void *data; | void *data; | ||||
VERIFY(dmu_object_info(zd->zd_os, object, &doi) == 0); | VERIFY0(dmu_object_info(zd->zd_os, object, &doi)); | ||||
blocksize = doi.doi_data_block_size; | blocksize = doi.doi_data_block_size; | ||||
data = umem_alloc(blocksize, UMEM_NOFAIL); | data = umem_alloc(blocksize, UMEM_NOFAIL); | ||||
/* | /* | ||||
* Pick an i/o type at random, biased toward writing block tags. | * Pick an i/o type at random, biased toward writing block tags. | ||||
*/ | */ | ||||
io_type = ztest_random(ZTEST_IO_TYPES); | io_type = ztest_random(ZTEST_IO_TYPES); | ||||
if (ztest_random(2) == 0) | if (ztest_random(2) == 0) | ||||
▲ Show 20 Lines • Show All 121 Lines • ▼ Show 20 Lines | ztest_zil_commit(ztest_ds_t *zd, uint64_t id) | ||||
zil_commit(zilog, ztest_random(ZTEST_OBJECTS)); | zil_commit(zilog, ztest_random(ZTEST_OBJECTS)); | ||||
/* | /* | ||||
* Remember the committed values in zd, which is in parent/child | * Remember the committed values in zd, which is in parent/child | ||||
* shared memory. If we die, the next iteration of ztest_run() | * shared memory. If we die, the next iteration of ztest_run() | ||||
* will verify that the log really does contain this record. | * will verify that the log really does contain this record. | ||||
*/ | */ | ||||
mutex_enter(&zilog->zl_lock); | mutex_enter(&zilog->zl_lock); | ||||
ASSERT(zd->zd_shared != NULL); | ASSERT3P(zd->zd_shared, !=, NULL); | ||||
ASSERT3U(zd->zd_shared->zd_seq, <=, zilog->zl_commit_lr_seq); | ASSERT3U(zd->zd_shared->zd_seq, <=, zilog->zl_commit_lr_seq); | ||||
zd->zd_shared->zd_seq = zilog->zl_commit_lr_seq; | zd->zd_shared->zd_seq = zilog->zl_commit_lr_seq; | ||||
mutex_exit(&zilog->zl_lock); | mutex_exit(&zilog->zl_lock); | ||||
(void) pthread_rwlock_unlock(&zd->zd_zilog_lock); | (void) pthread_rwlock_unlock(&zd->zd_zilog_lock); | ||||
} | } | ||||
/* | /* | ||||
Show All 21 Lines | ztest_zil_remount(ztest_ds_t *zd, uint64_t id) | ||||
*/ | */ | ||||
mutex_enter(&zd->zd_dirobj_lock); | mutex_enter(&zd->zd_dirobj_lock); | ||||
(void) pthread_rwlock_wrlock(&zd->zd_zilog_lock); | (void) pthread_rwlock_wrlock(&zd->zd_zilog_lock); | ||||
/* zfsvfs_teardown() */ | /* zfsvfs_teardown() */ | ||||
zil_close(zd->zd_zilog); | zil_close(zd->zd_zilog); | ||||
/* zfsvfs_setup() */ | /* zfsvfs_setup() */ | ||||
VERIFY(zil_open(os, ztest_get_data) == zd->zd_zilog); | VERIFY3P(zil_open(os, ztest_get_data), ==, zd->zd_zilog); | ||||
zil_replay(os, zd, ztest_replay_vector); | zil_replay(os, zd, ztest_replay_vector); | ||||
(void) pthread_rwlock_unlock(&zd->zd_zilog_lock); | (void) pthread_rwlock_unlock(&zd->zd_zilog_lock); | ||||
mutex_exit(&zd->zd_dirobj_lock); | mutex_exit(&zd->zd_dirobj_lock); | ||||
mutex_exit(&ztest_vdev_lock); | mutex_exit(&ztest_vdev_lock); | ||||
} | } | ||||
/* | /* | ||||
Show All 12 Lines | if (zo->zo_mmp_test) | ||||
return; | return; | ||||
/* | /* | ||||
* Attempt to create using a bad file. | * Attempt to create using a bad file. | ||||
*/ | */ | ||||
nvroot = make_vdev_root("/dev/bogus", NULL, NULL, 0, 0, NULL, 0, 0, 1); | nvroot = make_vdev_root("/dev/bogus", NULL, NULL, 0, 0, NULL, 0, 0, 1); | ||||
VERIFY3U(ENOENT, ==, | VERIFY3U(ENOENT, ==, | ||||
spa_create("ztest_bad_file", nvroot, NULL, NULL, NULL)); | spa_create("ztest_bad_file", nvroot, NULL, NULL, NULL)); | ||||
nvlist_free(nvroot); | fnvlist_free(nvroot); | ||||
/* | /* | ||||
* Attempt to create using a bad mirror. | * Attempt to create using a bad mirror. | ||||
*/ | */ | ||||
nvroot = make_vdev_root("/dev/bogus", NULL, NULL, 0, 0, NULL, 0, 2, 1); | nvroot = make_vdev_root("/dev/bogus", NULL, NULL, 0, 0, NULL, 0, 2, 1); | ||||
VERIFY3U(ENOENT, ==, | VERIFY3U(ENOENT, ==, | ||||
spa_create("ztest_bad_mirror", nvroot, NULL, NULL, NULL)); | spa_create("ztest_bad_mirror", nvroot, NULL, NULL, NULL)); | ||||
nvlist_free(nvroot); | fnvlist_free(nvroot); | ||||
/* | /* | ||||
* Attempt to create an existing pool. It shouldn't matter | * Attempt to create an existing pool. It shouldn't matter | ||||
* what's in the nvroot; we should fail with EEXIST. | * what's in the nvroot; we should fail with EEXIST. | ||||
*/ | */ | ||||
(void) pthread_rwlock_rdlock(&ztest_name_lock); | (void) pthread_rwlock_rdlock(&ztest_name_lock); | ||||
nvroot = make_vdev_root("/dev/bogus", NULL, NULL, 0, 0, NULL, 0, 0, 1); | nvroot = make_vdev_root("/dev/bogus", NULL, NULL, 0, 0, NULL, 0, 0, 1); | ||||
VERIFY3U(EEXIST, ==, | VERIFY3U(EEXIST, ==, | ||||
spa_create(zo->zo_pool, nvroot, NULL, NULL, NULL)); | spa_create(zo->zo_pool, nvroot, NULL, NULL, NULL)); | ||||
nvlist_free(nvroot); | fnvlist_free(nvroot); | ||||
/* | /* | ||||
* We open a reference to the spa and then we try to export it | * We open a reference to the spa and then we try to export it | ||||
* expecting one of the following errors: | * expecting one of the following errors: | ||||
* | * | ||||
* EBUSY | * EBUSY | ||||
* Because of the reference we just opened. | * Because of the reference we just opened. | ||||
* | * | ||||
* ZFS_ERR_EXPORT_IN_PROGRESS | * ZFS_ERR_EXPORT_IN_PROGRESS | ||||
* For the case that there is another ztest thread doing | * For the case that there is another ztest thread doing | ||||
* an export concurrently. | * an export concurrently. | ||||
*/ | */ | ||||
VERIFY3U(0, ==, spa_open(zo->zo_pool, &spa, FTAG)); | VERIFY0(spa_open(zo->zo_pool, &spa, FTAG)); | ||||
int error = spa_destroy(zo->zo_pool); | int error = spa_destroy(zo->zo_pool); | ||||
if (error != EBUSY && error != ZFS_ERR_EXPORT_IN_PROGRESS) { | if (error != EBUSY && error != ZFS_ERR_EXPORT_IN_PROGRESS) { | ||||
fatal(0, "spa_destroy(%s) returned unexpected value %d", | fatal(0, "spa_destroy(%s) returned unexpected value %d", | ||||
spa->spa_name, error); | spa->spa_name, error); | ||||
} | } | ||||
spa_close(spa, FTAG); | spa_close(spa, FTAG); | ||||
(void) pthread_rwlock_unlock(&ztest_name_lock); | (void) pthread_rwlock_unlock(&ztest_name_lock); | ||||
▲ Show 20 Lines • Show All 100 Lines • ▼ Show 20 Lines | ztest_spa_upgrade(ztest_ds_t *zd, uint64_t id) | ||||
*/ | */ | ||||
do { | do { | ||||
version = ztest_random_spa_version(initial_version); | version = ztest_random_spa_version(initial_version); | ||||
} while (version > SPA_VERSION_BEFORE_FEATURES); | } while (version > SPA_VERSION_BEFORE_FEATURES); | ||||
props = fnvlist_alloc(); | props = fnvlist_alloc(); | ||||
fnvlist_add_uint64(props, | fnvlist_add_uint64(props, | ||||
zpool_prop_to_name(ZPOOL_PROP_VERSION), version); | zpool_prop_to_name(ZPOOL_PROP_VERSION), version); | ||||
VERIFY3S(spa_create(name, nvroot, props, NULL, NULL), ==, 0); | VERIFY0(spa_create(name, nvroot, props, NULL, NULL)); | ||||
fnvlist_free(nvroot); | fnvlist_free(nvroot); | ||||
fnvlist_free(props); | fnvlist_free(props); | ||||
VERIFY3S(spa_open(name, &spa, FTAG), ==, 0); | VERIFY0(spa_open(name, &spa, FTAG)); | ||||
VERIFY3U(spa_version(spa), ==, version); | VERIFY3U(spa_version(spa), ==, version); | ||||
newversion = ztest_random_spa_version(version + 1); | newversion = ztest_random_spa_version(version + 1); | ||||
if (ztest_opts.zo_verbose >= 4) { | if (ztest_opts.zo_verbose >= 4) { | ||||
(void) printf("upgrading spa version from %llu to %llu\n", | (void) printf("upgrading spa version from %llu to %llu\n", | ||||
(u_longlong_t)version, (u_longlong_t)newversion); | (u_longlong_t)version, (u_longlong_t)newversion); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 160 Lines • ▼ Show 20 Lines | if (spa_has_slogs(spa) && ztest_random(4) == 0) { | ||||
* Make 1/4 of the devices be log devices | * Make 1/4 of the devices be log devices | ||||
*/ | */ | ||||
nvroot = make_vdev_root(NULL, NULL, NULL, | nvroot = make_vdev_root(NULL, NULL, NULL, | ||||
ztest_opts.zo_vdev_size, 0, (ztest_random(4) == 0) ? | ztest_opts.zo_vdev_size, 0, (ztest_random(4) == 0) ? | ||||
"log" : NULL, ztest_opts.zo_raid_children, zs->zs_mirrors, | "log" : NULL, ztest_opts.zo_raid_children, zs->zs_mirrors, | ||||
1); | 1); | ||||
error = spa_vdev_add(spa, nvroot); | error = spa_vdev_add(spa, nvroot); | ||||
nvlist_free(nvroot); | fnvlist_free(nvroot); | ||||
switch (error) { | switch (error) { | ||||
case 0: | case 0: | ||||
break; | break; | ||||
case ENOSPC: | case ENOSPC: | ||||
ztest_record_enospc("spa_vdev_add"); | ztest_record_enospc("spa_vdev_add"); | ||||
break; | break; | ||||
default: | default: | ||||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | ztest_vdev_class_add(ztest_ds_t *zd, uint64_t id) | ||||
spa_config_enter(spa, SCL_VDEV, FTAG, RW_READER); | spa_config_enter(spa, SCL_VDEV, FTAG, RW_READER); | ||||
ztest_shared->zs_vdev_next_leaf = spa_num_top_vdevs(spa) * leaves; | ztest_shared->zs_vdev_next_leaf = spa_num_top_vdevs(spa) * leaves; | ||||
spa_config_exit(spa, SCL_VDEV, FTAG); | spa_config_exit(spa, SCL_VDEV, FTAG); | ||||
nvroot = make_vdev_root(NULL, NULL, NULL, ztest_opts.zo_vdev_size, 0, | nvroot = make_vdev_root(NULL, NULL, NULL, ztest_opts.zo_vdev_size, 0, | ||||
class, ztest_opts.zo_raid_children, zs->zs_mirrors, 1); | class, ztest_opts.zo_raid_children, zs->zs_mirrors, 1); | ||||
error = spa_vdev_add(spa, nvroot); | error = spa_vdev_add(spa, nvroot); | ||||
nvlist_free(nvroot); | fnvlist_free(nvroot); | ||||
if (error == ENOSPC) | if (error == ENOSPC) | ||||
ztest_record_enospc("spa_vdev_add"); | ztest_record_enospc("spa_vdev_add"); | ||||
else if (error != 0) | else if (error != 0) | ||||
fatal(0, "spa_vdev_add() = %d", error); | fatal(0, "spa_vdev_add() = %d", error); | ||||
/* | /* | ||||
* 50% of the time allow small blocks in the special class | * 50% of the time allow small blocks in the special class | ||||
▲ Show 20 Lines • Show All 96 Lines • ▼ Show 20 Lines | if (guid == 0) { | ||||
error = spa_vdev_add(spa, nvroot); | error = spa_vdev_add(spa, nvroot); | ||||
switch (error) { | switch (error) { | ||||
case 0: | case 0: | ||||
break; | break; | ||||
default: | default: | ||||
fatal(0, "spa_vdev_add(%p) = %d", nvroot, error); | fatal(0, "spa_vdev_add(%p) = %d", nvroot, error); | ||||
} | } | ||||
nvlist_free(nvroot); | fnvlist_free(nvroot); | ||||
} else { | } else { | ||||
/* | /* | ||||
* Remove an existing device. Sometimes, dirty its | * Remove an existing device. Sometimes, dirty its | ||||
* vdev state first to make sure we handle removal | * vdev state first to make sure we handle removal | ||||
* of devices that have pending state changes. | * of devices that have pending state changes. | ||||
*/ | */ | ||||
if (ztest_random(2) == 0) | if (ztest_random(2) == 0) | ||||
(void) vdev_online(spa, guid, 0, NULL); | (void) vdev_online(spa, guid, 0, NULL); | ||||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | ztest_split_pool(ztest_ds_t *zd, uint64_t id) | ||||
/* clean up the old pool, if any */ | /* clean up the old pool, if any */ | ||||
(void) spa_destroy("splitp"); | (void) spa_destroy("splitp"); | ||||
spa_config_enter(spa, SCL_VDEV, FTAG, RW_READER); | spa_config_enter(spa, SCL_VDEV, FTAG, RW_READER); | ||||
/* generate a config from the existing config */ | /* generate a config from the existing config */ | ||||
mutex_enter(&spa->spa_props_lock); | mutex_enter(&spa->spa_props_lock); | ||||
VERIFY(nvlist_lookup_nvlist(spa->spa_config, ZPOOL_CONFIG_VDEV_TREE, | tree = fnvlist_lookup_nvlist(spa->spa_config, ZPOOL_CONFIG_VDEV_TREE); | ||||
&tree) == 0); | |||||
mutex_exit(&spa->spa_props_lock); | mutex_exit(&spa->spa_props_lock); | ||||
VERIFY(nvlist_lookup_nvlist_array(tree, ZPOOL_CONFIG_CHILDREN, &child, | VERIFY0(nvlist_lookup_nvlist_array(tree, ZPOOL_CONFIG_CHILDREN, | ||||
&children) == 0); | &child, &children)); | ||||
schild = malloc(rvd->vdev_children * sizeof (nvlist_t *)); | schild = malloc(rvd->vdev_children * sizeof (nvlist_t *)); | ||||
for (c = 0; c < children; c++) { | for (c = 0; c < children; c++) { | ||||
vdev_t *tvd = rvd->vdev_child[c]; | vdev_t *tvd = rvd->vdev_child[c]; | ||||
nvlist_t **mchild; | nvlist_t **mchild; | ||||
uint_t mchildren; | uint_t mchildren; | ||||
if (tvd->vdev_islog || tvd->vdev_ops == &vdev_hole_ops) { | if (tvd->vdev_islog || tvd->vdev_ops == &vdev_hole_ops) { | ||||
VERIFY(nvlist_alloc(&schild[schildren], NV_UNIQUE_NAME, | schild[schildren] = fnvlist_alloc(); | ||||
0) == 0); | fnvlist_add_string(schild[schildren], | ||||
VERIFY(nvlist_add_string(schild[schildren], | ZPOOL_CONFIG_TYPE, VDEV_TYPE_HOLE); | ||||
ZPOOL_CONFIG_TYPE, VDEV_TYPE_HOLE) == 0); | fnvlist_add_uint64(schild[schildren], | ||||
VERIFY(nvlist_add_uint64(schild[schildren], | ZPOOL_CONFIG_IS_HOLE, 1); | ||||
ZPOOL_CONFIG_IS_HOLE, 1) == 0); | |||||
if (lastlogid == 0) | if (lastlogid == 0) | ||||
lastlogid = schildren; | lastlogid = schildren; | ||||
++schildren; | ++schildren; | ||||
continue; | continue; | ||||
} | } | ||||
lastlogid = 0; | lastlogid = 0; | ||||
VERIFY(nvlist_lookup_nvlist_array(child[c], | VERIFY0(nvlist_lookup_nvlist_array(child[c], | ||||
ZPOOL_CONFIG_CHILDREN, &mchild, &mchildren) == 0); | ZPOOL_CONFIG_CHILDREN, &mchild, &mchildren)); | ||||
VERIFY(nvlist_dup(mchild[0], &schild[schildren++], 0) == 0); | schild[schildren++] = fnvlist_dup(mchild[0]); | ||||
} | } | ||||
/* OK, create a config that can be used to split */ | /* OK, create a config that can be used to split */ | ||||
VERIFY(nvlist_alloc(&split, NV_UNIQUE_NAME, 0) == 0); | split = fnvlist_alloc(); | ||||
VERIFY(nvlist_add_string(split, ZPOOL_CONFIG_TYPE, | fnvlist_add_string(split, ZPOOL_CONFIG_TYPE, VDEV_TYPE_ROOT); | ||||
VDEV_TYPE_ROOT) == 0); | fnvlist_add_nvlist_array(split, ZPOOL_CONFIG_CHILDREN, schild, | ||||
VERIFY(nvlist_add_nvlist_array(split, ZPOOL_CONFIG_CHILDREN, schild, | lastlogid != 0 ? lastlogid : schildren); | ||||
lastlogid != 0 ? lastlogid : schildren) == 0); | |||||
VERIFY(nvlist_alloc(&config, NV_UNIQUE_NAME, 0) == 0); | config = fnvlist_alloc(); | ||||
VERIFY(nvlist_add_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, split) == 0); | fnvlist_add_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, split); | ||||
for (c = 0; c < schildren; c++) | for (c = 0; c < schildren; c++) | ||||
nvlist_free(schild[c]); | fnvlist_free(schild[c]); | ||||
free(schild); | free(schild); | ||||
nvlist_free(split); | fnvlist_free(split); | ||||
spa_config_exit(spa, SCL_VDEV, FTAG); | spa_config_exit(spa, SCL_VDEV, FTAG); | ||||
(void) pthread_rwlock_wrlock(&ztest_name_lock); | (void) pthread_rwlock_wrlock(&ztest_name_lock); | ||||
error = spa_vdev_split_mirror(spa, "splitp", config, NULL, B_FALSE); | error = spa_vdev_split_mirror(spa, "splitp", config, NULL, B_FALSE); | ||||
(void) pthread_rwlock_unlock(&ztest_name_lock); | (void) pthread_rwlock_unlock(&ztest_name_lock); | ||||
nvlist_free(config); | fnvlist_free(config); | ||||
if (error == 0) { | if (error == 0) { | ||||
(void) printf("successful split - results:\n"); | (void) printf("successful split - results:\n"); | ||||
mutex_enter(&spa_namespace_lock); | mutex_enter(&spa_namespace_lock); | ||||
show_pool_stats(spa); | show_pool_stats(spa); | ||||
show_pool_stats(spa_lookup("splitp")); | show_pool_stats(spa_lookup("splitp")); | ||||
mutex_exit(&spa_namespace_lock); | mutex_exit(&spa_namespace_lock); | ||||
++zs->zs_splits; | ++zs->zs_splits; | ||||
▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | ztest_vdev_attach_detach(ztest_ds_t *zd, uint64_t id) | ||||
/* | /* | ||||
* Locate this vdev. | * Locate this vdev. | ||||
*/ | */ | ||||
oldvd = rvd->vdev_child[top]; | oldvd = rvd->vdev_child[top]; | ||||
/* pick a child from the mirror */ | /* pick a child from the mirror */ | ||||
if (zs->zs_mirrors >= 1) { | if (zs->zs_mirrors >= 1) { | ||||
ASSERT(oldvd->vdev_ops == &vdev_mirror_ops); | ASSERT3P(oldvd->vdev_ops, ==, &vdev_mirror_ops); | ||||
ASSERT(oldvd->vdev_children >= zs->zs_mirrors); | ASSERT3U(oldvd->vdev_children, >=, zs->zs_mirrors); | ||||
oldvd = oldvd->vdev_child[leaf / ztest_opts.zo_raid_children]; | oldvd = oldvd->vdev_child[leaf / ztest_opts.zo_raid_children]; | ||||
} | } | ||||
/* pick a child out of the raidz group */ | /* pick a child out of the raidz group */ | ||||
if (ztest_opts.zo_raid_children > 1) { | if (ztest_opts.zo_raid_children > 1) { | ||||
if (strcmp(oldvd->vdev_ops->vdev_op_type, "raidz") == 0) | if (strcmp(oldvd->vdev_ops->vdev_op_type, "raidz") == 0) | ||||
ASSERT(oldvd->vdev_ops == &vdev_raidz_ops); | ASSERT3P(oldvd->vdev_ops, ==, &vdev_raidz_ops); | ||||
else | else | ||||
ASSERT(oldvd->vdev_ops == &vdev_draid_ops); | ASSERT3P(oldvd->vdev_ops, ==, &vdev_draid_ops); | ||||
ASSERT(oldvd->vdev_children == ztest_opts.zo_raid_children); | ASSERT3U(oldvd->vdev_children, ==, ztest_opts.zo_raid_children); | ||||
oldvd = oldvd->vdev_child[leaf % ztest_opts.zo_raid_children]; | oldvd = oldvd->vdev_child[leaf % ztest_opts.zo_raid_children]; | ||||
} | } | ||||
/* | /* | ||||
* If we're already doing an attach or replace, oldvd may be a | * If we're already doing an attach or replace, oldvd may be a | ||||
* mirror vdev -- in which case, pick a random child. | * mirror vdev -- in which case, pick a random child. | ||||
*/ | */ | ||||
while (oldvd->vdev_children != 0) { | while (oldvd->vdev_children != 0) { | ||||
oldvd_has_siblings = B_TRUE; | oldvd_has_siblings = B_TRUE; | ||||
ASSERT(oldvd->vdev_children >= 2); | ASSERT3U(oldvd->vdev_children, >=, 2); | ||||
oldvd = oldvd->vdev_child[ztest_random(oldvd->vdev_children)]; | oldvd = oldvd->vdev_child[ztest_random(oldvd->vdev_children)]; | ||||
} | } | ||||
oldguid = oldvd->vdev_guid; | oldguid = oldvd->vdev_guid; | ||||
oldsize = vdev_get_min_asize(oldvd); | oldsize = vdev_get_min_asize(oldvd); | ||||
oldvd_is_log = oldvd->vdev_top->vdev_islog; | oldvd_is_log = oldvd->vdev_top->vdev_islog; | ||||
(void) strcpy(oldpath, oldvd->vdev_path); | (void) strcpy(oldpath, oldvd->vdev_path); | ||||
pvd = oldvd->vdev_parent; | pvd = oldvd->vdev_parent; | ||||
▲ Show 20 Lines • Show All 101 Lines • ▼ Show 20 Lines | ztest_vdev_attach_detach(ztest_ds_t *zd, uint64_t id) | ||||
boolean_t rebuilding = B_FALSE; | boolean_t rebuilding = B_FALSE; | ||||
if (pvd->vdev_ops == &vdev_mirror_ops || | if (pvd->vdev_ops == &vdev_mirror_ops || | ||||
pvd->vdev_ops == &vdev_root_ops) { | pvd->vdev_ops == &vdev_root_ops) { | ||||
rebuilding = !!ztest_random(2); | rebuilding = !!ztest_random(2); | ||||
} | } | ||||
error = spa_vdev_attach(spa, oldguid, root, replacing, rebuilding); | error = spa_vdev_attach(spa, oldguid, root, replacing, rebuilding); | ||||
nvlist_free(root); | fnvlist_free(root); | ||||
/* | /* | ||||
* If our parent was the replacing vdev, but the replace completed, | * If our parent was the replacing vdev, but the replace completed, | ||||
* then instead of failing with ENOTSUP we may either succeed, | * then instead of failing with ENOTSUP we may either succeed, | ||||
* fail with ENODEV, or fail with EOVERFLOW. | * fail with ENODEV, or fail with EOVERFLOW. | ||||
*/ | */ | ||||
if (expected_error == ENOTSUP && | if (expected_error == ENOTSUP && | ||||
(error == 0 || error == ENODEV || error == EOVERFLOW)) | (error == 0 || error == ENODEV || error == EOVERFLOW)) | ||||
▲ Show 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | |||||
static vdev_t * | static vdev_t * | ||||
grow_vdev(vdev_t *vd, void *arg) | grow_vdev(vdev_t *vd, void *arg) | ||||
{ | { | ||||
spa_t *spa __maybe_unused = vd->vdev_spa; | spa_t *spa __maybe_unused = vd->vdev_spa; | ||||
size_t *newsize = arg; | size_t *newsize = arg; | ||||
size_t fsize; | size_t fsize; | ||||
int fd; | int fd; | ||||
ASSERT(spa_config_held(spa, SCL_STATE, RW_READER) == SCL_STATE); | ASSERT3S(spa_config_held(spa, SCL_STATE, RW_READER), ==, SCL_STATE); | ||||
ASSERT(vd->vdev_ops->vdev_op_leaf); | ASSERT(vd->vdev_ops->vdev_op_leaf); | ||||
if ((fd = open(vd->vdev_path, O_RDWR)) == -1) | if ((fd = open(vd->vdev_path, O_RDWR)) == -1) | ||||
return (vd); | return (vd); | ||||
fsize = lseek(fd, 0, SEEK_END); | fsize = lseek(fd, 0, SEEK_END); | ||||
VERIFY(ftruncate(fd, *newsize) == 0); | VERIFY0(ftruncate(fd, *newsize)); | ||||
if (ztest_opts.zo_verbose >= 6) { | if (ztest_opts.zo_verbose >= 6) { | ||||
(void) printf("%s grew from %lu to %lu bytes\n", | (void) printf("%s grew from %lu to %lu bytes\n", | ||||
vd->vdev_path, (ulong_t)fsize, (ulong_t)*newsize); | vd->vdev_path, (ulong_t)fsize, (ulong_t)*newsize); | ||||
} | } | ||||
(void) close(fd); | (void) close(fd); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
/* | /* | ||||
* Callback function which expands a given vdev by calling vdev_online(). | * Callback function which expands a given vdev by calling vdev_online(). | ||||
*/ | */ | ||||
/* ARGSUSED */ | /* ARGSUSED */ | ||||
static vdev_t * | static vdev_t * | ||||
online_vdev(vdev_t *vd, void *arg) | online_vdev(vdev_t *vd, void *arg) | ||||
{ | { | ||||
spa_t *spa = vd->vdev_spa; | spa_t *spa = vd->vdev_spa; | ||||
vdev_t *tvd = vd->vdev_top; | vdev_t *tvd = vd->vdev_top; | ||||
uint64_t guid = vd->vdev_guid; | uint64_t guid = vd->vdev_guid; | ||||
uint64_t generation = spa->spa_config_generation + 1; | uint64_t generation = spa->spa_config_generation + 1; | ||||
vdev_state_t newstate = VDEV_STATE_UNKNOWN; | vdev_state_t newstate = VDEV_STATE_UNKNOWN; | ||||
int error; | int error; | ||||
ASSERT(spa_config_held(spa, SCL_STATE, RW_READER) == SCL_STATE); | ASSERT3S(spa_config_held(spa, SCL_STATE, RW_READER), ==, SCL_STATE); | ||||
ASSERT(vd->vdev_ops->vdev_op_leaf); | ASSERT(vd->vdev_ops->vdev_op_leaf); | ||||
/* Calling vdev_online will initialize the new metaslabs */ | /* Calling vdev_online will initialize the new metaslabs */ | ||||
spa_config_exit(spa, SCL_STATE, spa); | spa_config_exit(spa, SCL_STATE, spa); | ||||
error = vdev_online(spa, guid, ZFS_ONLINE_EXPAND, &newstate); | error = vdev_online(spa, guid, ZFS_ONLINE_EXPAND, &newstate); | ||||
spa_config_enter(spa, SCL_STATE, spa, RW_READER); | spa_config_enter(spa, SCL_STATE, spa, RW_READER); | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 114 Lines • ▼ Show 20 Lines | ztest_vdev_LUN_growth(ztest_ds_t *zd, uint64_t id) | ||||
*/ | */ | ||||
if (tvd->vdev_state != VDEV_STATE_HEALTHY || | if (tvd->vdev_state != VDEV_STATE_HEALTHY || | ||||
psize == 0 || psize >= 4 * ztest_opts.zo_vdev_size) { | psize == 0 || psize >= 4 * ztest_opts.zo_vdev_size) { | ||||
spa_config_exit(spa, SCL_STATE, spa); | spa_config_exit(spa, SCL_STATE, spa); | ||||
mutex_exit(&ztest_vdev_lock); | mutex_exit(&ztest_vdev_lock); | ||||
mutex_exit(&ztest_checkpoint_lock); | mutex_exit(&ztest_checkpoint_lock); | ||||
return; | return; | ||||
} | } | ||||
ASSERT(psize > 0); | ASSERT3U(psize, >, 0); | ||||
newsize = psize + MAX(psize / 8, SPA_MAXBLOCKSIZE); | newsize = psize + MAX(psize / 8, SPA_MAXBLOCKSIZE); | ||||
ASSERT3U(newsize, >, psize); | ASSERT3U(newsize, >, psize); | ||||
if (ztest_opts.zo_verbose >= 6) { | if (ztest_opts.zo_verbose >= 6) { | ||||
(void) printf("Expanding LUN %s from %lu to %lu\n", | (void) printf("Expanding LUN %s from %lu to %lu\n", | ||||
vd->vdev_path, (ulong_t)psize, (ulong_t)newsize); | vd->vdev_path, (ulong_t)psize, (ulong_t)newsize); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 85 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
/* ARGSUSED */ | /* ARGSUSED */ | ||||
static void | static void | ||||
ztest_objset_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx) | ztest_objset_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx) | ||||
{ | { | ||||
/* | /* | ||||
* Create the objects common to all ztest datasets. | * Create the objects common to all ztest datasets. | ||||
*/ | */ | ||||
VERIFY(zap_create_claim(os, ZTEST_DIROBJ, | VERIFY0(zap_create_claim(os, ZTEST_DIROBJ, | ||||
DMU_OT_ZAP_OTHER, DMU_OT_NONE, 0, tx) == 0); | DMU_OT_ZAP_OTHER, DMU_OT_NONE, 0, tx)); | ||||
} | } | ||||
static int | static int | ||||
ztest_dataset_create(char *dsname) | ztest_dataset_create(char *dsname) | ||||
{ | { | ||||
int err; | int err; | ||||
uint64_t rand; | uint64_t rand; | ||||
dsl_crypto_params_t *dcp = NULL; | dsl_crypto_params_t *dcp = NULL; | ||||
▲ Show 20 Lines • Show All 219 Lines • ▼ Show 20 Lines | ztest_dmu_objset_create_destroy(ztest_ds_t *zd, uint64_t id) | ||||
* Verify that we cannot create an existing dataset. | * Verify that we cannot create an existing dataset. | ||||
*/ | */ | ||||
VERIFY3U(EEXIST, ==, | VERIFY3U(EEXIST, ==, | ||||
dmu_objset_create(name, DMU_OST_OTHER, 0, NULL, NULL, NULL)); | dmu_objset_create(name, DMU_OST_OTHER, 0, NULL, NULL, NULL)); | ||||
/* | /* | ||||
* Verify that we can hold an objset that is also owned. | * Verify that we can hold an objset that is also owned. | ||||
*/ | */ | ||||
VERIFY3U(0, ==, dmu_objset_hold(name, FTAG, &os2)); | VERIFY0(dmu_objset_hold(name, FTAG, &os2)); | ||||
dmu_objset_rele(os2, FTAG); | dmu_objset_rele(os2, FTAG); | ||||
/* | /* | ||||
* Verify that we cannot own an objset that is already owned. | * Verify that we cannot own an objset that is already owned. | ||||
*/ | */ | ||||
VERIFY3U(EBUSY, ==, ztest_dmu_objset_own(name, DMU_OST_OTHER, | VERIFY3U(EBUSY, ==, ztest_dmu_objset_own(name, DMU_OST_OTHER, | ||||
B_FALSE, B_TRUE, FTAG, &os2)); | B_FALSE, B_TRUE, FTAG, &os2)); | ||||
▲ Show 20 Lines • Show All 295 Lines • ▼ Show 20 Lines | ztest_dmu_read_write(ztest_ds_t *zd, uint64_t id) | ||||
if (ztest_object_init(zd, od, size, B_FALSE) != 0) { | if (ztest_object_init(zd, od, size, B_FALSE) != 0) { | ||||
umem_free(od, size); | umem_free(od, size); | ||||
return; | return; | ||||
} | } | ||||
bigobj = od[0].od_object; | bigobj = od[0].od_object; | ||||
packobj = od[1].od_object; | packobj = od[1].od_object; | ||||
chunksize = od[0].od_gen; | chunksize = od[0].od_gen; | ||||
ASSERT(chunksize == od[1].od_gen); | ASSERT3U(chunksize, ==, od[1].od_gen); | ||||
/* | /* | ||||
* Prefetch a random chunk of the big object. | * Prefetch a random chunk of the big object. | ||||
* Our aim here is to get some async reads in flight | * Our aim here is to get some async reads in flight | ||||
* for blocks that we may free below; the DMU should | * for blocks that we may free below; the DMU should | ||||
* handle this race correctly. | * handle this race correctly. | ||||
*/ | */ | ||||
n = ztest_random(regions) * stride + ztest_random(width); | n = ztest_random(regions) * stride + ztest_random(width); | ||||
▲ Show 20 Lines • Show All 78 Lines • ▼ Show 20 Lines | ztest_dmu_read_write(ztest_ds_t *zd, uint64_t id) | ||||
for (i = 0; i < s; i++) { | for (i = 0; i < s; i++) { | ||||
/* LINTED */ | /* LINTED */ | ||||
pack = (bufwad_t *)((char *)packbuf + i * sizeof (bufwad_t)); | pack = (bufwad_t *)((char *)packbuf + i * sizeof (bufwad_t)); | ||||
/* LINTED */ | /* LINTED */ | ||||
bigH = (bufwad_t *)((char *)bigbuf + i * chunksize); | bigH = (bufwad_t *)((char *)bigbuf + i * chunksize); | ||||
/* LINTED */ | /* LINTED */ | ||||
bigT = (bufwad_t *)((char *)bigH + chunksize) - 1; | bigT = (bufwad_t *)((char *)bigH + chunksize) - 1; | ||||
ASSERT((uintptr_t)bigH - (uintptr_t)bigbuf < bigsize); | ASSERT3U((uintptr_t)bigH - (uintptr_t)bigbuf, <, bigsize); | ||||
ASSERT((uintptr_t)bigT - (uintptr_t)bigbuf < bigsize); | ASSERT3U((uintptr_t)bigT - (uintptr_t)bigbuf, <, bigsize); | ||||
if (pack->bw_txg > txg) | if (pack->bw_txg > txg) | ||||
fatal(0, "future leak: got %llx, open txg is %llx", | fatal(0, "future leak: got %llx, open txg is %llx", | ||||
pack->bw_txg, txg); | pack->bw_txg, txg); | ||||
if (pack->bw_data != 0 && pack->bw_index != n + i) | if (pack->bw_data != 0 && pack->bw_index != n + i) | ||||
fatal(0, "wrong index: got %llx, wanted %llx+%llx", | fatal(0, "wrong index: got %llx, wanted %llx+%llx", | ||||
pack->bw_index, n, i); | pack->bw_index, n, i); | ||||
Show All 24 Lines | ztest_dmu_read_write(ztest_ds_t *zd, uint64_t id) | ||||
if (freeit) { | if (freeit) { | ||||
if (ztest_opts.zo_verbose >= 7) { | if (ztest_opts.zo_verbose >= 7) { | ||||
(void) printf("freeing offset %llx size %llx" | (void) printf("freeing offset %llx size %llx" | ||||
" txg %llx\n", | " txg %llx\n", | ||||
(u_longlong_t)bigoff, | (u_longlong_t)bigoff, | ||||
(u_longlong_t)bigsize, | (u_longlong_t)bigsize, | ||||
(u_longlong_t)txg); | (u_longlong_t)txg); | ||||
} | } | ||||
VERIFY(0 == dmu_free_range(os, bigobj, bigoff, bigsize, tx)); | VERIFY0(dmu_free_range(os, bigobj, bigoff, bigsize, tx)); | ||||
} else { | } else { | ||||
if (ztest_opts.zo_verbose >= 7) { | if (ztest_opts.zo_verbose >= 7) { | ||||
(void) printf("writing offset %llx size %llx" | (void) printf("writing offset %llx size %llx" | ||||
" txg %llx\n", | " txg %llx\n", | ||||
(u_longlong_t)bigoff, | (u_longlong_t)bigoff, | ||||
(u_longlong_t)bigsize, | (u_longlong_t)bigsize, | ||||
(u_longlong_t)txg); | (u_longlong_t)txg); | ||||
} | } | ||||
dmu_write(os, bigobj, bigoff, bigsize, bigbuf, tx); | dmu_write(os, bigobj, bigoff, bigsize, bigbuf, tx); | ||||
} | } | ||||
dmu_tx_commit(tx); | dmu_tx_commit(tx); | ||||
/* | /* | ||||
* Sanity check the stuff we just wrote. | * Sanity check the stuff we just wrote. | ||||
*/ | */ | ||||
{ | { | ||||
void *packcheck = umem_alloc(packsize, UMEM_NOFAIL); | void *packcheck = umem_alloc(packsize, UMEM_NOFAIL); | ||||
void *bigcheck = umem_alloc(bigsize, UMEM_NOFAIL); | void *bigcheck = umem_alloc(bigsize, UMEM_NOFAIL); | ||||
VERIFY(0 == dmu_read(os, packobj, packoff, | VERIFY0(dmu_read(os, packobj, packoff, | ||||
packsize, packcheck, DMU_READ_PREFETCH)); | packsize, packcheck, DMU_READ_PREFETCH)); | ||||
VERIFY(0 == dmu_read(os, bigobj, bigoff, | VERIFY0(dmu_read(os, bigobj, bigoff, | ||||
bigsize, bigcheck, DMU_READ_PREFETCH)); | bigsize, bigcheck, DMU_READ_PREFETCH)); | ||||
ASSERT(bcmp(packbuf, packcheck, packsize) == 0); | ASSERT0(bcmp(packbuf, packcheck, packsize)); | ||||
ASSERT(bcmp(bigbuf, bigcheck, bigsize) == 0); | ASSERT0(bcmp(bigbuf, bigcheck, bigsize)); | ||||
umem_free(packcheck, packsize); | umem_free(packcheck, packsize); | ||||
umem_free(bigcheck, bigsize); | umem_free(bigcheck, bigsize); | ||||
} | } | ||||
umem_free(packbuf, packsize); | umem_free(packbuf, packsize); | ||||
umem_free(bigbuf, bigsize); | umem_free(bigbuf, bigsize); | ||||
umem_free(od, size); | umem_free(od, size); | ||||
Show All 17 Lines | compare_and_update_pbbufs(uint64_t s, bufwad_t *packbuf, bufwad_t *bigbuf, | ||||
for (i = 0; i < s; i++) { | for (i = 0; i < s; i++) { | ||||
/* LINTED */ | /* LINTED */ | ||||
pack = (bufwad_t *)((char *)packbuf + i * sizeof (bufwad_t)); | pack = (bufwad_t *)((char *)packbuf + i * sizeof (bufwad_t)); | ||||
/* LINTED */ | /* LINTED */ | ||||
bigH = (bufwad_t *)((char *)bigbuf + i * chunksize); | bigH = (bufwad_t *)((char *)bigbuf + i * chunksize); | ||||
/* LINTED */ | /* LINTED */ | ||||
bigT = (bufwad_t *)((char *)bigH + chunksize) - 1; | bigT = (bufwad_t *)((char *)bigH + chunksize) - 1; | ||||
ASSERT((uintptr_t)bigH - (uintptr_t)bigbuf < bigsize); | ASSERT3U((uintptr_t)bigH - (uintptr_t)bigbuf, <, bigsize); | ||||
ASSERT((uintptr_t)bigT - (uintptr_t)bigbuf < bigsize); | ASSERT3U((uintptr_t)bigT - (uintptr_t)bigbuf, <, bigsize); | ||||
if (pack->bw_txg > txg) | if (pack->bw_txg > txg) | ||||
fatal(0, "future leak: got %llx, open txg is %llx", | fatal(0, "future leak: got %llx, open txg is %llx", | ||||
pack->bw_txg, txg); | pack->bw_txg, txg); | ||||
if (pack->bw_data != 0 && pack->bw_index != n + i) | if (pack->bw_data != 0 && pack->bw_index != n + i) | ||||
fatal(0, "wrong index: got %llx, wanted %llx+%llx", | fatal(0, "wrong index: got %llx, wanted %llx+%llx", | ||||
pack->bw_index, n, i); | pack->bw_index, n, i); | ||||
▲ Show 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | if (ztest_object_init(zd, od, size, B_FALSE) != 0) { | ||||
umem_free(od, size); | umem_free(od, size); | ||||
return; | return; | ||||
} | } | ||||
bigobj = od[0].od_object; | bigobj = od[0].od_object; | ||||
packobj = od[1].od_object; | packobj = od[1].od_object; | ||||
blocksize = od[0].od_blocksize; | blocksize = od[0].od_blocksize; | ||||
chunksize = blocksize; | chunksize = blocksize; | ||||
ASSERT(chunksize == od[1].od_gen); | ASSERT3U(chunksize, ==, od[1].od_gen); | ||||
VERIFY(dmu_object_info(os, bigobj, &doi) == 0); | VERIFY0(dmu_object_info(os, bigobj, &doi)); | ||||
VERIFY(ISP2(doi.doi_data_block_size)); | VERIFY(ISP2(doi.doi_data_block_size)); | ||||
VERIFY(chunksize == doi.doi_data_block_size); | VERIFY3U(chunksize, ==, doi.doi_data_block_size); | ||||
VERIFY(chunksize >= 2 * sizeof (bufwad_t)); | VERIFY3U(chunksize, >=, 2 * sizeof (bufwad_t)); | ||||
/* | /* | ||||
* Pick a random index and compute the offsets into packobj and bigobj. | * Pick a random index and compute the offsets into packobj and bigobj. | ||||
*/ | */ | ||||
n = ztest_random(regions) * stride + ztest_random(width); | n = ztest_random(regions) * stride + ztest_random(width); | ||||
s = 1 + ztest_random(width - 1); | s = 1 + ztest_random(width - 1); | ||||
packoff = n * sizeof (bufwad_t); | packoff = n * sizeof (bufwad_t); | ||||
packsize = s * sizeof (bufwad_t); | packsize = s * sizeof (bufwad_t); | ||||
bigoff = n * chunksize; | bigoff = n * chunksize; | ||||
bigsize = s * chunksize; | bigsize = s * chunksize; | ||||
packbuf = umem_zalloc(packsize, UMEM_NOFAIL); | packbuf = umem_zalloc(packsize, UMEM_NOFAIL); | ||||
bigbuf = umem_zalloc(bigsize, UMEM_NOFAIL); | bigbuf = umem_zalloc(bigsize, UMEM_NOFAIL); | ||||
VERIFY3U(0, ==, dmu_bonus_hold(os, bigobj, FTAG, &bonus_db)); | VERIFY0(dmu_bonus_hold(os, bigobj, FTAG, &bonus_db)); | ||||
bigbuf_arcbufs = umem_zalloc(2 * s * sizeof (arc_buf_t *), UMEM_NOFAIL); | bigbuf_arcbufs = umem_zalloc(2 * s * sizeof (arc_buf_t *), UMEM_NOFAIL); | ||||
/* | /* | ||||
* Iteration 0 test zcopy for DB_UNCACHED dbufs. | * Iteration 0 test zcopy for DB_UNCACHED dbufs. | ||||
* Iteration 1 test zcopy to already referenced dbufs. | * Iteration 1 test zcopy to already referenced dbufs. | ||||
* Iteration 2 test zcopy to dirty dbuf in the same txg. | * Iteration 2 test zcopy to dirty dbuf in the same txg. | ||||
* Iteration 3 test zcopy to dbuf dirty in previous txg. | * Iteration 3 test zcopy to dbuf dirty in previous txg. | ||||
▲ Show 20 Lines • Show All 252 Lines • ▼ Show 20 Lines | ztest_zap(ztest_ds_t *zd, uint64_t id) | ||||
*/ | */ | ||||
tx = dmu_tx_create(os); | tx = dmu_tx_create(os); | ||||
dmu_tx_hold_zap(tx, object, B_TRUE, NULL); | dmu_tx_hold_zap(tx, object, B_TRUE, NULL); | ||||
txg = ztest_tx_assign(tx, TXG_MIGHTWAIT, FTAG); | txg = ztest_tx_assign(tx, TXG_MIGHTWAIT, FTAG); | ||||
if (txg == 0) | if (txg == 0) | ||||
goto out; | goto out; | ||||
for (i = 0; i < 2; i++) { | for (i = 0; i < 2; i++) { | ||||
value[i] = i; | value[i] = i; | ||||
VERIFY3U(0, ==, zap_add(os, object, hc[i], sizeof (uint64_t), | VERIFY0(zap_add(os, object, hc[i], sizeof (uint64_t), | ||||
1, &value[i], tx)); | 1, &value[i], tx)); | ||||
} | } | ||||
for (i = 0; i < 2; i++) { | for (i = 0; i < 2; i++) { | ||||
VERIFY3U(EEXIST, ==, zap_add(os, object, hc[i], | VERIFY3U(EEXIST, ==, zap_add(os, object, hc[i], | ||||
sizeof (uint64_t), 1, &value[i], tx)); | sizeof (uint64_t), 1, &value[i], tx)); | ||||
VERIFY3U(0, ==, | VERIFY0( | ||||
zap_length(os, object, hc[i], &zl_intsize, &zl_ints)); | zap_length(os, object, hc[i], &zl_intsize, &zl_ints)); | ||||
ASSERT3U(zl_intsize, ==, sizeof (uint64_t)); | ASSERT3U(zl_intsize, ==, sizeof (uint64_t)); | ||||
ASSERT3U(zl_ints, ==, 1); | ASSERT3U(zl_ints, ==, 1); | ||||
} | } | ||||
for (i = 0; i < 2; i++) { | for (i = 0; i < 2; i++) { | ||||
VERIFY3U(0, ==, zap_remove(os, object, hc[i], tx)); | VERIFY0(zap_remove(os, object, hc[i], tx)); | ||||
} | } | ||||
dmu_tx_commit(tx); | dmu_tx_commit(tx); | ||||
/* | /* | ||||
* Generate a bunch of random entries. | * Generate a bunch of random entries. | ||||
*/ | */ | ||||
ints = MAX(ZTEST_ZAP_MIN_INTS, object % ZTEST_ZAP_MAX_INTS); | ints = MAX(ZTEST_ZAP_MIN_INTS, object % ZTEST_ZAP_MAX_INTS); | ||||
prop = ztest_random(ZTEST_ZAP_MAX_PROPS); | prop = ztest_random(ZTEST_ZAP_MAX_PROPS); | ||||
(void) sprintf(propname, "prop_%llu", (u_longlong_t)prop); | (void) sprintf(propname, "prop_%llu", (u_longlong_t)prop); | ||||
(void) sprintf(txgname, "txg_%llu", (u_longlong_t)prop); | (void) sprintf(txgname, "txg_%llu", (u_longlong_t)prop); | ||||
bzero(value, sizeof (value)); | bzero(value, sizeof (value)); | ||||
last_txg = 0; | last_txg = 0; | ||||
/* | /* | ||||
* If these zap entries already exist, validate their contents. | * If these zap entries already exist, validate their contents. | ||||
*/ | */ | ||||
error = zap_length(os, object, txgname, &zl_intsize, &zl_ints); | error = zap_length(os, object, txgname, &zl_intsize, &zl_ints); | ||||
if (error == 0) { | if (error == 0) { | ||||
ASSERT3U(zl_intsize, ==, sizeof (uint64_t)); | ASSERT3U(zl_intsize, ==, sizeof (uint64_t)); | ||||
ASSERT3U(zl_ints, ==, 1); | ASSERT3U(zl_ints, ==, 1); | ||||
VERIFY(zap_lookup(os, object, txgname, zl_intsize, | VERIFY0(zap_lookup(os, object, txgname, zl_intsize, | ||||
zl_ints, &last_txg) == 0); | zl_ints, &last_txg)); | ||||
VERIFY(zap_length(os, object, propname, &zl_intsize, | VERIFY0(zap_length(os, object, propname, &zl_intsize, | ||||
&zl_ints) == 0); | &zl_ints)); | ||||
ASSERT3U(zl_intsize, ==, sizeof (uint64_t)); | ASSERT3U(zl_intsize, ==, sizeof (uint64_t)); | ||||
ASSERT3U(zl_ints, ==, ints); | ASSERT3U(zl_ints, ==, ints); | ||||
VERIFY(zap_lookup(os, object, propname, zl_intsize, | VERIFY0(zap_lookup(os, object, propname, zl_intsize, | ||||
zl_ints, value) == 0); | zl_ints, value)); | ||||
for (i = 0; i < ints; i++) { | for (i = 0; i < ints; i++) { | ||||
ASSERT3U(value[i], ==, last_txg + object + i); | ASSERT3U(value[i], ==, last_txg + object + i); | ||||
} | } | ||||
} else { | } else { | ||||
ASSERT3U(error, ==, ENOENT); | ASSERT3U(error, ==, ENOENT); | ||||
} | } | ||||
Show All 11 Lines | if (txg == 0) | ||||
goto out; | goto out; | ||||
if (last_txg > txg) | if (last_txg > txg) | ||||
fatal(0, "zap future leak: old %llu new %llu", last_txg, txg); | fatal(0, "zap future leak: old %llu new %llu", last_txg, txg); | ||||
for (i = 0; i < ints; i++) | for (i = 0; i < ints; i++) | ||||
value[i] = txg + object + i; | value[i] = txg + object + i; | ||||
VERIFY3U(0, ==, zap_update(os, object, txgname, sizeof (uint64_t), | VERIFY0(zap_update(os, object, txgname, sizeof (uint64_t), | ||||
1, &txg, tx)); | 1, &txg, tx)); | ||||
VERIFY3U(0, ==, zap_update(os, object, propname, sizeof (uint64_t), | VERIFY0(zap_update(os, object, propname, sizeof (uint64_t), | ||||
ints, value, tx)); | ints, value, tx)); | ||||
dmu_tx_commit(tx); | dmu_tx_commit(tx); | ||||
/* | /* | ||||
* Remove a random pair of entries. | * Remove a random pair of entries. | ||||
*/ | */ | ||||
prop = ztest_random(ZTEST_ZAP_MAX_PROPS); | prop = ztest_random(ZTEST_ZAP_MAX_PROPS); | ||||
(void) sprintf(propname, "prop_%llu", (u_longlong_t)prop); | (void) sprintf(propname, "prop_%llu", (u_longlong_t)prop); | ||||
(void) sprintf(txgname, "txg_%llu", (u_longlong_t)prop); | (void) sprintf(txgname, "txg_%llu", (u_longlong_t)prop); | ||||
error = zap_length(os, object, txgname, &zl_intsize, &zl_ints); | error = zap_length(os, object, txgname, &zl_intsize, &zl_ints); | ||||
if (error == ENOENT) | if (error == ENOENT) | ||||
goto out; | goto out; | ||||
ASSERT0(error); | ASSERT0(error); | ||||
tx = dmu_tx_create(os); | tx = dmu_tx_create(os); | ||||
dmu_tx_hold_zap(tx, object, B_TRUE, NULL); | dmu_tx_hold_zap(tx, object, B_TRUE, NULL); | ||||
txg = ztest_tx_assign(tx, TXG_MIGHTWAIT, FTAG); | txg = ztest_tx_assign(tx, TXG_MIGHTWAIT, FTAG); | ||||
if (txg == 0) | if (txg == 0) | ||||
goto out; | goto out; | ||||
VERIFY3U(0, ==, zap_remove(os, object, txgname, tx)); | VERIFY0(zap_remove(os, object, txgname, tx)); | ||||
VERIFY3U(0, ==, zap_remove(os, object, propname, tx)); | VERIFY0(zap_remove(os, object, propname, tx)); | ||||
dmu_tx_commit(tx); | dmu_tx_commit(tx); | ||||
out: | out: | ||||
umem_free(od, sizeof (ztest_od_t)); | umem_free(od, sizeof (ztest_od_t)); | ||||
} | } | ||||
/* | /* | ||||
* Test case to test the upgrading of a microzap to fatzap. | * Test case to test the upgrading of a microzap to fatzap. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 85 Lines • ▼ Show 20 Lines | ztest_zap_parallel(ztest_ds_t *zd, uint64_t id) | ||||
} else { | } else { | ||||
wsize = 1; | wsize = 1; | ||||
wc = namelen; | wc = namelen; | ||||
data = string_value; | data = string_value; | ||||
} | } | ||||
count = -1ULL; | count = -1ULL; | ||||
VERIFY0(zap_count(os, object, &count)); | VERIFY0(zap_count(os, object, &count)); | ||||
ASSERT(count != -1ULL); | ASSERT3S(count, !=, -1ULL); | ||||
/* | /* | ||||
* Select an operation: length, lookup, add, update, remove. | * Select an operation: length, lookup, add, update, remove. | ||||
*/ | */ | ||||
i = ztest_random(5); | i = ztest_random(5); | ||||
if (i >= 2) { | if (i >= 2) { | ||||
tx = dmu_tx_create(os); | tx = dmu_tx_create(os); | ||||
Show All 35 Lines | case 1: | ||||
break; | break; | ||||
case 2: | case 2: | ||||
error = zap_add(os, object, name, wsize, wc, data, tx); | error = zap_add(os, object, name, wsize, wc, data, tx); | ||||
ASSERT(error == 0 || error == EEXIST); | ASSERT(error == 0 || error == EEXIST); | ||||
break; | break; | ||||
case 3: | case 3: | ||||
VERIFY(zap_update(os, object, name, wsize, wc, data, tx) == 0); | VERIFY0(zap_update(os, object, name, wsize, wc, data, tx)); | ||||
break; | break; | ||||
case 4: | case 4: | ||||
error = zap_remove(os, object, name, tx); | error = zap_remove(os, object, name, tx); | ||||
ASSERT(error == 0 || error == ENOENT); | ASSERT(error == 0 || error == ENOENT); | ||||
break; | break; | ||||
} | } | ||||
Show All 17 Lines | |||||
/* This is the actual commit callback function */ | /* This is the actual commit callback function */ | ||||
static void | static void | ||||
ztest_commit_callback(void *arg, int error) | ztest_commit_callback(void *arg, int error) | ||||
{ | { | ||||
ztest_cb_data_t *data = arg; | ztest_cb_data_t *data = arg; | ||||
uint64_t synced_txg; | uint64_t synced_txg; | ||||
VERIFY(data != NULL); | VERIFY3P(data, !=, NULL); | ||||
VERIFY3S(data->zcd_expected_err, ==, error); | VERIFY3S(data->zcd_expected_err, ==, error); | ||||
VERIFY(!data->zcd_called); | VERIFY(!data->zcd_called); | ||||
synced_txg = spa_last_synced_txg(data->zcd_spa); | synced_txg = spa_last_synced_txg(data->zcd_spa); | ||||
if (data->zcd_txg > synced_txg) | if (data->zcd_txg > synced_txg) | ||||
fatal(0, "commit callback of txg %" PRIu64 " called prematurely" | fatal(0, "commit callback of txg %" PRIu64 " called prematurely" | ||||
", last synced txg = %" PRIu64 "\n", data->zcd_txg, | ", last synced txg = %" PRIu64 "\n", data->zcd_txg, | ||||
synced_txg); | synced_txg); | ||||
▲ Show 20 Lines • Show All 109 Lines • ▼ Show 20 Lines | ztest_dmu_commit_callbacks(ztest_ds_t *zd, uint64_t id) | ||||
} | } | ||||
cb_data[2] = ztest_create_cb_data(os, txg); | cb_data[2] = ztest_create_cb_data(os, txg); | ||||
dmu_tx_callback_register(tx, ztest_commit_callback, cb_data[2]); | dmu_tx_callback_register(tx, ztest_commit_callback, cb_data[2]); | ||||
/* | /* | ||||
* Read existing data to make sure there isn't a future leak. | * Read existing data to make sure there isn't a future leak. | ||||
*/ | */ | ||||
VERIFY(0 == dmu_read(os, od->od_object, 0, sizeof (uint64_t), | VERIFY0(dmu_read(os, od->od_object, 0, sizeof (uint64_t), | ||||
&old_txg, DMU_READ_PREFETCH)); | &old_txg, DMU_READ_PREFETCH)); | ||||
if (old_txg > txg) | if (old_txg > txg) | ||||
fatal(0, "future leak: got %" PRIu64 ", open txg is %" PRIu64, | fatal(0, "future leak: got %" PRIu64 ", open txg is %" PRIu64, | ||||
old_txg, txg); | old_txg, txg); | ||||
dmu_write(os, od->od_object, 0, sizeof (uint64_t), &txg, tx); | dmu_write(os, od->od_object, 0, sizeof (uint64_t), &txg, tx); | ||||
▲ Show 20 Lines • Show All 127 Lines • ▼ Show 20 Lines | ztest_spa_prop_get_set(ztest_ds_t *zd, uint64_t id) | ||||
(void) ztest_spa_prop_set_uint64(ZPOOL_PROP_AUTOTRIM, ztest_random(2)); | (void) ztest_spa_prop_set_uint64(ZPOOL_PROP_AUTOTRIM, ztest_random(2)); | ||||
VERIFY0(spa_prop_get(ztest_spa, &props)); | VERIFY0(spa_prop_get(ztest_spa, &props)); | ||||
if (ztest_opts.zo_verbose >= 6) | if (ztest_opts.zo_verbose >= 6) | ||||
dump_nvlist(props, 4); | dump_nvlist(props, 4); | ||||
nvlist_free(props); | fnvlist_free(props); | ||||
(void) pthread_rwlock_unlock(&ztest_name_lock); | (void) pthread_rwlock_unlock(&ztest_name_lock); | ||||
} | } | ||||
static int | static int | ||||
user_release_one(const char *snapname, const char *holdname) | user_release_one(const char *snapname, const char *holdname) | ||||
{ | { | ||||
nvlist_t *snaps, *holds; | nvlist_t *snaps, *holds; | ||||
▲ Show 20 Lines • Show All 175 Lines • ▼ Show 20 Lines | if (ztest_device_removal_active) { | ||||
goto out; | goto out; | ||||
} | } | ||||
maxfaults = MAXFAULTS(zs); | maxfaults = MAXFAULTS(zs); | ||||
leaves = MAX(zs->zs_mirrors, 1) * ztest_opts.zo_raid_children; | leaves = MAX(zs->zs_mirrors, 1) * ztest_opts.zo_raid_children; | ||||
mirror_save = zs->zs_mirrors; | mirror_save = zs->zs_mirrors; | ||||
mutex_exit(&ztest_vdev_lock); | mutex_exit(&ztest_vdev_lock); | ||||
ASSERT(leaves >= 1); | ASSERT3U(leaves, >=, 1); | ||||
/* | /* | ||||
* While ztest is running the number of leaves will not change. This | * While ztest is running the number of leaves will not change. This | ||||
* is critical for the fault injection logic as it determines where | * is critical for the fault injection logic as it determines where | ||||
* errors can be safely injected such that they are always repairable. | * errors can be safely injected such that they are always repairable. | ||||
* | * | ||||
* When restarting ztest a different number of leaves may be requested | * When restarting ztest a different number of leaves may be requested | ||||
* which will shift the regions to be damaged. This is fine as long | * which will shift the regions to be damaged. This is fine as long | ||||
▲ Show 20 Lines • Show All 112 Lines • ▼ Show 20 Lines | if (ztest_random(10) < 6) { | ||||
* destroying a dataset. Offlining the slog will | * destroying a dataset. Offlining the slog will | ||||
* grab a reference on the dataset which may cause | * grab a reference on the dataset which may cause | ||||
* dsl_destroy_head() to fail with EBUSY thus | * dsl_destroy_head() to fail with EBUSY thus | ||||
* leaving the dataset in an inconsistent state. | * leaving the dataset in an inconsistent state. | ||||
*/ | */ | ||||
if (islog) | if (islog) | ||||
(void) pthread_rwlock_wrlock(&ztest_name_lock); | (void) pthread_rwlock_wrlock(&ztest_name_lock); | ||||
VERIFY(vdev_offline(spa, guid0, flags) != EBUSY); | VERIFY3U(vdev_offline(spa, guid0, flags), !=, EBUSY); | ||||
if (islog) | if (islog) | ||||
(void) pthread_rwlock_unlock(&ztest_name_lock); | (void) pthread_rwlock_unlock(&ztest_name_lock); | ||||
} else { | } else { | ||||
/* | /* | ||||
* Ideally we would like to be able to randomly | * Ideally we would like to be able to randomly | ||||
* call vdev_[on|off]line without holding locks | * call vdev_[on|off]line without holding locks | ||||
* to force unpredictable failures but the side | * to force unpredictable failures but the side | ||||
▲ Show 20 Lines • Show All 354 Lines • ▼ Show 20 Lines | if ((zdb_path = getenv("ZDB_PATH"))) { | ||||
strlcpy(bin, zdb_path, len); /* In env */ | strlcpy(bin, zdb_path, len); /* In env */ | ||||
if (!ztest_check_path(bin)) { | if (!ztest_check_path(bin)) { | ||||
ztest_dump_core = 0; | ztest_dump_core = 0; | ||||
fatal(1, "invalid ZDB_PATH '%s'", bin); | fatal(1, "invalid ZDB_PATH '%s'", bin); | ||||
} | } | ||||
return; | return; | ||||
} | } | ||||
VERIFY(realpath(getexecname(), bin) != NULL); | VERIFY3P(realpath(getexecname(), bin), !=, NULL); | ||||
if (strstr(bin, "/ztest/")) { | if (strstr(bin, "/ztest/")) { | ||||
strstr(bin, "/ztest/")[0] = '\0'; /* In-tree */ | strstr(bin, "/ztest/")[0] = '\0'; /* In-tree */ | ||||
strcat(bin, "/zdb/zdb"); | strcat(bin, "/zdb/zdb"); | ||||
if (ztest_check_path(bin)) | if (ztest_check_path(bin)) | ||||
return; | return; | ||||
} | } | ||||
strcpy(bin, "zdb"); | strcpy(bin, "zdb"); | ||||
} | } | ||||
Show All 13 Lines | for (i = 0; i < vd->vdev_children; i++) { | ||||
vdev_t *cvd = vd->vdev_child[i]; | vdev_t *cvd = vd->vdev_child[i]; | ||||
if (cvd->vdev_top->vdev_removing) | if (cvd->vdev_top->vdev_removing) | ||||
continue; | continue; | ||||
if (cvd->vdev_children > 0 || | if (cvd->vdev_children > 0 || | ||||
(vdev_is_concrete(cvd) && !cvd->vdev_detached)) { | (vdev_is_concrete(cvd) && !cvd->vdev_detached)) { | ||||
eligible[eligible_idx++] = cvd; | eligible[eligible_idx++] = cvd; | ||||
} | } | ||||
} | } | ||||
VERIFY(eligible_idx > 0); | VERIFY3S(eligible_idx, >, 0); | ||||
uint64_t child_no = ztest_random(eligible_idx); | uint64_t child_no = ztest_random(eligible_idx); | ||||
return (ztest_random_concrete_vdev_leaf(eligible[child_no])); | return (ztest_random_concrete_vdev_leaf(eligible[child_no])); | ||||
} | } | ||||
/* ARGSUSED */ | /* ARGSUSED */ | ||||
void | void | ||||
ztest_initialize(ztest_ds_t *zd, uint64_t id) | ztest_initialize(ztest_ds_t *zd, uint64_t id) | ||||
▲ Show 20 Lines • Show All 225 Lines • ▼ Show 20 Lines | ztest_spa_import_export(char *oldname, char *newname) | ||||
/* | /* | ||||
* Clean up from previous runs. | * Clean up from previous runs. | ||||
*/ | */ | ||||
(void) spa_destroy(newname); | (void) spa_destroy(newname); | ||||
/* | /* | ||||
* Get the pool's configuration and guid. | * Get the pool's configuration and guid. | ||||
*/ | */ | ||||
VERIFY3U(0, ==, spa_open(oldname, &spa, FTAG)); | VERIFY0(spa_open(oldname, &spa, FTAG)); | ||||
/* | /* | ||||
* Kick off a scrub to tickle scrub/export races. | * Kick off a scrub to tickle scrub/export races. | ||||
*/ | */ | ||||
if (ztest_random(2) == 0) | if (ztest_random(2) == 0) | ||||
(void) spa_scan(spa, POOL_SCAN_SCRUB); | (void) spa_scan(spa, POOL_SCAN_SCRUB); | ||||
pool_guid = spa_guid(spa); | pool_guid = spa_guid(spa); | ||||
spa_close(spa, FTAG); | spa_close(spa, FTAG); | ||||
ztest_walk_pool_directory("pools before export"); | ztest_walk_pool_directory("pools before export"); | ||||
/* | /* | ||||
* Export it. | * Export it. | ||||
*/ | */ | ||||
VERIFY3U(0, ==, spa_export(oldname, &config, B_FALSE, B_FALSE)); | VERIFY0(spa_export(oldname, &config, B_FALSE, B_FALSE)); | ||||
ztest_walk_pool_directory("pools after export"); | ztest_walk_pool_directory("pools after export"); | ||||
/* | /* | ||||
* Try to import it. | * Try to import it. | ||||
*/ | */ | ||||
newconfig = spa_tryimport(config); | newconfig = spa_tryimport(config); | ||||
ASSERT(newconfig != NULL); | ASSERT3P(newconfig, !=, NULL); | ||||
nvlist_free(newconfig); | fnvlist_free(newconfig); | ||||
/* | /* | ||||
* Import it under the new name. | * Import it under the new name. | ||||
*/ | */ | ||||
error = spa_import(newname, config, NULL, 0); | error = spa_import(newname, config, NULL, 0); | ||||
if (error != 0) { | if (error != 0) { | ||||
dump_nvlist(config, 0); | dump_nvlist(config, 0); | ||||
fatal(B_FALSE, "couldn't import pool %s as %s: error %u", | fatal(B_FALSE, "couldn't import pool %s as %s: error %u", | ||||
Show All 15 Lines | ztest_spa_import_export(char *oldname, char *newname) | ||||
/* | /* | ||||
* Verify that the pool is no longer visible under the old name. | * Verify that the pool is no longer visible under the old name. | ||||
*/ | */ | ||||
VERIFY3U(ENOENT, ==, spa_open(oldname, &spa, FTAG)); | VERIFY3U(ENOENT, ==, spa_open(oldname, &spa, FTAG)); | ||||
/* | /* | ||||
* Verify that we can open and close the pool using the new name. | * Verify that we can open and close the pool using the new name. | ||||
*/ | */ | ||||
VERIFY3U(0, ==, spa_open(newname, &spa, FTAG)); | VERIFY0(spa_open(newname, &spa, FTAG)); | ||||
ASSERT(pool_guid == spa_guid(spa)); | ASSERT3U(pool_guid, ==, spa_guid(spa)); | ||||
spa_close(spa, FTAG); | spa_close(spa, FTAG); | ||||
nvlist_free(config); | fnvlist_free(config); | ||||
} | } | ||||
static void | static void | ||||
ztest_resume(spa_t *spa) | ztest_resume(spa_t *spa) | ||||
{ | { | ||||
if (spa_suspended(spa) && ztest_opts.zo_verbose >= 6) | if (spa_suspended(spa) && ztest_opts.zo_verbose >= 6) | ||||
(void) printf("resuming from suspended state\n"); | (void) printf("resuming from suspended state\n"); | ||||
spa_vdev_state_enter(spa, SCL_NONE); | spa_vdev_state_enter(spa, SCL_NONE); | ||||
▲ Show 20 Lines • Show All 187 Lines • ▼ Show 20 Lines | ztest_dataset_dirobj_verify(ztest_ds_t *zd) | ||||
* number of ZTEST_DIROBJ entries, +1 for ZTEST_DIROBJ itself. | * number of ZTEST_DIROBJ entries, +1 for ZTEST_DIROBJ itself. | ||||
* If not, we have an object leak. | * If not, we have an object leak. | ||||
* | * | ||||
* Note that we can only check this in ztest_dataset_open(), | * Note that we can only check this in ztest_dataset_open(), | ||||
* when the open-context and syncing-context values agree. | * when the open-context and syncing-context values agree. | ||||
* That's because zap_count() returns the open-context value, | * That's because zap_count() returns the open-context value, | ||||
* while dmu_objset_space() returns the rootbp fill count. | * while dmu_objset_space() returns the rootbp fill count. | ||||
*/ | */ | ||||
VERIFY3U(0, ==, zap_count(zd->zd_os, ZTEST_DIROBJ, &dirobjs)); | VERIFY0(zap_count(zd->zd_os, ZTEST_DIROBJ, &dirobjs)); | ||||
dmu_objset_space(zd->zd_os, &scratch, &scratch, &usedobjs, &scratch); | dmu_objset_space(zd->zd_os, &scratch, &scratch, &usedobjs, &scratch); | ||||
ASSERT3U(dirobjs + 1, ==, usedobjs); | ASSERT3U(dirobjs + 1, ==, usedobjs); | ||||
} | } | ||||
static int | static int | ||||
ztest_dataset_open(int d) | ztest_dataset_open(int d) | ||||
{ | { | ||||
ztest_ds_t *zd = &ztest_ds[d]; | ztest_ds_t *zd = &ztest_ds[d]; | ||||
▲ Show 20 Lines • Show All 101 Lines • ▼ Show 20 Lines | ztest_freeze(void) | ||||
ztest_ds_t *zd = &ztest_ds[0]; | ztest_ds_t *zd = &ztest_ds[0]; | ||||
spa_t *spa; | spa_t *spa; | ||||
int numloops = 0; | int numloops = 0; | ||||
if (ztest_opts.zo_verbose >= 3) | if (ztest_opts.zo_verbose >= 3) | ||||
(void) printf("testing spa_freeze()...\n"); | (void) printf("testing spa_freeze()...\n"); | ||||
kernel_init(SPA_MODE_READ | SPA_MODE_WRITE); | kernel_init(SPA_MODE_READ | SPA_MODE_WRITE); | ||||
VERIFY3U(0, ==, spa_open(ztest_opts.zo_pool, &spa, FTAG)); | VERIFY0(spa_open(ztest_opts.zo_pool, &spa, FTAG)); | ||||
VERIFY3U(0, ==, ztest_dataset_open(0)); | VERIFY0(ztest_dataset_open(0)); | ||||
ztest_spa = spa; | ztest_spa = spa; | ||||
/* | /* | ||||
* Force the first log block to be transactionally allocated. | * Force the first log block to be transactionally allocated. | ||||
* We have to do this before we freeze the pool -- otherwise | * We have to do this before we freeze the pool -- otherwise | ||||
* the log chain won't be anchored. | * the log chain won't be anchored. | ||||
*/ | */ | ||||
while (BP_IS_HOLE(&zd->zd_zilog->zl_header->zh_log)) { | while (BP_IS_HOLE(&zd->zd_zilog->zl_header->zh_log)) { | ||||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | ztest_freeze(void) | ||||
ztest_dataset_close(0); | ztest_dataset_close(0); | ||||
spa_close(spa, FTAG); | spa_close(spa, FTAG); | ||||
kernel_fini(); | kernel_fini(); | ||||
/* | /* | ||||
* Open and close the pool and dataset to induce log replay. | * Open and close the pool and dataset to induce log replay. | ||||
*/ | */ | ||||
kernel_init(SPA_MODE_READ | SPA_MODE_WRITE); | kernel_init(SPA_MODE_READ | SPA_MODE_WRITE); | ||||
VERIFY3U(0, ==, spa_open(ztest_opts.zo_pool, &spa, FTAG)); | VERIFY0(spa_open(ztest_opts.zo_pool, &spa, FTAG)); | ||||
ASSERT(spa_freeze_txg(spa) == UINT64_MAX); | ASSERT3U(spa_freeze_txg(spa), ==, UINT64_MAX); | ||||
VERIFY3U(0, ==, ztest_dataset_open(0)); | VERIFY0(ztest_dataset_open(0)); | ||||
ztest_spa = spa; | ztest_spa = spa; | ||||
txg_wait_synced(spa_get_dsl(spa), 0); | txg_wait_synced(spa_get_dsl(spa), 0); | ||||
ztest_dataset_close(0); | ztest_dataset_close(0); | ||||
ztest_reguid(NULL, 0); | ztest_reguid(NULL, 0); | ||||
spa_close(spa, FTAG); | spa_close(spa, FTAG); | ||||
kernel_fini(); | kernel_fini(); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 306 Lines • ▼ Show 20 Lines | else | ||||
(void) sprintf(timebuf, "%llus", s); | (void) sprintf(timebuf, "%llus", s); | ||||
} | } | ||||
static nvlist_t * | static nvlist_t * | ||||
make_random_props(void) | make_random_props(void) | ||||
{ | { | ||||
nvlist_t *props; | nvlist_t *props; | ||||
VERIFY0(nvlist_alloc(&props, NV_UNIQUE_NAME, 0)); | props = fnvlist_alloc(); | ||||
if (ztest_random(2) == 0) | if (ztest_random(2) == 0) | ||||
return (props); | return (props); | ||||
VERIFY0(nvlist_add_uint64(props, | fnvlist_add_uint64(props, | ||||
zpool_prop_to_name(ZPOOL_PROP_AUTOREPLACE), 1)); | zpool_prop_to_name(ZPOOL_PROP_AUTOREPLACE), 1); | ||||
return (props); | return (props); | ||||
} | } | ||||
/* | /* | ||||
* Create a storage pool with the given name and initial vdev size. | * Create a storage pool with the given name and initial vdev size. | ||||
* Then test spa_freeze() functionality. | * Then test spa_freeze() functionality. | ||||
*/ | */ | ||||
Show All 21 Lines | nvroot = make_vdev_root(NULL, NULL, NULL, ztest_opts.zo_vdev_size, 0, | ||||
NULL, ztest_opts.zo_raid_children, zs->zs_mirrors, 1); | NULL, ztest_opts.zo_raid_children, zs->zs_mirrors, 1); | ||||
props = make_random_props(); | props = make_random_props(); | ||||
/* | /* | ||||
* We don't expect the pool to suspend unless maxfaults == 0, | * We don't expect the pool to suspend unless maxfaults == 0, | ||||
* in which case ztest_fault_inject() temporarily takes away | * in which case ztest_fault_inject() temporarily takes away | ||||
* the only valid replica. | * the only valid replica. | ||||
*/ | */ | ||||
VERIFY0(nvlist_add_uint64(props, | fnvlist_add_uint64(props, | ||||
zpool_prop_to_name(ZPOOL_PROP_FAILUREMODE), | zpool_prop_to_name(ZPOOL_PROP_FAILUREMODE), | ||||
MAXFAULTS(zs) ? ZIO_FAILURE_MODE_PANIC : ZIO_FAILURE_MODE_WAIT)); | MAXFAULTS(zs) ? ZIO_FAILURE_MODE_PANIC : ZIO_FAILURE_MODE_WAIT); | ||||
for (i = 0; i < SPA_FEATURES; i++) { | for (i = 0; i < SPA_FEATURES; i++) { | ||||
char *buf; | char *buf; | ||||
/* | /* | ||||
* 75% chance of using the log space map feature. We want ztest | * 75% chance of using the log space map feature. We want ztest | ||||
* to exercise both the code paths that use the log space map | * to exercise both the code paths that use the log space map | ||||
* feature and the ones that don't. | * feature and the ones that don't. | ||||
*/ | */ | ||||
if (i == SPA_FEATURE_LOG_SPACEMAP && ztest_random(4) == 0) | if (i == SPA_FEATURE_LOG_SPACEMAP && ztest_random(4) == 0) | ||||
continue; | continue; | ||||
VERIFY3S(-1, !=, asprintf(&buf, "feature@%s", | VERIFY3S(-1, !=, asprintf(&buf, "feature@%s", | ||||
spa_feature_table[i].fi_uname)); | spa_feature_table[i].fi_uname)); | ||||
VERIFY3U(0, ==, nvlist_add_uint64(props, buf, 0)); | fnvlist_add_uint64(props, buf, 0); | ||||
free(buf); | free(buf); | ||||
} | } | ||||
VERIFY0(spa_create(ztest_opts.zo_pool, nvroot, props, NULL, NULL)); | VERIFY0(spa_create(ztest_opts.zo_pool, nvroot, props, NULL, NULL)); | ||||
nvlist_free(nvroot); | fnvlist_free(nvroot); | ||||
nvlist_free(props); | fnvlist_free(props); | ||||
VERIFY3U(0, ==, spa_open(ztest_opts.zo_pool, &spa, FTAG)); | VERIFY0(spa_open(ztest_opts.zo_pool, &spa, FTAG)); | ||||
zs->zs_metaslab_sz = | zs->zs_metaslab_sz = | ||||
1ULL << spa->spa_root_vdev->vdev_child[0]->vdev_ms_shift; | 1ULL << spa->spa_root_vdev->vdev_child[0]->vdev_ms_shift; | ||||
spa_close(spa, FTAG); | spa_close(spa, FTAG); | ||||
kernel_fini(); | kernel_fini(); | ||||
if (!ztest_opts.zo_mmp_test) { | if (!ztest_opts.zo_mmp_test) { | ||||
ztest_run_zdb(ztest_opts.zo_pool); | ztest_run_zdb(ztest_opts.zo_pool); | ||||
Show All 33 Lines | |||||
static void | static void | ||||
setup_hdr(void) | setup_hdr(void) | ||||
{ | { | ||||
int size; | int size; | ||||
ztest_shared_hdr_t *hdr; | ztest_shared_hdr_t *hdr; | ||||
hdr = (void *)mmap(0, P2ROUNDUP(sizeof (*hdr), getpagesize()), | hdr = (void *)mmap(0, P2ROUNDUP(sizeof (*hdr), getpagesize()), | ||||
PROT_READ | PROT_WRITE, MAP_SHARED, ztest_fd_data, 0); | PROT_READ | PROT_WRITE, MAP_SHARED, ztest_fd_data, 0); | ||||
ASSERT(hdr != MAP_FAILED); | ASSERT3P(hdr, !=, MAP_FAILED); | ||||
VERIFY3U(0, ==, ftruncate(ztest_fd_data, sizeof (ztest_shared_hdr_t))); | VERIFY0(ftruncate(ztest_fd_data, sizeof (ztest_shared_hdr_t))); | ||||
hdr->zh_hdr_size = sizeof (ztest_shared_hdr_t); | hdr->zh_hdr_size = sizeof (ztest_shared_hdr_t); | ||||
hdr->zh_opts_size = sizeof (ztest_shared_opts_t); | hdr->zh_opts_size = sizeof (ztest_shared_opts_t); | ||||
hdr->zh_size = sizeof (ztest_shared_t); | hdr->zh_size = sizeof (ztest_shared_t); | ||||
hdr->zh_stats_size = sizeof (ztest_shared_callstate_t); | hdr->zh_stats_size = sizeof (ztest_shared_callstate_t); | ||||
hdr->zh_stats_count = ZTEST_FUNCS; | hdr->zh_stats_count = ZTEST_FUNCS; | ||||
hdr->zh_ds_size = sizeof (ztest_shared_ds_t); | hdr->zh_ds_size = sizeof (ztest_shared_ds_t); | ||||
hdr->zh_ds_count = ztest_opts.zo_datasets; | hdr->zh_ds_count = ztest_opts.zo_datasets; | ||||
size = shared_data_size(hdr); | size = shared_data_size(hdr); | ||||
VERIFY3U(0, ==, ftruncate(ztest_fd_data, size)); | VERIFY0(ftruncate(ztest_fd_data, size)); | ||||
(void) munmap((caddr_t)hdr, P2ROUNDUP(sizeof (*hdr), getpagesize())); | (void) munmap((caddr_t)hdr, P2ROUNDUP(sizeof (*hdr), getpagesize())); | ||||
} | } | ||||
static void | static void | ||||
setup_data(void) | setup_data(void) | ||||
{ | { | ||||
int size, offset; | int size, offset; | ||||
ztest_shared_hdr_t *hdr; | ztest_shared_hdr_t *hdr; | ||||
uint8_t *buf; | uint8_t *buf; | ||||
hdr = (void *)mmap(0, P2ROUNDUP(sizeof (*hdr), getpagesize()), | hdr = (void *)mmap(0, P2ROUNDUP(sizeof (*hdr), getpagesize()), | ||||
PROT_READ, MAP_SHARED, ztest_fd_data, 0); | PROT_READ, MAP_SHARED, ztest_fd_data, 0); | ||||
ASSERT(hdr != MAP_FAILED); | ASSERT3P(hdr, !=, MAP_FAILED); | ||||
size = shared_data_size(hdr); | size = shared_data_size(hdr); | ||||
(void) munmap((caddr_t)hdr, P2ROUNDUP(sizeof (*hdr), getpagesize())); | (void) munmap((caddr_t)hdr, P2ROUNDUP(sizeof (*hdr), getpagesize())); | ||||
hdr = ztest_shared_hdr = (void *)mmap(0, P2ROUNDUP(size, getpagesize()), | hdr = ztest_shared_hdr = (void *)mmap(0, P2ROUNDUP(size, getpagesize()), | ||||
PROT_READ | PROT_WRITE, MAP_SHARED, ztest_fd_data, 0); | PROT_READ | PROT_WRITE, MAP_SHARED, ztest_fd_data, 0); | ||||
ASSERT(hdr != MAP_FAILED); | ASSERT3P(hdr, !=, MAP_FAILED); | ||||
buf = (uint8_t *)hdr; | buf = (uint8_t *)hdr; | ||||
offset = hdr->zh_hdr_size; | offset = hdr->zh_hdr_size; | ||||
ztest_shared_opts = (void *)&buf[offset]; | ztest_shared_opts = (void *)&buf[offset]; | ||||
offset += hdr->zh_opts_size; | offset += hdr->zh_opts_size; | ||||
ztest_shared = (void *)&buf[offset]; | ztest_shared = (void *)&buf[offset]; | ||||
offset += hdr->zh_size; | offset += hdr->zh_size; | ||||
ztest_shared_callstate = (void *)&buf[offset]; | ztest_shared_callstate = (void *)&buf[offset]; | ||||
Show All 22 Lines | exec_child(char *cmd, char *libpath, boolean_t ignorekill, int *statusp) | ||||
if (pid == 0) { /* child */ | if (pid == 0) { /* child */ | ||||
char *emptyargv[2] = { cmd, NULL }; | char *emptyargv[2] = { cmd, NULL }; | ||||
char fd_data_str[12]; | char fd_data_str[12]; | ||||
struct rlimit rl = { 1024, 1024 }; | struct rlimit rl = { 1024, 1024 }; | ||||
(void) setrlimit(RLIMIT_NOFILE, &rl); | (void) setrlimit(RLIMIT_NOFILE, &rl); | ||||
(void) close(ztest_fd_rand); | (void) close(ztest_fd_rand); | ||||
VERIFY(11 >= snprintf(fd_data_str, 12, "%d", ztest_fd_data)); | VERIFY3S(11, >=, | ||||
VERIFY(0 == setenv("ZTEST_FD_DATA", fd_data_str, 1)); | snprintf(fd_data_str, 12, "%d", ztest_fd_data)); | ||||
VERIFY0(setenv("ZTEST_FD_DATA", fd_data_str, 1)); | |||||
(void) enable_extended_FILE_stdio(-1, -1); | (void) enable_extended_FILE_stdio(-1, -1); | ||||
if (libpath != NULL) | if (libpath != NULL) | ||||
VERIFY(0 == setenv("LD_LIBRARY_PATH", libpath, 1)); | VERIFY0(setenv("LD_LIBRARY_PATH", libpath, 1)); | ||||
(void) execv(cmd, emptyargv); | (void) execv(cmd, emptyargv); | ||||
ztest_dump_core = B_FALSE; | ztest_dump_core = B_FALSE; | ||||
fatal(B_TRUE, "exec failed: %s", cmd); | fatal(B_TRUE, "exec failed: %s", cmd); | ||||
} | } | ||||
if (cmdbuf != NULL) { | if (cmdbuf != NULL) { | ||||
umem_free(cmdbuf, MAXPATHLEN); | umem_free(cmdbuf, MAXPATHLEN); | ||||
cmd = NULL; | cmd = NULL; | ||||
▲ Show 20 Lines • Show All 135 Lines • ▼ Show 20 Lines | main(int argc, char **argv) | ||||
} else { | } else { | ||||
ztest_fd_data = atoi(fd_data_str); | ztest_fd_data = atoi(fd_data_str); | ||||
setup_data(); | setup_data(); | ||||
bcopy(ztest_shared_opts, &ztest_opts, sizeof (ztest_opts)); | bcopy(ztest_shared_opts, &ztest_opts, sizeof (ztest_opts)); | ||||
} | } | ||||
ASSERT3U(ztest_opts.zo_datasets, ==, ztest_shared_hdr->zh_ds_count); | ASSERT3U(ztest_opts.zo_datasets, ==, ztest_shared_hdr->zh_ds_count); | ||||
/* Override location of zpool.cache */ | /* Override location of zpool.cache */ | ||||
VERIFY(asprintf((char **)&spa_config_path, "%s/zpool.cache", | VERIFY3S(asprintf((char **)&spa_config_path, "%s/zpool.cache", | ||||
ztest_opts.zo_dir) != -1); | ztest_opts.zo_dir), !=, -1); | ||||
ztest_ds = umem_alloc(ztest_opts.zo_datasets * sizeof (ztest_ds_t), | ztest_ds = umem_alloc(ztest_opts.zo_datasets * sizeof (ztest_ds_t), | ||||
UMEM_NOFAIL); | UMEM_NOFAIL); | ||||
zs = ztest_shared; | zs = ztest_shared; | ||||
if (fd_data_str) { | if (fd_data_str) { | ||||
metaslab_force_ganging = ztest_opts.zo_metaslab_force_ganging; | metaslab_force_ganging = ztest_opts.zo_metaslab_force_ganging; | ||||
metaslab_df_alloc_threshold = | metaslab_df_alloc_threshold = | ||||
▲ Show 20 Lines • Show All 148 Lines • Show Last 20 Lines |