mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 18:40:43 +03:00
Illumos #3464
3464 zfs synctask code needs restructuring Reviewed by: Dan Kimmel <dan.kimmel@delphix.com> Reviewed by: Adam Leventhal <ahl@delphix.com> Reviewed by: George Wilson <george.wilson@delphix.com> Reviewed by: Christopher Siden <christopher.siden@delphix.com> Approved by: Garrett D'Amore <garrett@damore.org> References: https://www.illumos.org/issues/3464 illumos/illumos-gate@3b2aab1880 Ported-by: Tim Chase <tim@chase2k.com> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Closes #1495
This commit is contained in:
committed by
Brian Behlendorf
parent
6f1ffb0665
commit
13fe019870
+6
-3
@@ -1725,7 +1725,9 @@ dump_dir(objset_t *os)
|
||||
int print_header = 1;
|
||||
int i, error;
|
||||
|
||||
dsl_pool_config_enter(dmu_objset_pool(os), FTAG);
|
||||
dmu_objset_fast_stat(os, &dds);
|
||||
dsl_pool_config_exit(dmu_objset_pool(os), FTAG);
|
||||
|
||||
if (dds.dds_type < DMU_OST_NUMTYPES)
|
||||
type = objset_types[dds.dds_type];
|
||||
@@ -2171,7 +2173,6 @@ zdb_blkptr_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
|
||||
|
||||
zio_nowait(zio_read(NULL, spa, bp, data, size,
|
||||
zdb_blkptr_done, zcb, ZIO_PRIORITY_ASYNC_READ, flags, zb));
|
||||
|
||||
}
|
||||
|
||||
zcb->zcb_readfails = 0;
|
||||
@@ -2365,8 +2366,10 @@ dump_block_stats(spa_t *spa)
|
||||
*/
|
||||
(void) bpobj_iterate_nofree(&spa->spa_deferred_bpobj,
|
||||
count_block_cb, &zcb, NULL);
|
||||
(void) bpobj_iterate_nofree(&spa->spa_dsl_pool->dp_free_bpobj,
|
||||
count_block_cb, &zcb, NULL);
|
||||
if (spa_version(spa) >= SPA_VERSION_DEADLISTS) {
|
||||
(void) bpobj_iterate_nofree(&spa->spa_dsl_pool->dp_free_bpobj,
|
||||
count_block_cb, &zcb, NULL);
|
||||
}
|
||||
if (spa_feature_is_active(spa,
|
||||
&spa_feature_table[SPA_FEATURE_ASYNC_DESTROY])) {
|
||||
VERIFY3U(0, ==, bptree_iterate(spa->spa_meta_objset,
|
||||
|
||||
+66
-50
@@ -892,6 +892,7 @@ typedef struct destroy_cbdata {
|
||||
boolean_t cb_parsable;
|
||||
boolean_t cb_dryrun;
|
||||
nvlist_t *cb_nvl;
|
||||
nvlist_t *cb_batchedsnaps;
|
||||
|
||||
/* first snap in contiguous run */
|
||||
char *cb_firstsnap;
|
||||
@@ -988,9 +989,27 @@ destroy_callback(zfs_handle_t *zhp, void *data)
|
||||
zfs_close(zhp);
|
||||
return (0);
|
||||
}
|
||||
if (cb->cb_dryrun) {
|
||||
zfs_close(zhp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (!cb->cb_dryrun) {
|
||||
if (zfs_unmount(zhp, NULL, cb->cb_force ? MS_FORCE : 0) != 0 ||
|
||||
/*
|
||||
* We batch up all contiguous snapshots (even of different
|
||||
* filesystems) and destroy them with one ioctl. We can't
|
||||
* simply do all snap deletions and then all fs deletions,
|
||||
* because we must delete a clone before its origin.
|
||||
*/
|
||||
if (zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT) {
|
||||
fnvlist_add_boolean(cb->cb_batchedsnaps, name);
|
||||
} else {
|
||||
int error = zfs_destroy_snaps_nvl(g_zfs,
|
||||
cb->cb_batchedsnaps, B_FALSE);
|
||||
fnvlist_free(cb->cb_batchedsnaps);
|
||||
cb->cb_batchedsnaps = fnvlist_alloc();
|
||||
|
||||
if (error != 0 ||
|
||||
zfs_unmount(zhp, NULL, cb->cb_force ? MS_FORCE : 0) != 0 ||
|
||||
zfs_destroy(zhp, cb->cb_defer_destroy) != 0) {
|
||||
zfs_close(zhp);
|
||||
return (-1);
|
||||
@@ -1146,8 +1165,10 @@ static int
|
||||
zfs_do_destroy(int argc, char **argv)
|
||||
{
|
||||
destroy_cbdata_t cb = { 0 };
|
||||
int rv = 0;
|
||||
int err = 0;
|
||||
int c;
|
||||
zfs_handle_t *zhp;
|
||||
zfs_handle_t *zhp = NULL;
|
||||
char *at;
|
||||
zfs_type_t type = ZFS_TYPE_DATASET;
|
||||
|
||||
@@ -1201,11 +1222,9 @@ zfs_do_destroy(int argc, char **argv)
|
||||
|
||||
at = strchr(argv[0], '@');
|
||||
if (at != NULL) {
|
||||
int err = 0;
|
||||
|
||||
/* Build the list of snaps to destroy in cb_nvl. */
|
||||
if (nvlist_alloc(&cb.cb_nvl, NV_UNIQUE_NAME, 0) != 0)
|
||||
nomem();
|
||||
cb.cb_nvl = fnvlist_alloc();
|
||||
|
||||
*at = '\0';
|
||||
zhp = zfs_open(g_zfs, argv[0],
|
||||
@@ -1216,17 +1235,15 @@ zfs_do_destroy(int argc, char **argv)
|
||||
cb.cb_snapspec = at + 1;
|
||||
if (gather_snapshots(zfs_handle_dup(zhp), &cb) != 0 ||
|
||||
cb.cb_error) {
|
||||
zfs_close(zhp);
|
||||
nvlist_free(cb.cb_nvl);
|
||||
return (1);
|
||||
rv = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nvlist_empty(cb.cb_nvl)) {
|
||||
(void) fprintf(stderr, gettext("could not find any "
|
||||
"snapshots to destroy; check snapshot names.\n"));
|
||||
zfs_close(zhp);
|
||||
nvlist_free(cb.cb_nvl);
|
||||
return (1);
|
||||
rv = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (cb.cb_verbose) {
|
||||
@@ -1245,18 +1262,26 @@ zfs_do_destroy(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (!cb.cb_dryrun) {
|
||||
if (cb.cb_doclones)
|
||||
if (cb.cb_doclones) {
|
||||
cb.cb_batchedsnaps = fnvlist_alloc();
|
||||
err = destroy_clones(&cb);
|
||||
if (err == 0) {
|
||||
err = zfs_destroy_snaps_nvl(g_zfs,
|
||||
cb.cb_batchedsnaps, B_FALSE);
|
||||
}
|
||||
if (err != 0) {
|
||||
rv = 1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if (err == 0) {
|
||||
err = zfs_destroy_snaps_nvl(zhp, cb.cb_nvl,
|
||||
err = zfs_destroy_snaps_nvl(g_zfs, cb.cb_nvl,
|
||||
cb.cb_defer_destroy);
|
||||
}
|
||||
}
|
||||
|
||||
zfs_close(zhp);
|
||||
nvlist_free(cb.cb_nvl);
|
||||
if (err != 0)
|
||||
return (1);
|
||||
rv = 1;
|
||||
} else {
|
||||
/* Open the given dataset */
|
||||
if ((zhp = zfs_open(g_zfs, argv[0], type)) == NULL)
|
||||
@@ -1277,8 +1302,8 @@ zfs_do_destroy(int argc, char **argv)
|
||||
zfs_get_name(zhp));
|
||||
(void) fprintf(stderr, gettext("use 'zpool destroy %s' "
|
||||
"to destroy the pool itself\n"), zfs_get_name(zhp));
|
||||
zfs_close(zhp);
|
||||
return (1);
|
||||
rv = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1288,30 +1313,42 @@ zfs_do_destroy(int argc, char **argv)
|
||||
if (!cb.cb_doclones &&
|
||||
zfs_iter_dependents(zhp, B_TRUE, destroy_check_dependent,
|
||||
&cb) != 0) {
|
||||
zfs_close(zhp);
|
||||
return (1);
|
||||
rv = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (cb.cb_error) {
|
||||
zfs_close(zhp);
|
||||
return (1);
|
||||
rv = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cb.cb_batchedsnaps = fnvlist_alloc();
|
||||
if (zfs_iter_dependents(zhp, B_FALSE, destroy_callback,
|
||||
&cb) != 0) {
|
||||
zfs_close(zhp);
|
||||
return (1);
|
||||
rv = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do the real thing. The callback will close the
|
||||
* handle regardless of whether it succeeds or not.
|
||||
*/
|
||||
if (destroy_callback(zhp, &cb) != 0)
|
||||
return (1);
|
||||
err = destroy_callback(zhp, &cb);
|
||||
zhp = NULL;
|
||||
if (err == 0) {
|
||||
err = zfs_destroy_snaps_nvl(g_zfs,
|
||||
cb.cb_batchedsnaps, cb.cb_defer_destroy);
|
||||
}
|
||||
if (err != 0)
|
||||
rv = 1;
|
||||
}
|
||||
|
||||
return (0);
|
||||
out:
|
||||
fnvlist_free(cb.cb_batchedsnaps);
|
||||
fnvlist_free(cb.cb_nvl);
|
||||
if (zhp != NULL)
|
||||
zfs_close(zhp);
|
||||
return (rv);
|
||||
}
|
||||
|
||||
static boolean_t
|
||||
@@ -5081,28 +5118,12 @@ cleanup2:
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* zfs allow [-r] [-t] <tag> <snap> ...
|
||||
*
|
||||
* -r Recursively hold
|
||||
* -t Temporary hold (hidden option)
|
||||
*
|
||||
* Apply a user-hold with the given tag to the list of snapshots.
|
||||
*/
|
||||
static int
|
||||
zfs_do_allow(int argc, char **argv)
|
||||
{
|
||||
return (zfs_do_allow_unallow_impl(argc, argv, B_FALSE));
|
||||
}
|
||||
|
||||
/*
|
||||
* zfs unallow [-r] [-t] <tag> <snap> ...
|
||||
*
|
||||
* -r Recursively hold
|
||||
* -t Temporary hold (hidden option)
|
||||
*
|
||||
* Apply a user-hold with the given tag to the list of snapshots.
|
||||
*/
|
||||
static int
|
||||
zfs_do_unallow(int argc, char **argv)
|
||||
{
|
||||
@@ -5116,7 +5137,6 @@ zfs_do_hold_rele_impl(int argc, char **argv, boolean_t holding)
|
||||
int i;
|
||||
const char *tag;
|
||||
boolean_t recursive = B_FALSE;
|
||||
boolean_t temphold = B_FALSE;
|
||||
const char *opts = holding ? "rt" : "r";
|
||||
int c;
|
||||
|
||||
@@ -5126,9 +5146,6 @@ zfs_do_hold_rele_impl(int argc, char **argv, boolean_t holding)
|
||||
case 'r':
|
||||
recursive = B_TRUE;
|
||||
break;
|
||||
case 't':
|
||||
temphold = B_TRUE;
|
||||
break;
|
||||
case '?':
|
||||
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
|
||||
optopt);
|
||||
@@ -5177,7 +5194,7 @@ zfs_do_hold_rele_impl(int argc, char **argv, boolean_t holding)
|
||||
}
|
||||
if (holding) {
|
||||
if (zfs_hold(zhp, delim+1, tag, recursive,
|
||||
temphold, B_FALSE, -1, 0, 0) != 0)
|
||||
B_FALSE, -1) != 0)
|
||||
++errors;
|
||||
} else {
|
||||
if (zfs_release(zhp, delim+1, tag, recursive) != 0)
|
||||
@@ -5193,7 +5210,6 @@ zfs_do_hold_rele_impl(int argc, char **argv, boolean_t holding)
|
||||
* zfs hold [-r] [-t] <tag> <snap> ...
|
||||
*
|
||||
* -r Recursively hold
|
||||
* -t Temporary hold (hidden option)
|
||||
*
|
||||
* Apply a user-hold with the given tag to the list of snapshots.
|
||||
*/
|
||||
|
||||
+15
-14
@@ -46,6 +46,7 @@
|
||||
#include <sys/zio_checksum.h>
|
||||
#include <sys/zio_compress.h>
|
||||
#include <sys/zfeature.h>
|
||||
#include <sys/dmu_tx.h>
|
||||
#undef ZFS_MAXNAMELEN
|
||||
#include <libzfs.h>
|
||||
|
||||
@@ -123,7 +124,7 @@ import_pool(const char *target, boolean_t readonly)
|
||||
spa_t *spa;
|
||||
nvpair_t *elem;
|
||||
nvlist_t *props;
|
||||
const char *name;
|
||||
char *name;
|
||||
|
||||
kernel_init(readonly ? FREAD : (FREAD | FWRITE));
|
||||
g_zfs = libzfs_init();
|
||||
@@ -273,10 +274,10 @@ zhack_do_feature_stat(int argc, char **argv)
|
||||
}
|
||||
|
||||
static void
|
||||
feature_enable_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
||||
feature_enable_sync(void *arg, dmu_tx_t *tx)
|
||||
{
|
||||
spa_t *spa = arg1;
|
||||
zfeature_info_t *feature = arg2;
|
||||
spa_t *spa = dmu_tx_pool(tx)->dp_spa;
|
||||
zfeature_info_t *feature = arg;
|
||||
|
||||
spa_feature_enable(spa, feature, tx);
|
||||
spa_history_log_internal(spa, "zhack enable feature", tx,
|
||||
@@ -344,8 +345,8 @@ zhack_do_feature_enable(int argc, char **argv)
|
||||
if (0 == zap_contains(mos, spa->spa_feat_desc_obj, feature.fi_guid))
|
||||
fatal("feature already enabled: %s", feature.fi_guid);
|
||||
|
||||
VERIFY3U(0, ==, dsl_sync_task_do(spa->spa_dsl_pool, NULL,
|
||||
feature_enable_sync, spa, &feature, 5));
|
||||
VERIFY0(dsl_sync_task(spa_name(spa), NULL,
|
||||
feature_enable_sync, &feature, 5));
|
||||
|
||||
spa_close(spa, FTAG);
|
||||
|
||||
@@ -353,10 +354,10 @@ zhack_do_feature_enable(int argc, char **argv)
|
||||
}
|
||||
|
||||
static void
|
||||
feature_incr_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
||||
feature_incr_sync(void *arg, dmu_tx_t *tx)
|
||||
{
|
||||
spa_t *spa = arg1;
|
||||
zfeature_info_t *feature = arg2;
|
||||
spa_t *spa = dmu_tx_pool(tx)->dp_spa;
|
||||
zfeature_info_t *feature = arg;
|
||||
|
||||
spa_feature_incr(spa, feature, tx);
|
||||
spa_history_log_internal(spa, "zhack feature incr", tx,
|
||||
@@ -364,10 +365,10 @@ feature_incr_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
||||
}
|
||||
|
||||
static void
|
||||
feature_decr_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
||||
feature_decr_sync(void *arg, dmu_tx_t *tx)
|
||||
{
|
||||
spa_t *spa = arg1;
|
||||
zfeature_info_t *feature = arg2;
|
||||
spa_t *spa = dmu_tx_pool(tx)->dp_spa;
|
||||
zfeature_info_t *feature = arg;
|
||||
|
||||
spa_feature_decr(spa, feature, tx);
|
||||
spa_history_log_internal(spa, "zhack feature decr", tx,
|
||||
@@ -442,8 +443,8 @@ zhack_do_feature_ref(int argc, char **argv)
|
||||
if (decr && !spa_feature_is_active(spa, &feature))
|
||||
fatal("feature refcount already 0: %s", feature.fi_guid);
|
||||
|
||||
VERIFY3U(0, ==, dsl_sync_task_do(spa->spa_dsl_pool, NULL,
|
||||
decr ? feature_decr_sync : feature_incr_sync, spa, &feature, 5));
|
||||
VERIFY0(dsl_sync_task(spa_name(spa), NULL,
|
||||
decr ? feature_decr_sync : feature_incr_sync, &feature, 5));
|
||||
|
||||
spa_close(spa, FTAG);
|
||||
}
|
||||
|
||||
+111
-85
@@ -106,10 +106,12 @@
|
||||
#include <sys/metaslab_impl.h>
|
||||
#include <sys/dsl_prop.h>
|
||||
#include <sys/dsl_dataset.h>
|
||||
#include <sys/dsl_destroy.h>
|
||||
#include <sys/dsl_scan.h>
|
||||
#include <sys/zio_checksum.h>
|
||||
#include <sys/refcount.h>
|
||||
#include <sys/zfeature.h>
|
||||
#include <sys/dsl_userhold.h>
|
||||
#include <stdio.h>
|
||||
#include <stdio_ext.h>
|
||||
#include <stdlib.h>
|
||||
@@ -367,7 +369,7 @@ ztest_info_t ztest_info[] = {
|
||||
{ ztest_scrub, 1, &zopt_rarely },
|
||||
{ ztest_spa_upgrade, 1, &zopt_rarely },
|
||||
{ ztest_dsl_dataset_promote_busy, 1, &zopt_rarely },
|
||||
{ ztest_vdev_attach_detach, 1, &zopt_rarely },
|
||||
{ ztest_vdev_attach_detach, 1, &zopt_sometimes },
|
||||
{ ztest_vdev_LUN_growth, 1, &zopt_rarely },
|
||||
{ ztest_vdev_add_remove, 1,
|
||||
&ztest_opts.zo_vdevtime },
|
||||
@@ -1031,9 +1033,8 @@ ztest_dsl_prop_set_uint64(char *osname, zfs_prop_t prop, uint64_t value,
|
||||
uint64_t curval;
|
||||
int error;
|
||||
|
||||
error = dsl_prop_set(osname, propname,
|
||||
(inherit ? ZPROP_SRC_NONE : ZPROP_SRC_LOCAL),
|
||||
sizeof (value), 1, &value);
|
||||
error = dsl_prop_set_int(osname, propname,
|
||||
(inherit ? ZPROP_SRC_NONE : ZPROP_SRC_LOCAL), value);
|
||||
|
||||
if (error == ENOSPC) {
|
||||
ztest_record_enospc(FTAG);
|
||||
@@ -1042,8 +1043,7 @@ ztest_dsl_prop_set_uint64(char *osname, zfs_prop_t prop, uint64_t value,
|
||||
ASSERT0(error);
|
||||
|
||||
setpoint = umem_alloc(MAXPATHLEN, UMEM_NOFAIL);
|
||||
VERIFY3U(dsl_prop_get(osname, propname, sizeof (curval),
|
||||
1, &curval, setpoint), ==, 0);
|
||||
VERIFY0(dsl_prop_get_integer(osname, propname, &curval, setpoint));
|
||||
|
||||
if (ztest_opts.zo_verbose >= 6) {
|
||||
VERIFY(zfs_prop_index_to_string(prop, curval, &valname) == 0);
|
||||
@@ -2484,8 +2484,7 @@ ztest_vdev_add_remove(ztest_ds_t *zd, uint64_t id)
|
||||
int error;
|
||||
|
||||
mutex_enter(&ztest_vdev_lock);
|
||||
leaves =
|
||||
MAX(zs->zs_mirrors + zs->zs_splits, 1) * ztest_opts.zo_raidz;
|
||||
leaves = MAX(zs->zs_mirrors + zs->zs_splits, 1) * ztest_opts.zo_raidz;
|
||||
|
||||
spa_config_enter(spa, SCL_VDEV, FTAG, RW_READER);
|
||||
|
||||
@@ -2507,7 +2506,7 @@ ztest_vdev_add_remove(ztest_ds_t *zd, uint64_t id)
|
||||
* prevent a race between removing a slog (dmu_objset_find)
|
||||
* and destroying a dataset. Removing the slog will
|
||||
* grab a reference on the dataset which may cause
|
||||
* dmu_objset_destroy() to fail with EBUSY thus
|
||||
* dsl_destroy_head() to fail with EBUSY thus
|
||||
* leaving the dataset in an inconsistent state.
|
||||
*/
|
||||
rw_enter(&ztest_name_lock, RW_WRITER);
|
||||
@@ -3196,7 +3195,7 @@ ztest_objset_destroy_cb(const char *name, void *arg)
|
||||
/*
|
||||
* Verify that the dataset contains a directory object.
|
||||
*/
|
||||
VERIFY3U(0, ==, dmu_objset_hold(name, FTAG, &os));
|
||||
VERIFY0(dmu_objset_own(name, DMU_OST_OTHER, B_TRUE, FTAG, &os));
|
||||
error = dmu_object_info(os, ZTEST_DIROBJ, &doi);
|
||||
if (error != ENOENT) {
|
||||
/* We could have crashed in the middle of destroying it */
|
||||
@@ -3204,12 +3203,16 @@ ztest_objset_destroy_cb(const char *name, void *arg)
|
||||
ASSERT3U(doi.doi_type, ==, DMU_OT_ZAP_OTHER);
|
||||
ASSERT3S(doi.doi_physical_blocks_512, >=, 0);
|
||||
}
|
||||
dmu_objset_rele(os, FTAG);
|
||||
dmu_objset_disown(os, FTAG);
|
||||
|
||||
/*
|
||||
* Destroy the dataset.
|
||||
*/
|
||||
VERIFY3U(0, ==, dmu_objset_destroy(name, B_FALSE));
|
||||
if (strchr(name, '@') != NULL) {
|
||||
VERIFY0(dsl_destroy_snapshot(name, B_FALSE));
|
||||
} else {
|
||||
VERIFY0(dsl_destroy_head(name));
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -3219,16 +3222,17 @@ ztest_snapshot_create(char *osname, uint64_t id)
|
||||
char snapname[MAXNAMELEN];
|
||||
int error;
|
||||
|
||||
(void) snprintf(snapname, MAXNAMELEN, "%s@%llu", osname,
|
||||
(u_longlong_t)id);
|
||||
(void) snprintf(snapname, sizeof (snapname), "%llu", (u_longlong_t)id);
|
||||
|
||||
error = dmu_objset_snapshot_one(osname, strchr(snapname, '@') + 1);
|
||||
error = dmu_objset_snapshot_one(osname, snapname);
|
||||
if (error == ENOSPC) {
|
||||
ztest_record_enospc(FTAG);
|
||||
return (B_FALSE);
|
||||
}
|
||||
if (error != 0 && error != EEXIST)
|
||||
fatal(0, "ztest_snapshot_create(%s) = %d", snapname, error);
|
||||
if (error != 0 && error != EEXIST) {
|
||||
fatal(0, "ztest_snapshot_create(%s@%s) = %d", osname,
|
||||
snapname, error);
|
||||
}
|
||||
return (B_TRUE);
|
||||
}
|
||||
|
||||
@@ -3241,7 +3245,7 @@ ztest_snapshot_destroy(char *osname, uint64_t id)
|
||||
(void) snprintf(snapname, MAXNAMELEN, "%s@%llu", osname,
|
||||
(u_longlong_t)id);
|
||||
|
||||
error = dmu_objset_destroy(snapname, B_FALSE);
|
||||
error = dsl_destroy_snapshot(snapname, B_FALSE);
|
||||
if (error != 0 && error != ENOENT)
|
||||
fatal(0, "ztest_snapshot_destroy(%s) = %d", snapname, error);
|
||||
return (B_TRUE);
|
||||
@@ -3269,7 +3273,7 @@ ztest_dmu_objset_create_destroy(ztest_ds_t *zd, uint64_t id)
|
||||
|
||||
/*
|
||||
* If this dataset exists from a previous run, process its replay log
|
||||
* half of the time. If we don't replay it, then dmu_objset_destroy()
|
||||
* half of the time. If we don't replay it, then dsl_destroy_head()
|
||||
* (invoked from ztest_objset_destroy_cb()) should just throw it away.
|
||||
*/
|
||||
if (ztest_random(2) == 0 &&
|
||||
@@ -3291,7 +3295,8 @@ ztest_dmu_objset_create_destroy(ztest_ds_t *zd, uint64_t id)
|
||||
/*
|
||||
* Verify that the destroyed dataset is no longer in the namespace.
|
||||
*/
|
||||
VERIFY3U(ENOENT, ==, dmu_objset_hold(name, FTAG, &os));
|
||||
VERIFY3U(ENOENT, ==, dmu_objset_own(name, DMU_OST_OTHER, B_TRUE,
|
||||
FTAG, &os));
|
||||
|
||||
/*
|
||||
* Verify that we can create a new dataset.
|
||||
@@ -3305,8 +3310,7 @@ ztest_dmu_objset_create_destroy(ztest_ds_t *zd, uint64_t id)
|
||||
fatal(0, "dmu_objset_create(%s) = %d", name, error);
|
||||
}
|
||||
|
||||
VERIFY3U(0, ==,
|
||||
dmu_objset_own(name, DMU_OST_OTHER, B_FALSE, FTAG, &os));
|
||||
VERIFY0(dmu_objset_own(name, DMU_OST_OTHER, B_FALSE, FTAG, &os));
|
||||
|
||||
ztest_zd_init(zdtmp, NULL, os);
|
||||
|
||||
@@ -3396,21 +3400,21 @@ ztest_dsl_dataset_cleanup(char *osname, uint64_t id)
|
||||
(void) snprintf(snap3name, MAXNAMELEN, "%s@s3_%llu",
|
||||
clone1name, (u_longlong_t)id);
|
||||
|
||||
error = dmu_objset_destroy(clone2name, B_FALSE);
|
||||
error = dsl_destroy_head(clone2name);
|
||||
if (error && error != ENOENT)
|
||||
fatal(0, "dmu_objset_destroy(%s) = %d", clone2name, error);
|
||||
error = dmu_objset_destroy(snap3name, B_FALSE);
|
||||
fatal(0, "dsl_destroy_head(%s) = %d", clone2name, error);
|
||||
error = dsl_destroy_snapshot(snap3name, B_FALSE);
|
||||
if (error && error != ENOENT)
|
||||
fatal(0, "dmu_objset_destroy(%s) = %d", snap3name, error);
|
||||
error = dmu_objset_destroy(snap2name, B_FALSE);
|
||||
fatal(0, "dsl_destroy_snapshot(%s) = %d", snap3name, error);
|
||||
error = dsl_destroy_snapshot(snap2name, B_FALSE);
|
||||
if (error && error != ENOENT)
|
||||
fatal(0, "dmu_objset_destroy(%s) = %d", snap2name, error);
|
||||
error = dmu_objset_destroy(clone1name, B_FALSE);
|
||||
fatal(0, "dsl_destroy_snapshot(%s) = %d", snap2name, error);
|
||||
error = dsl_destroy_head(clone1name);
|
||||
if (error && error != ENOENT)
|
||||
fatal(0, "dmu_objset_destroy(%s) = %d", clone1name, error);
|
||||
error = dmu_objset_destroy(snap1name, B_FALSE);
|
||||
fatal(0, "dsl_destroy_head(%s) = %d", clone1name, error);
|
||||
error = dsl_destroy_snapshot(snap1name, B_FALSE);
|
||||
if (error && error != ENOENT)
|
||||
fatal(0, "dmu_objset_destroy(%s) = %d", snap1name, error);
|
||||
fatal(0, "dsl_destroy_snapshot(%s) = %d", snap1name, error);
|
||||
|
||||
umem_free(snap1name, MAXNAMELEN);
|
||||
umem_free(clone1name, MAXNAMELEN);
|
||||
@@ -3425,8 +3429,7 @@ ztest_dsl_dataset_cleanup(char *osname, uint64_t id)
|
||||
void
|
||||
ztest_dsl_dataset_promote_busy(ztest_ds_t *zd, uint64_t id)
|
||||
{
|
||||
objset_t *clone;
|
||||
dsl_dataset_t *ds;
|
||||
objset_t *os;
|
||||
char *snap1name;
|
||||
char *clone1name;
|
||||
char *snap2name;
|
||||
@@ -3465,12 +3468,7 @@ ztest_dsl_dataset_promote_busy(ztest_ds_t *zd, uint64_t id)
|
||||
fatal(0, "dmu_take_snapshot(%s) = %d", snap1name, error);
|
||||
}
|
||||
|
||||
error = dmu_objset_hold(snap1name, FTAG, &clone);
|
||||
if (error)
|
||||
fatal(0, "dmu_open_snapshot(%s) = %d", snap1name, error);
|
||||
|
||||
error = dmu_objset_clone(clone1name, dmu_objset_ds(clone), 0);
|
||||
dmu_objset_rele(clone, FTAG);
|
||||
error = dmu_objset_clone(clone1name, snap1name);
|
||||
if (error) {
|
||||
if (error == ENOSPC) {
|
||||
ztest_record_enospc(FTAG);
|
||||
@@ -3497,12 +3495,7 @@ ztest_dsl_dataset_promote_busy(ztest_ds_t *zd, uint64_t id)
|
||||
fatal(0, "dmu_open_snapshot(%s) = %d", snap3name, error);
|
||||
}
|
||||
|
||||
error = dmu_objset_hold(snap3name, FTAG, &clone);
|
||||
if (error)
|
||||
fatal(0, "dmu_open_snapshot(%s) = %d", snap3name, error);
|
||||
|
||||
error = dmu_objset_clone(clone2name, dmu_objset_ds(clone), 0);
|
||||
dmu_objset_rele(clone, FTAG);
|
||||
error = dmu_objset_clone(clone2name, snap3name);
|
||||
if (error) {
|
||||
if (error == ENOSPC) {
|
||||
ztest_record_enospc(FTAG);
|
||||
@@ -3511,14 +3504,14 @@ ztest_dsl_dataset_promote_busy(ztest_ds_t *zd, uint64_t id)
|
||||
fatal(0, "dmu_objset_create(%s) = %d", clone2name, error);
|
||||
}
|
||||
|
||||
error = dsl_dataset_own(snap2name, B_FALSE, FTAG, &ds);
|
||||
error = dmu_objset_own(snap2name, DMU_OST_ANY, B_TRUE, FTAG, &os);
|
||||
if (error)
|
||||
fatal(0, "dsl_dataset_own(%s) = %d", snap2name, error);
|
||||
fatal(0, "dmu_objset_own(%s) = %d", snap2name, error);
|
||||
error = dsl_dataset_promote(clone2name, NULL);
|
||||
if (error != EBUSY)
|
||||
fatal(0, "dsl_dataset_promote(%s), %d, not EBUSY", clone2name,
|
||||
error);
|
||||
dsl_dataset_disown(ds, FTAG);
|
||||
dmu_objset_disown(os, FTAG);
|
||||
|
||||
out:
|
||||
ztest_dsl_dataset_cleanup(osname, id);
|
||||
@@ -4392,7 +4385,7 @@ ztest_zap_parallel(ztest_ds_t *zd, uint64_t id)
|
||||
}
|
||||
|
||||
count = -1ULL;
|
||||
VERIFY(zap_count(os, object, &count) == 0);
|
||||
VERIFY0(zap_count(os, object, &count));
|
||||
ASSERT(count != -1ULL);
|
||||
|
||||
/*
|
||||
@@ -4710,6 +4703,22 @@ ztest_spa_prop_get_set(ztest_ds_t *zd, uint64_t id)
|
||||
(void) rw_exit(&ztest_name_lock);
|
||||
}
|
||||
|
||||
static int
|
||||
user_release_one(const char *snapname, const char *holdname)
|
||||
{
|
||||
nvlist_t *snaps, *holds;
|
||||
int error;
|
||||
|
||||
snaps = fnvlist_alloc();
|
||||
holds = fnvlist_alloc();
|
||||
fnvlist_add_boolean(holds, holdname);
|
||||
fnvlist_add_nvlist(snaps, snapname, holds);
|
||||
fnvlist_free(holds);
|
||||
error = dsl_dataset_user_release(snaps, NULL);
|
||||
fnvlist_free(snaps);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test snapshot hold/release and deferred destroy.
|
||||
*/
|
||||
@@ -4724,22 +4733,30 @@ ztest_dmu_snapshot_hold(ztest_ds_t *zd, uint64_t id)
|
||||
char clonename[100];
|
||||
char tag[100];
|
||||
char osname[MAXNAMELEN];
|
||||
nvlist_t *holds;
|
||||
|
||||
(void) rw_enter(&ztest_name_lock, RW_READER);
|
||||
|
||||
dmu_objset_name(os, osname);
|
||||
|
||||
(void) snprintf(snapname, 100, "sh1_%llu", (u_longlong_t)id);
|
||||
(void) snprintf(fullname, 100, "%s@%s", osname, snapname);
|
||||
(void) snprintf(clonename, 100, "%s/ch1_%llu",osname,(u_longlong_t)id);
|
||||
(void) snprintf(tag, 100, "tag_%llu", (u_longlong_t)id);
|
||||
(void) snprintf(snapname, sizeof (snapname), "sh1_%llu", (long long unsigned int)id);
|
||||
(void) snprintf(fullname, sizeof (fullname), "%s@%s", osname, snapname);
|
||||
(void) snprintf(clonename, sizeof (clonename),
|
||||
"%s/ch1_%llu", osname, (long long unsigned int)id);
|
||||
(void) snprintf(tag, sizeof (tag), "tag_%llu", (long long unsigned int)id);
|
||||
|
||||
/*
|
||||
* Clean up from any previous run.
|
||||
*/
|
||||
(void) dmu_objset_destroy(clonename, B_FALSE);
|
||||
(void) dsl_dataset_user_release(osname, snapname, tag, B_FALSE);
|
||||
(void) dmu_objset_destroy(fullname, B_FALSE);
|
||||
error = dsl_destroy_head(clonename);
|
||||
if (error != ENOENT)
|
||||
ASSERT0(error);
|
||||
error = user_release_one(fullname, tag);
|
||||
if (error != ESRCH && error != ENOENT)
|
||||
ASSERT0(error);
|
||||
error = dsl_destroy_snapshot(fullname, B_FALSE);
|
||||
if (error != ENOENT)
|
||||
ASSERT0(error);
|
||||
|
||||
/*
|
||||
* Create snapshot, clone it, mark snap for deferred destroy,
|
||||
@@ -4754,12 +4771,7 @@ ztest_dmu_snapshot_hold(ztest_ds_t *zd, uint64_t id)
|
||||
fatal(0, "dmu_objset_snapshot(%s) = %d", fullname, error);
|
||||
}
|
||||
|
||||
error = dmu_objset_hold(fullname, FTAG, &origin);
|
||||
if (error)
|
||||
fatal(0, "dmu_objset_hold(%s) = %d", fullname, error);
|
||||
|
||||
error = dmu_objset_clone(clonename, dmu_objset_ds(origin), 0);
|
||||
dmu_objset_rele(origin, FTAG);
|
||||
error = dmu_objset_clone(clonename, fullname);
|
||||
if (error) {
|
||||
if (error == ENOSPC) {
|
||||
ztest_record_enospc("dmu_objset_clone");
|
||||
@@ -4768,15 +4780,15 @@ ztest_dmu_snapshot_hold(ztest_ds_t *zd, uint64_t id)
|
||||
fatal(0, "dmu_objset_clone(%s) = %d", clonename, error);
|
||||
}
|
||||
|
||||
error = dmu_objset_destroy(fullname, B_TRUE);
|
||||
error = dsl_destroy_snapshot(fullname, B_TRUE);
|
||||
if (error) {
|
||||
fatal(0, "dmu_objset_destroy(%s, B_TRUE) = %d",
|
||||
fatal(0, "dsl_destroy_snapshot(%s, B_TRUE) = %d",
|
||||
fullname, error);
|
||||
}
|
||||
|
||||
error = dmu_objset_destroy(clonename, B_FALSE);
|
||||
error = dsl_destroy_head(clonename);
|
||||
if (error)
|
||||
fatal(0, "dmu_objset_destroy(%s) = %d", clonename, error);
|
||||
fatal(0, "dsl_destroy_head(%s) = %d", clonename, error);
|
||||
|
||||
error = dmu_objset_hold(fullname, FTAG, &origin);
|
||||
if (error != ENOENT)
|
||||
@@ -4796,28 +4808,31 @@ ztest_dmu_snapshot_hold(ztest_ds_t *zd, uint64_t id)
|
||||
fatal(0, "dmu_objset_snapshot(%s) = %d", fullname, error);
|
||||
}
|
||||
|
||||
error = dsl_dataset_user_hold(osname, snapname, tag, B_FALSE,
|
||||
B_TRUE, -1);
|
||||
holds = fnvlist_alloc();
|
||||
fnvlist_add_string(holds, fullname, tag);
|
||||
error = dsl_dataset_user_hold(holds, 0, NULL);
|
||||
fnvlist_free(holds);
|
||||
|
||||
if (error)
|
||||
fatal(0, "dsl_dataset_user_hold(%s)", fullname, tag);
|
||||
|
||||
error = dmu_objset_destroy(fullname, B_FALSE);
|
||||
error = dsl_destroy_snapshot(fullname, B_FALSE);
|
||||
if (error != EBUSY) {
|
||||
fatal(0, "dmu_objset_destroy(%s, B_FALSE) = %d",
|
||||
fatal(0, "dsl_destroy_snapshot(%s, B_FALSE) = %d",
|
||||
fullname, error);
|
||||
}
|
||||
|
||||
error = dmu_objset_destroy(fullname, B_TRUE);
|
||||
error = dsl_destroy_snapshot(fullname, B_TRUE);
|
||||
if (error) {
|
||||
fatal(0, "dmu_objset_destroy(%s, B_TRUE) = %d",
|
||||
fatal(0, "dsl_destroy_snapshot(%s, B_TRUE) = %d",
|
||||
fullname, error);
|
||||
}
|
||||
|
||||
error = dsl_dataset_user_release(osname, snapname, tag, B_FALSE);
|
||||
error = user_release_one(fullname, tag);
|
||||
if (error)
|
||||
fatal(0, "dsl_dataset_user_release(%s)", fullname, tag);
|
||||
fatal(0, "user_release_one(%s)", fullname, tag);
|
||||
|
||||
VERIFY(dmu_objset_hold(fullname, FTAG, &origin) == ENOENT);
|
||||
VERIFY3U(dmu_objset_hold(fullname, FTAG, &origin), ==, ENOENT);
|
||||
|
||||
out:
|
||||
(void) rw_exit(&ztest_name_lock);
|
||||
@@ -4947,7 +4962,7 @@ ztest_fault_inject(ztest_ds_t *zd, uint64_t id)
|
||||
* prevent a race between offlining a slog and
|
||||
* destroying a dataset. Offlining the slog will
|
||||
* grab a reference on the dataset which may cause
|
||||
* dmu_objset_destroy() to fail with EBUSY thus
|
||||
* dsl_destroy_head() to fail with EBUSY thus
|
||||
* leaving the dataset in an inconsistent state.
|
||||
*/
|
||||
if (islog)
|
||||
@@ -5084,8 +5099,12 @@ ztest_ddt_repair(ztest_ds_t *zd, uint64_t id)
|
||||
*/
|
||||
for (i = 0; i < copies; i++) {
|
||||
uint64_t offset = i * blocksize;
|
||||
VERIFY(dmu_buf_hold(os, object, offset, FTAG, &db,
|
||||
DMU_READ_NO_PREFETCH) == 0);
|
||||
int error = dmu_buf_hold(os, object, offset, FTAG, &db,
|
||||
DMU_READ_NO_PREFETCH);
|
||||
if (error != 0) {
|
||||
fatal(B_FALSE, "dmu_buf_hold(%p, %llu, %llu) = %u",
|
||||
os, (long long)object, (long long) offset, error);
|
||||
}
|
||||
ASSERT(db->db_offset == offset);
|
||||
ASSERT(db->db_size == blocksize);
|
||||
ASSERT(ztest_pattern_match(db->db_data, db->db_size, pattern) ||
|
||||
@@ -5300,6 +5319,7 @@ ztest_spa_import_export(char *oldname, char *newname)
|
||||
nvlist_t *config, *newconfig;
|
||||
uint64_t pool_guid;
|
||||
spa_t *spa;
|
||||
int error;
|
||||
|
||||
if (ztest_opts.zo_verbose >= 4) {
|
||||
(void) printf("import/export: old = %s, new = %s\n",
|
||||
@@ -5344,7 +5364,12 @@ ztest_spa_import_export(char *oldname, char *newname)
|
||||
/*
|
||||
* Import it under the new name.
|
||||
*/
|
||||
VERIFY3U(0, ==, spa_import(newname, config, NULL, 0));
|
||||
error = spa_import(newname, config, NULL, 0);
|
||||
if (error != 0) {
|
||||
dump_nvlist(config, 0);
|
||||
fatal(B_FALSE, "couldn't import pool %s as %s: error %u",
|
||||
oldname, newname, error);
|
||||
}
|
||||
|
||||
ztest_walk_pool_directory("pools after import");
|
||||
|
||||
@@ -5551,7 +5576,7 @@ ztest_dataset_open(int d)
|
||||
}
|
||||
ASSERT(error == 0 || error == EEXIST);
|
||||
|
||||
VERIFY0(dmu_objset_hold(name, zd, &os));
|
||||
VERIFY0(dmu_objset_own(name, DMU_OST_OTHER, B_FALSE, zd, &os));
|
||||
(void) rw_exit(&ztest_name_lock);
|
||||
|
||||
ztest_zd_init(zd, ZTEST_GET_SHARED_DS(d), os);
|
||||
@@ -5592,7 +5617,7 @@ ztest_dataset_close(int d)
|
||||
ztest_ds_t *zd = &ztest_ds[d];
|
||||
|
||||
zil_close(zd->zd_zilog);
|
||||
dmu_objset_rele(zd->zd_os, zd);
|
||||
dmu_objset_disown(zd->zd_os, zd);
|
||||
|
||||
ztest_zd_fini(zd);
|
||||
}
|
||||
@@ -5638,13 +5663,14 @@ ztest_run(ztest_shared_t *zs)
|
||||
* Open our pool.
|
||||
*/
|
||||
kernel_init(FREAD | FWRITE);
|
||||
VERIFY(spa_open(ztest_opts.zo_pool, &spa, FTAG) == 0);
|
||||
VERIFY0(spa_open(ztest_opts.zo_pool, &spa, FTAG));
|
||||
spa->spa_debug = B_TRUE;
|
||||
ztest_spa = spa;
|
||||
|
||||
VERIFY3U(0, ==, dmu_objset_hold(ztest_opts.zo_pool, FTAG, &os));
|
||||
VERIFY0(dmu_objset_own(ztest_opts.zo_pool,
|
||||
DMU_OST_ANY, B_TRUE, FTAG, &os));
|
||||
zs->zs_guid = dmu_objset_fsid_guid(os);
|
||||
dmu_objset_rele(os, FTAG);
|
||||
dmu_objset_disown(os, FTAG);
|
||||
|
||||
spa->spa_dedup_ditto = 2 * ZIO_DEDUPDITTO_MIN;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user