From owner-svn-src-projects@FreeBSD.ORG Tue Mar 19 12:51:20 2013 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.FreeBSD.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id 03A2EA00; Tue, 19 Mar 2013 12:51:20 +0000 (UTC) (envelope-from mm@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id E1CF2106; Tue, 19 Mar 2013 12:51:19 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.6/8.14.6) with ESMTP id r2JCpJuN084282; Tue, 19 Mar 2013 12:51:19 GMT (envelope-from mm@svn.freebsd.org) Received: (from mm@localhost) by svn.freebsd.org (8.14.6/8.14.5/Submit) id r2JCpIfA084273; Tue, 19 Mar 2013 12:51:18 GMT (envelope-from mm@svn.freebsd.org) Message-Id: <201303191251.r2JCpIfA084273@svn.freebsd.org> From: Martin Matuska Date: Tue, 19 Mar 2013 12:51:18 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r248498 - in projects/libzfs_core: cddl/contrib/opensolaris/cmd/zdb cddl/contrib/opensolaris/cmd/zfs cddl/contrib/opensolaris/cmd/zhack cddl/contrib/opensolaris/cmd/ztest cddl/contrib/o... X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 19 Mar 2013 12:51:20 -0000 Author: mm Date: Tue Mar 19 12:51:18 2013 New Revision: 248498 URL: http://svnweb.freebsd.org/changeset/base/248498 Log: MFV r247580: Merge synctask code restructuring from vendor. Modify forward and backward compatibility to support new change. Illumos ZFS issues: 3464 zfs synctask code needs restructuring Sponsored by: Hybrid Logic Ltd. Added: projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_destroy.c - copied unchanged from r247580, vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_destroy.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_userhold.c - copied unchanged from r247580, vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_userhold.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu_send.h - copied, changed from r247580, vendor-sys/illumos/dist/uts/common/fs/zfs/sys/dmu_send.h projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_destroy.h - copied unchanged from r247580, vendor-sys/illumos/dist/uts/common/fs/zfs/sys/dsl_destroy.h projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_userhold.h - copied unchanged from r247580, vendor-sys/illumos/dist/uts/common/fs/zfs/sys/dsl_userhold.h Modified: projects/libzfs_core/cddl/contrib/opensolaris/cmd/zdb/zdb.c projects/libzfs_core/cddl/contrib/opensolaris/cmd/zfs/zfs.8 projects/libzfs_core/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c projects/libzfs_core/cddl/contrib/opensolaris/cmd/zhack/zhack.c projects/libzfs_core/cddl/contrib/opensolaris/cmd/ztest/ztest.c projects/libzfs_core/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h projects/libzfs_core/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c projects/libzfs_core/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c projects/libzfs_core/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c projects/libzfs_core/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.h projects/libzfs_core/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core_compat.c projects/libzfs_core/cddl/contrib/opensolaris/lib/libzpool/common/kernel.c projects/libzfs_core/cddl/contrib/opensolaris/lib/libzpool/common/sys/zfs_context.h projects/libzfs_core/sys/cddl/contrib/opensolaris/common/nvpair/fnvpair.c projects/libzfs_core/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c projects/libzfs_core/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.h projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/Makefile.files projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bplist.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bpobj.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_diff.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_tx.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_deleg.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dir.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_prop.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_synctask.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/refcount.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/rrwlock.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sa.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_history.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/space_map.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/arc.h projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dbuf.h projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu_objset.h projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu_tx.h projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dir.h projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_pool.h projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_prop.h projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_synctask.h projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/metaslab.h projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/refcount.h projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/rrwlock.h projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/space_map.h projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/txg.h projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfeature.h projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_debug.h projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_ioctl.h projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zil.h projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/txg.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/sys/nvpair.h Directory Properties: projects/libzfs_core/cddl/contrib/opensolaris/ (props changed) projects/libzfs_core/cddl/contrib/opensolaris/cmd/zfs/ (props changed) projects/libzfs_core/cddl/contrib/opensolaris/lib/libzfs/ (props changed) projects/libzfs_core/sys/cddl/contrib/opensolaris/ (props changed) Modified: projects/libzfs_core/cddl/contrib/opensolaris/cmd/zdb/zdb.c ============================================================================== --- projects/libzfs_core/cddl/contrib/opensolaris/cmd/zdb/zdb.c Tue Mar 19 12:42:14 2013 (r248497) +++ projects/libzfs_core/cddl/contrib/opensolaris/cmd/zdb/zdb.c Tue Mar 19 12:51:18 2013 (r248498) @@ -1692,7 +1692,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]; @@ -2101,7 +2103,6 @@ zdb_blkptr_cb(spa_t *spa, zilog_t *zilog NULL, NULL, ZIO_PRIORITY_ASYNC_READ, flags, zb)); free(data); - if (ioerr && !(flags & ZIO_FLAG_SPECULATIVE)) { zcb->zcb_haderrors = 1; zcb->zcb_errors[ioerr]++; Modified: projects/libzfs_core/cddl/contrib/opensolaris/cmd/zfs/zfs.8 ============================================================================== --- projects/libzfs_core/cddl/contrib/opensolaris/cmd/zfs/zfs.8 Tue Mar 19 12:42:14 2013 (r248497) +++ projects/libzfs_core/cddl/contrib/opensolaris/cmd/zfs/zfs.8 Tue Mar 19 12:51:18 2013 (r248498) @@ -1618,7 +1618,11 @@ multiple snapshots. Destroy (or mark for deferred deletion) all snapshots with this name in descendent file systems. .It Fl R -Recursively destroy all dependents. +Recursively destroy all clones of these snapshots, including the clones, +snapshots, and children. +If this flag is specified, the +.Op fl d +flag will have no effect. .It Fl n Do a dry-run ("No-op") deletion. No data will be deleted. This is useful in conjunction with the Modified: projects/libzfs_core/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c ============================================================================== --- projects/libzfs_core/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c Tue Mar 19 12:42:14 2013 (r248497) +++ projects/libzfs_core/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c Tue Mar 19 12:51:18 2013 (r248498) @@ -916,6 +916,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; @@ -1012,9 +1013,27 @@ destroy_callback(zfs_handle_t *zhp, void zfs_close(zhp); return (0); } + if (cb->cb_dryrun) { + zfs_close(zhp); + return (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 (!cb->cb_dryrun) { - if (zfs_unmount(zhp, NULL, cb->cb_force ? MS_FORCE : 0) != 0 || + 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); @@ -1170,8 +1189,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; @@ -1225,11 +1246,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], @@ -1240,17 +1259,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) { @@ -1269,18 +1286,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) @@ -1301,8 +1326,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; } /* @@ -1312,30 +1337,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 @@ -5121,28 +5158,12 @@ cleanup2: return (error); } -/* - * zfs allow [-r] [-t] ... - * - * -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] ... - * - * -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) { @@ -5156,7 +5177,6 @@ zfs_do_hold_rele_impl(int argc, char **a int i; const char *tag; boolean_t recursive = B_FALSE; - boolean_t temphold = B_FALSE; const char *opts = holding ? "rt" : "r"; int c; @@ -5166,9 +5186,6 @@ zfs_do_hold_rele_impl(int argc, char **a case 'r': recursive = B_TRUE; break; - case 't': - temphold = B_TRUE; - break; case '?': (void) fprintf(stderr, gettext("invalid option '%c'\n"), optopt); @@ -5217,7 +5234,7 @@ zfs_do_hold_rele_impl(int argc, char **a } 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) @@ -5233,7 +5250,6 @@ zfs_do_hold_rele_impl(int argc, char **a * zfs hold [-r] [-t] ... * * -r Recursively hold - * -t Temporary hold (hidden option) * * Apply a user-hold with the given tag to the list of snapshots. */ Modified: projects/libzfs_core/cddl/contrib/opensolaris/cmd/zhack/zhack.c ============================================================================== --- projects/libzfs_core/cddl/contrib/opensolaris/cmd/zhack/zhack.c Tue Mar 19 12:42:14 2013 (r248497) +++ projects/libzfs_core/cddl/contrib/opensolaris/cmd/zhack/zhack.c Tue Mar 19 12:51:18 2013 (r248498) @@ -46,6 +46,7 @@ #include #include #include +#include #undef ZFS_MAXNAMELEN #undef verify #include @@ -273,10 +274,10 @@ zhack_do_feature_stat(int argc, char **a } 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 * 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 * } 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 } 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 **ar 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); } Modified: projects/libzfs_core/cddl/contrib/opensolaris/cmd/ztest/ztest.c ============================================================================== --- projects/libzfs_core/cddl/contrib/opensolaris/cmd/ztest/ztest.c Tue Mar 19 12:42:14 2013 (r248497) +++ projects/libzfs_core/cddl/contrib/opensolaris/cmd/ztest/ztest.c Tue Mar 19 12:51:18 2013 (r248498) @@ -104,10 +104,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -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 }, @@ -1008,9 +1010,8 @@ ztest_dsl_prop_set_uint64(char *osname, 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); @@ -1018,8 +1019,7 @@ ztest_dsl_prop_set_uint64(char *osname, } ASSERT0(error); - 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); @@ -2481,8 +2481,7 @@ ztest_vdev_add_remove(ztest_ds_t *zd, ui int error; VERIFY(mutex_lock(&ztest_vdev_lock) == 0); - 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); @@ -3182,7 +3181,7 @@ ztest_objset_destroy_cb(const char *name /* * 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 */ @@ -3190,12 +3189,16 @@ ztest_objset_destroy_cb(const char *name 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); } @@ -3205,16 +3208,17 @@ ztest_snapshot_create(char *osname, uint 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); } @@ -3227,7 +3231,7 @@ ztest_snapshot_destroy(char *osname, uin (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); @@ -3273,7 +3277,8 @@ ztest_dmu_objset_create_destroy(ztest_ds /* * 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. @@ -3288,8 +3293,7 @@ ztest_dmu_objset_create_destroy(ztest_ds 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); @@ -3365,21 +3369,21 @@ ztest_dsl_dataset_cleanup(char *osname, (void) snprintf(clone2name, MAXNAMELEN, "%s/c2_%llu", osname, id); (void) snprintf(snap3name, MAXNAMELEN, "%s@s3_%llu", clone1name, 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); } /* @@ -3388,8 +3392,7 @@ ztest_dsl_dataset_cleanup(char *osname, 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[MAXNAMELEN]; char clone1name[MAXNAMELEN]; char snap2name[MAXNAMELEN]; @@ -3417,12 +3420,7 @@ ztest_dsl_dataset_promote_busy(ztest_ds_ 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); @@ -3449,12 +3447,7 @@ ztest_dsl_dataset_promote_busy(ztest_ds_ 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); @@ -3463,14 +3456,14 @@ ztest_dsl_dataset_promote_busy(ztest_ds_ 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); @@ -4282,7 +4275,7 @@ ztest_zap_parallel(ztest_ds_t *zd, uint6 } count = -1ULL; - VERIFY(zap_count(os, object, &count) == 0); + VERIFY0(zap_count(os, object, &count)); ASSERT(count != -1ULL); /* @@ -4593,6 +4586,22 @@ ztest_spa_prop_get_set(ztest_ds_t *zd, u (void) rw_unlock(&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. */ @@ -4607,22 +4616,30 @@ ztest_dmu_snapshot_hold(ztest_ds_t *zd, char clonename[100]; char tag[100]; char osname[MAXNAMELEN]; + nvlist_t *holds; (void) rw_rdlock(&ztest_name_lock); dmu_objset_name(os, osname); - (void) snprintf(snapname, 100, "sh1_%llu", id); - (void) snprintf(fullname, 100, "%s@%s", osname, snapname); - (void) snprintf(clonename, 100, "%s/ch1_%llu", osname, id); - (void) snprintf(tag, 100, "%tag_%llu", id); + (void) snprintf(snapname, sizeof (snapname), "sh1_%llu", id); + (void) snprintf(fullname, sizeof (fullname), "%s@%s", osname, snapname); + (void) snprintf(clonename, sizeof (clonename), + "%s/ch1_%llu", osname, id); + (void) snprintf(tag, sizeof (tag), "tag_%llu", 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, @@ -4637,12 +4654,7 @@ ztest_dmu_snapshot_hold(ztest_ds_t *zd, 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"); @@ -4651,15 +4663,15 @@ ztest_dmu_snapshot_hold(ztest_ds_t *zd, 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) @@ -4679,28 +4691,31 @@ ztest_dmu_snapshot_hold(ztest_ds_t *zd, 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_unlock(&ztest_name_lock); @@ -4954,8 +4969,12 @@ ztest_ddt_repair(ztest_ds_t *zd, uint64_ */ for (int i = 0; i < copies; i++) { uint64_t offset = i * blocksize; - VERIFY0(dmu_buf_hold(os, object, offset, FTAG, &db, - DMU_READ_NO_PREFETCH)); + 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) || @@ -5166,6 +5185,7 @@ ztest_spa_import_export(char *oldname, c 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", @@ -5210,7 +5230,12 @@ ztest_spa_import_export(char *oldname, c /* * 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"); @@ -5417,7 +5442,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_unlock(&ztest_name_lock); ztest_zd_init(zd, ZTEST_GET_SHARED_DS(d), os); @@ -5458,7 +5483,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); } @@ -5502,13 +5527,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; Modified: projects/libzfs_core/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h ============================================================================== --- projects/libzfs_core/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h Tue Mar 19 12:42:14 2013 (r248497) +++ projects/libzfs_core/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h Tue Mar 19 12:51:18 2013 (r248498) @@ -554,7 +554,7 @@ extern int zfs_create(libzfs_handle_t *, extern int zfs_create_ancestors(libzfs_handle_t *, const char *); extern int zfs_destroy(zfs_handle_t *, boolean_t); extern int zfs_destroy_snaps(zfs_handle_t *, char *, boolean_t); -extern int zfs_destroy_snaps_nvl(zfs_handle_t *, nvlist_t *, boolean_t); +extern int zfs_destroy_snaps_nvl(libzfs_handle_t *, nvlist_t *, boolean_t); extern int zfs_clone(zfs_handle_t *, const char *, nvlist_t *); extern int zfs_snapshot(libzfs_handle_t *, const char *, boolean_t, nvlist_t *); extern int zfs_snapshot_nvl(libzfs_handle_t *hdl, nvlist_t *snaps, @@ -610,8 +610,8 @@ extern int zfs_send(zfs_handle_t *, cons sendflags_t *, int, snapfilter_cb_t, void *, nvlist_t **); extern int zfs_promote(zfs_handle_t *); -extern int zfs_hold(zfs_handle_t *, const char *, const char *, boolean_t, - boolean_t, boolean_t, int, uint64_t, uint64_t); +extern int zfs_hold(zfs_handle_t *, const char *, const char *, + boolean_t, boolean_t, int); extern int zfs_release(zfs_handle_t *, const char *, const char *, boolean_t); extern int zfs_get_holds(zfs_handle_t *, nvlist_t **); extern uint64_t zvol_volsize_to_reservation(uint64_t, nvlist_t *); Modified: projects/libzfs_core/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c ============================================================================== --- projects/libzfs_core/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c Tue Mar 19 12:42:14 2013 (r248497) +++ projects/libzfs_core/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c Tue Mar 19 12:51:18 2013 (r248498) @@ -2016,10 +2016,7 @@ get_clones_cb(zfs_handle_t *zhp, void *a NULL, NULL, 0, B_TRUE) != 0) goto out; if (strcmp(gca->buf, gca->origin) == 0) { - if (nvlist_add_boolean(gca->value, zfs_get_name(zhp)) != 0) { - zfs_close(zhp); - return (no_memory(zhp->zfs_hdl)); - } + fnvlist_add_boolean(gca->value, zfs_get_name(zhp)); gca->numclones--; } @@ -3197,45 +3194,49 @@ zfs_destroy_snaps(zfs_handle_t *zhp, cha dgettext(TEXT_DOMAIN, "cannot destroy '%s@%s'"), zhp->zfs_name, snapname); } else { - ret = zfs_destroy_snaps_nvl(zhp, dd.nvl, defer); + ret = zfs_destroy_snaps_nvl(zhp->zfs_hdl, dd.nvl, defer); } nvlist_free(dd.nvl); return (ret); } /* - * Destroys all the snapshots named in the nvlist. They must be underneath - * the zhp (either snapshots of it, or snapshots of its descendants). + * Destroys all the snapshots named in the nvlist. */ int -zfs_destroy_snaps_nvl(zfs_handle_t *zhp, nvlist_t *snaps, boolean_t defer) +zfs_destroy_snaps_nvl(libzfs_handle_t *hdl, nvlist_t *snaps, boolean_t defer) { int ret; nvlist_t *errlist; ret = lzc_destroy_snaps(snaps, defer, &errlist); - if (ret != 0) { - for (nvpair_t *pair = nvlist_next_nvpair(errlist, NULL); - pair != NULL; pair = nvlist_next_nvpair(errlist, pair)) { - char errbuf[1024]; - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, "cannot destroy snapshot %s"), - nvpair_name(pair)); + if (ret == 0) + return (0); - switch (fnvpair_value_int32(pair)) { - case EEXIST: - zfs_error_aux(zhp->zfs_hdl, - dgettext(TEXT_DOMAIN, - "snapshot is cloned")); - ret = zfs_error(zhp->zfs_hdl, EZFS_EXISTS, - errbuf); - break; - default: - ret = zfs_standard_error(zhp->zfs_hdl, errno, - errbuf); - break; - } + if (nvlist_next_nvpair(errlist, NULL) == NULL) { + char errbuf[1024]; + (void) snprintf(errbuf, sizeof (errbuf), + dgettext(TEXT_DOMAIN, "cannot destroy snapshots")); + + ret = zfs_standard_error(hdl, ret, errbuf); + } + for (nvpair_t *pair = nvlist_next_nvpair(errlist, NULL); + pair != NULL; pair = nvlist_next_nvpair(errlist, pair)) { + char errbuf[1024]; + (void) snprintf(errbuf, sizeof (errbuf), + dgettext(TEXT_DOMAIN, "cannot destroy snapshot %s"), + nvpair_name(pair)); + + switch (fnvpair_value_int32(pair)) { + case EEXIST: + zfs_error_aux(hdl, + dgettext(TEXT_DOMAIN, "snapshot is cloned")); + ret = zfs_error(hdl, EZFS_EXISTS, errbuf); + break; + default: + ret = zfs_standard_error(hdl, errno, errbuf); + break; } } @@ -4134,7 +4135,7 @@ zfs_userspace(zfs_handle_t *zhp, zfs_use zc.zc_nvlist_dst_size = sizeof (buf); if (zfs_ioctl(hdl, ZFS_IOC_USERSPACE_MANY, &zc) != 0) { - char errbuf[ZFS_MAXNAMELEN + 32]; + char errbuf[1024]; (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, @@ -4156,37 +4157,83 @@ zfs_userspace(zfs_handle_t *zhp, zfs_use return (0); } +struct holdarg { + nvlist_t *nvl; + const char *snapname; + const char *tag; + boolean_t recursive; +}; + +static int +zfs_hold_one(zfs_handle_t *zhp, void *arg) +{ + struct holdarg *ha = arg; + zfs_handle_t *szhp; + char name[ZFS_MAXNAMELEN]; + int rv = 0; + + (void) snprintf(name, sizeof (name), + "%s@%s", zhp->zfs_name, ha->snapname); + + szhp = make_dataset_handle(zhp->zfs_hdl, name); + if (szhp) { + fnvlist_add_string(ha->nvl, name, ha->tag); + zfs_close(szhp); + } + + if (ha->recursive) + rv = zfs_iter_filesystems(zhp, zfs_hold_one, ha); + zfs_close(zhp); + return (rv); +} + int zfs_hold(zfs_handle_t *zhp, const char *snapname, const char *tag, - boolean_t recursive, boolean_t temphold, boolean_t enoent_ok, - int cleanup_fd, uint64_t dsobj, uint64_t createtxg) + boolean_t recursive, boolean_t enoent_ok, int cleanup_fd) { - zfs_cmd_t zc = { 0 }; + int ret; + struct holdarg ha; + nvlist_t *errors; libzfs_handle_t *hdl = zhp->zfs_hdl; + char errbuf[1024]; + nvpair_t *elem; - ASSERT(!recursive || dsobj == 0); + ha.nvl = fnvlist_alloc(); + ha.snapname = snapname; + ha.tag = tag; + ha.recursive = recursive; + (void) zfs_hold_one(zfs_handle_dup(zhp), &ha); + ret = lzc_hold(ha.nvl, cleanup_fd, &errors); + fnvlist_free(ha.nvl); - (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); - (void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value)); - if (strlcpy(zc.zc_string, tag, sizeof (zc.zc_string)) - >= sizeof (zc.zc_string)) - return (zfs_error(hdl, EZFS_TAGTOOLONG, tag)); - zc.zc_cookie = recursive; - zc.zc_temphold = temphold; - zc.zc_cleanup_fd = cleanup_fd; - zc.zc_sendobj = dsobj; - zc.zc_createtxg = createtxg; + if (ret == 0) + return (0); - if (zfs_ioctl(hdl, ZFS_IOC_HOLD, &zc) != 0) { - char errbuf[ZFS_MAXNAMELEN+32]; + if (nvlist_next_nvpair(errors, NULL) == NULL) { + /* no hold-specific errors */ + (void) snprintf(errbuf, sizeof (errbuf), + dgettext(TEXT_DOMAIN, "cannot hold")); + switch (ret) { + case ENOTSUP: + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, + "pool must be upgraded")); + (void) zfs_error(hdl, EZFS_BADVERSION, errbuf); + break; + case EINVAL: + (void) zfs_error(hdl, EZFS_BADTYPE, errbuf); *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***