svn commit: r238583 - in vendor/illumos/dist: cmd/zdb cmd/zfs
cmd/zpool cmd/ztest lib/libnvpair lib/libuutil/common
lib/libzfs/common lib/libzpool/common lib/libzpool/common/sys
man/man1m
Martin Matuska
mm at FreeBSD.org
Wed Jul 18 10:19:51 UTC 2012
Author: mm
Date: Wed Jul 18 10:19:51 2012
New Revision: 238583
URL: http://svn.freebsd.org/changeset/base/238583
Log:
Update vendor/illumos/dist to pre libzfs_core state (zfs part)
illumos-gate revision 13742:b6bbdd77139c
Obtained from: ssh://anonhg@hg.illumos.org/illumos-gate
Added:
vendor/illumos/dist/lib/libzfs/common/libzfs_iter.c
Deleted:
vendor/illumos/dist/lib/libzfs/common/libzfs_graph.c
Modified:
vendor/illumos/dist/cmd/zdb/zdb.c
vendor/illumos/dist/cmd/zfs/zfs_main.c
vendor/illumos/dist/cmd/zpool/zpool_main.c
vendor/illumos/dist/cmd/ztest/ztest.c
vendor/illumos/dist/lib/libnvpair/libnvpair.c
vendor/illumos/dist/lib/libuutil/common/uu_list.c
vendor/illumos/dist/lib/libzfs/common/libzfs.h
vendor/illumos/dist/lib/libzfs/common/libzfs_config.c
vendor/illumos/dist/lib/libzfs/common/libzfs_dataset.c
vendor/illumos/dist/lib/libzfs/common/libzfs_impl.h
vendor/illumos/dist/lib/libzfs/common/libzfs_import.c
vendor/illumos/dist/lib/libzfs/common/libzfs_pool.c
vendor/illumos/dist/lib/libzfs/common/libzfs_sendrecv.c
vendor/illumos/dist/lib/libzfs/common/libzfs_status.c
vendor/illumos/dist/lib/libzfs/common/libzfs_util.c
vendor/illumos/dist/lib/libzpool/common/kernel.c
vendor/illumos/dist/lib/libzpool/common/sys/zfs_context.h
vendor/illumos/dist/lib/libzpool/common/taskq.c
vendor/illumos/dist/man/man1m/zdb.1m
vendor/illumos/dist/man/man1m/zfs.1m
vendor/illumos/dist/man/man1m/zpool.1m
vendor/illumos/dist/man/man1m/zstreamdump.1m
Modified: vendor/illumos/dist/cmd/zdb/zdb.c
==============================================================================
--- vendor/illumos/dist/cmd/zdb/zdb.c Wed Jul 18 10:19:06 2012 (r238582)
+++ vendor/illumos/dist/cmd/zdb/zdb.c Wed Jul 18 10:19:51 2012 (r238583)
@@ -18,8 +18,10 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
*/
#include <stdio.h>
@@ -54,6 +56,7 @@
#include <sys/zfs_fuid.h>
#include <sys/arc.h>
#include <sys/ddt.h>
+#include <sys/zfeature.h>
#undef ZFS_MAXNAMELEN
#undef verify
#include <libzfs.h>
@@ -63,7 +66,8 @@
#define ZDB_CHECKSUM_NAME(idx) ((idx) < ZIO_CHECKSUM_FUNCTIONS ? \
zio_checksum_table[(idx)].ci_name : "UNKNOWN")
#define ZDB_OT_NAME(idx) ((idx) < DMU_OT_NUMTYPES ? \
- dmu_ot[(idx)].ot_name : "UNKNOWN")
+ dmu_ot[(idx)].ot_name : DMU_OT_IS_VALID(idx) ? \
+ dmu_ot_byteswap[DMU_OT_BYTESWAP(idx)].ob_name : "UNKNOWN")
#define ZDB_OT_TYPE(idx) ((idx) < DMU_OT_NUMTYPES ? (idx) : DMU_OT_NUMTYPES)
#ifndef lint
@@ -102,13 +106,16 @@ static void
usage(void)
{
(void) fprintf(stderr,
- "Usage: %s [-CumdibcsDvhL] poolname [object...]\n"
- " %s [-div] dataset [object...]\n"
- " %s -m [-L] poolname [vdev [metaslab...]]\n"
- " %s -R poolname vdev:offset:size[:flags]\n"
- " %s -S poolname\n"
- " %s -l [-u] device\n"
- " %s -C\n\n",
+ "Usage: %s [-CumdibcsDvhLXFPA] [-t txg] [-e [-p path...]] "
+ "poolname [object...]\n"
+ " %s [-divPA] [-e -p path...] dataset [object...]\n"
+ " %s -m [-LXFPA] [-t txg] [-e [-p path...]] "
+ "poolname [vdev [metaslab...]]\n"
+ " %s -R [-A] [-e [-p path...]] poolname "
+ "vdev:offset:size[:flags]\n"
+ " %s -S [-PA] [-e [-p path...]] poolname\n"
+ " %s -l [-uA] device\n"
+ " %s -C [-A] [-U config]\n\n",
cmdname, cmdname, cmdname, cmdname, cmdname, cmdname, cmdname);
(void) fprintf(stderr, " Dataset name must include at least one "
@@ -150,7 +157,7 @@ usage(void)
"has altroot/not in a cachefile\n");
(void) fprintf(stderr, " -p <path> -- use one or more with "
"-e to specify path to vdev dir\n");
- (void) fprintf(stderr, " -P print numbers parsable\n");
+ (void) fprintf(stderr, " -P print numbers in parseable form\n");
(void) fprintf(stderr, " -t <txg> -- highest txg to use when "
"searching for uberblocks\n");
(void) fprintf(stderr, "Specify an option more than once (e.g. -bb) "
@@ -1085,7 +1092,7 @@ dump_dsl_dataset(objset_t *os, uint64_t
ASSERT(size == sizeof (*ds));
crtime = ds->ds_creation_time;
- zdb_nicenum(ds->ds_used_bytes, used);
+ zdb_nicenum(ds->ds_referenced_bytes, used);
zdb_nicenum(ds->ds_compressed_bytes, compressed);
zdb_nicenum(ds->ds_uncompressed_bytes, uncompressed);
zdb_nicenum(ds->ds_unique_bytes, unique);
@@ -1129,6 +1136,44 @@ dump_dsl_dataset(objset_t *os, uint64_t
/* ARGSUSED */
static int
+dump_bptree_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx)
+{
+ char blkbuf[BP_SPRINTF_LEN];
+
+ if (bp->blk_birth != 0) {
+ sprintf_blkptr(blkbuf, bp);
+ (void) printf("\t%s\n", blkbuf);
+ }
+ return (0);
+}
+
+static void
+dump_bptree(objset_t *os, uint64_t obj, char *name)
+{
+ char bytes[32];
+ bptree_phys_t *bt;
+ dmu_buf_t *db;
+
+ if (dump_opt['d'] < 3)
+ return;
+
+ VERIFY3U(0, ==, dmu_bonus_hold(os, obj, FTAG, &db));
+ bt = db->db_data;
+ zdb_nicenum(bt->bt_bytes, bytes);
+ (void) printf("\n %s: %llu datasets, %s\n",
+ name, (unsigned long long)(bt->bt_end - bt->bt_begin), bytes);
+ dmu_buf_rele(db, FTAG);
+
+ if (dump_opt['d'] < 5)
+ return;
+
+ (void) printf("\n");
+
+ (void) bptree_iterate(os, obj, B_FALSE, dump_bptree_cb, NULL, NULL);
+}
+
+/* ARGSUSED */
+static int
dump_bpobj_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx)
{
char blkbuf[BP_SPRINTF_LEN];
@@ -1880,11 +1925,13 @@ typedef struct zdb_blkstats {
*/
#define ZDB_OT_DEFERRED (DMU_OT_NUMTYPES + 0)
#define ZDB_OT_DITTO (DMU_OT_NUMTYPES + 1)
-#define ZDB_OT_TOTAL (DMU_OT_NUMTYPES + 2)
+#define ZDB_OT_OTHER (DMU_OT_NUMTYPES + 2)
+#define ZDB_OT_TOTAL (DMU_OT_NUMTYPES + 3)
static char *zdb_ot_extname[] = {
"deferred free",
"dedup ditto",
+ "other",
"Total",
};
@@ -1965,9 +2012,10 @@ zdb_blkptr_cb(spa_t *spa, zilog_t *zilog
type = BP_GET_TYPE(bp);
- zdb_count_block(zcb, zilog, bp, type);
+ zdb_count_block(zcb, zilog, bp,
+ (type & DMU_OT_NEWTYPE) ? ZDB_OT_OTHER : type);
- is_metadata = (BP_GET_LEVEL(bp) != 0 || dmu_ot[type].ot_metadata);
+ is_metadata = (BP_GET_LEVEL(bp) != 0 || DMU_OT_IS_METADATA(type));
if (dump_opt['c'] > 1 || (dump_opt['c'] && is_metadata)) {
int ioerr;
@@ -2192,6 +2240,12 @@ dump_block_stats(spa_t *spa)
count_block_cb, &zcb, NULL);
(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,
+ spa->spa_dsl_pool->dp_bptree_obj, B_FALSE, count_block_cb,
+ &zcb, NULL));
+ }
if (dump_opt['c'] > 1)
flags |= TRAVERSE_PREFETCH_DATA;
@@ -2368,7 +2422,7 @@ zdb_ddt_add_cb(spa_t *spa, zilog_t *zilo
}
if (BP_IS_HOLE(bp) || BP_GET_CHECKSUM(bp) == ZIO_CHECKSUM_OFF ||
- BP_GET_LEVEL(bp) > 0 || dmu_ot[BP_GET_TYPE(bp)].ot_metadata)
+ BP_GET_LEVEL(bp) > 0 || DMU_OT_IS_METADATA(BP_GET_TYPE(bp)))
return (0);
ddt_key_fill(&zdde_search.zdde_key, bp);
@@ -2473,7 +2527,14 @@ dump_zpool(spa_t *spa)
dump_bpobj(&spa->spa_deferred_bpobj, "Deferred frees");
if (spa_version(spa) >= SPA_VERSION_DEADLISTS) {
dump_bpobj(&spa->spa_dsl_pool->dp_free_bpobj,
- "Pool frees");
+ "Pool snapshot frees");
+ }
+
+ if (spa_feature_is_active(spa,
+ &spa_feature_table[SPA_FEATURE_ASYNC_DESTROY])) {
+ dump_bptree(spa->spa_meta_objset,
+ spa->spa_dsl_pool->dp_bptree_obj,
+ "Pool dataset frees");
}
dump_dtl(spa->spa_root_vdev, 0);
}
Modified: vendor/illumos/dist/cmd/zfs/zfs_main.c
==============================================================================
--- vendor/illumos/dist/cmd/zfs/zfs_main.c Wed Jul 18 10:19:06 2012 (r238582)
+++ vendor/illumos/dist/cmd/zfs/zfs_main.c Wed Jul 18 10:19:51 2012 (r238583)
@@ -21,6 +21,10 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright 2012 Milan Jurik. All rights reserved.
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
*/
#include <assert.h>
@@ -41,6 +45,7 @@
#include <grp.h>
#include <pwd.h>
#include <signal.h>
+#include <sys/list.h>
#include <sys/mkdev.h>
#include <sys/mntent.h>
#include <sys/mnttab.h>
@@ -51,7 +56,11 @@
#include <time.h>
#include <libzfs.h>
+#include <zfs_prop.h>
+#include <zfs_deleg.h>
#include <libuutil.h>
+#include <aclutils.h>
+#include <directory.h>
#include "zfs_iter.h"
#include "zfs_util.h"
@@ -61,7 +70,6 @@ libzfs_handle_t *g_zfs;
static FILE *mnttab_file;
static char history_str[HIS_MAX_RECORD_LEN];
-const char *pypath = "/usr/lib/zfs/pyzfs.py";
static int zfs_do_clone(int argc, char **argv);
static int zfs_do_create(int argc, char **argv);
@@ -82,8 +90,10 @@ static int zfs_do_send(int argc, char **
static int zfs_do_receive(int argc, char **argv);
static int zfs_do_promote(int argc, char **argv);
static int zfs_do_userspace(int argc, char **argv);
-static int zfs_do_python(int argc, char **argv);
+static int zfs_do_allow(int argc, char **argv);
+static int zfs_do_unallow(int argc, char **argv);
static int zfs_do_hold(int argc, char **argv);
+static int zfs_do_holds(int argc, char **argv);
static int zfs_do_release(int argc, char **argv);
static int zfs_do_diff(int argc, char **argv);
@@ -131,7 +141,7 @@ typedef enum {
HELP_HOLD,
HELP_HOLDS,
HELP_RELEASE,
- HELP_DIFF
+ HELP_DIFF,
} zfs_help_t;
typedef struct zfs_command {
@@ -176,12 +186,12 @@ static zfs_command_t command_table[] = {
{ "send", zfs_do_send, HELP_SEND },
{ "receive", zfs_do_receive, HELP_RECEIVE },
{ NULL },
- { "allow", zfs_do_python, HELP_ALLOW },
+ { "allow", zfs_do_allow, HELP_ALLOW },
{ NULL },
- { "unallow", zfs_do_python, HELP_UNALLOW },
+ { "unallow", zfs_do_unallow, HELP_UNALLOW },
{ NULL },
{ "hold", zfs_do_hold, HELP_HOLD },
- { "holds", zfs_do_python, HELP_HOLDS },
+ { "holds", zfs_do_holds, HELP_HOLDS },
{ "release", zfs_do_release, HELP_RELEASE },
{ "diff", zfs_do_diff, HELP_DIFF },
};
@@ -203,11 +213,13 @@ get_usage(zfs_help_t idx)
"\tcreate [-ps] [-b blocksize] [-o property=value] ... "
"-V <size> <volume>\n"));
case HELP_DESTROY:
- return (gettext("\tdestroy [-rRf] <filesystem|volume>\n"
- "\tdestroy [-rRd] <snapshot>\n"));
+ return (gettext("\tdestroy [-fnpRrv] <filesystem|volume>\n"
+ "\tdestroy [-dnpRrv] "
+ "<filesystem|volume>@<snap>[%<snap>][,...]\n"));
case HELP_GET:
return (gettext("\tget [-rHp] [-d max] "
- "[-o \"all\" | field[,...]] [-s source[,...]]\n"
+ "[-o \"all\" | field[,...]] [-t type[,...]] "
+ "[-s source[,...]]\n"
"\t <\"all\" | property[,...]> "
"[filesystem|volume|snapshot] ...\n"));
case HELP_INHERIT:
@@ -231,14 +243,15 @@ get_usage(zfs_help_t idx)
"snapshot>\n"
"\treceive [-vnFu] [-d | -e] <filesystem>\n"));
case HELP_RENAME:
- return (gettext("\trename <filesystem|volume|snapshot> "
+ return (gettext("\trename [-f] <filesystem|volume|snapshot> "
"<filesystem|volume|snapshot>\n"
- "\trename -p <filesystem|volume> <filesystem|volume>\n"
+ "\trename [-f] -p <filesystem|volume> <filesystem|volume>\n"
"\trename -r <snapshot> <snapshot>"));
case HELP_ROLLBACK:
return (gettext("\trollback [-rRf] <snapshot>\n"));
case HELP_SEND:
- return (gettext("\tsend [-RDp] [-[iI] snapshot] <snapshot>\n"));
+ return (gettext("\tsend [-DnPpRrv] [-[iI] snapshot] "
+ "<snapshot>\n"));
case HELP_SET:
return (gettext("\tset <property=value> "
"<filesystem|volume|snapshot> ...\n"));
@@ -417,6 +430,8 @@ usage(boolean_t requested)
(void) fprintf(fp, "YES NO <size> | none\n");
(void) fprintf(fp, "\t%-15s ", "groupquota at ...");
(void) fprintf(fp, "YES NO <size> | none\n");
+ (void) fprintf(fp, "\t%-15s ", "written@<snap>");
+ (void) fprintf(fp, " NO NO <size>\n");
(void) fprintf(fp, gettext("\nSizes are specified in bytes "
"with standard units such as K, M, G, etc.\n"));
@@ -562,7 +577,7 @@ zfs_do_clone(int argc, char **argv)
zfs_handle_t *zhp = NULL;
boolean_t parents = B_FALSE;
nvlist_t *props;
- int ret;
+ int ret = 0;
int c;
if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0)
@@ -729,7 +744,6 @@ zfs_do_create(int argc, char **argv)
(void) fprintf(stderr, gettext("missing size "
"argument\n"));
goto badusage;
- break;
case '?':
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
optopt);
@@ -862,15 +876,23 @@ badusage:
*/
typedef struct destroy_cbdata {
boolean_t cb_first;
- int cb_force;
- int cb_recurse;
- int cb_error;
- int cb_needforce;
- int cb_doclones;
- boolean_t cb_closezhp;
+ boolean_t cb_force;
+ boolean_t cb_recurse;
+ boolean_t cb_error;
+ boolean_t cb_doclones;
zfs_handle_t *cb_target;
- char *cb_snapname;
boolean_t cb_defer_destroy;
+ boolean_t cb_verbose;
+ boolean_t cb_parsable;
+ boolean_t cb_dryrun;
+ nvlist_t *cb_nvl;
+
+ /* first snap in contiguous run */
+ zfs_handle_t *cb_firstsnap;
+ /* previous snap in contiguous run */
+ zfs_handle_t *cb_prevsnap;
+ int64_t cb_snapused;
+ char *cb_snapspec;
} destroy_cbdata_t;
/*
@@ -900,7 +922,7 @@ destroy_check_dependent(zfs_handle_t *zh
(void) fprintf(stderr, gettext("use '-r' to destroy "
"the following datasets:\n"));
cbp->cb_first = B_FALSE;
- cbp->cb_error = 1;
+ cbp->cb_error = B_TRUE;
}
(void) fprintf(stderr, "%s\n", zfs_get_name(zhp));
@@ -921,7 +943,8 @@ destroy_check_dependent(zfs_handle_t *zh
(void) fprintf(stderr, gettext("use '-R' to destroy "
"the following datasets:\n"));
cbp->cb_first = B_FALSE;
- cbp->cb_error = 1;
+ cbp->cb_error = B_TRUE;
+ cbp->cb_dryrun = B_TRUE;
}
(void) fprintf(stderr, "%s\n", zfs_get_name(zhp));
@@ -935,7 +958,20 @@ out:
static int
destroy_callback(zfs_handle_t *zhp, void *data)
{
- destroy_cbdata_t *cbp = data;
+ destroy_cbdata_t *cb = data;
+ const char *name = zfs_get_name(zhp);
+
+ if (cb->cb_verbose) {
+ if (cb->cb_parsable) {
+ (void) printf("destroy\t%s\n", name);
+ } else if (cb->cb_dryrun) {
+ (void) printf(gettext("would destroy %s\n"),
+ name);
+ } else {
+ (void) printf(gettext("will destroy %s\n"),
+ name);
+ }
+ }
/*
* Ignore pools (which we've already flagged as an error before getting
@@ -947,13 +983,12 @@ destroy_callback(zfs_handle_t *zhp, void
return (0);
}
- /*
- * Bail out on the first error.
- */
- if (zfs_unmount(zhp, NULL, cbp->cb_force ? MS_FORCE : 0) != 0 ||
- zfs_destroy(zhp, cbp->cb_defer_destroy) != 0) {
- zfs_close(zhp);
- return (-1);
+ if (!cb->cb_dryrun) {
+ if (zfs_unmount(zhp, NULL, cb->cb_force ? MS_FORCE : 0) != 0 ||
+ zfs_destroy(zhp, cb->cb_defer_destroy) != 0) {
+ zfs_close(zhp);
+ return (-1);
+ }
}
zfs_close(zhp);
@@ -961,39 +996,142 @@ destroy_callback(zfs_handle_t *zhp, void
}
static int
-destroy_snap_clones(zfs_handle_t *zhp, void *arg)
+destroy_print_cb(zfs_handle_t *zhp, void *arg)
{
- destroy_cbdata_t *cbp = arg;
- char thissnap[MAXPATHLEN];
- zfs_handle_t *szhp;
- boolean_t closezhp = cbp->cb_closezhp;
- int rv;
+ destroy_cbdata_t *cb = arg;
+ const char *name = zfs_get_name(zhp);
+ int err = 0;
- (void) snprintf(thissnap, sizeof (thissnap),
- "%s@%s", zfs_get_name(zhp), cbp->cb_snapname);
+ if (nvlist_exists(cb->cb_nvl, name)) {
+ if (cb->cb_firstsnap == NULL)
+ cb->cb_firstsnap = zfs_handle_dup(zhp);
+ if (cb->cb_prevsnap != NULL)
+ zfs_close(cb->cb_prevsnap);
+ /* this snap continues the current range */
+ cb->cb_prevsnap = zfs_handle_dup(zhp);
+ if (cb->cb_verbose) {
+ if (cb->cb_parsable) {
+ (void) printf("destroy\t%s\n", name);
+ } else if (cb->cb_dryrun) {
+ (void) printf(gettext("would destroy %s\n"),
+ name);
+ } else {
+ (void) printf(gettext("will destroy %s\n"),
+ name);
+ }
+ }
+ } else if (cb->cb_firstsnap != NULL) {
+ /* end of this range */
+ uint64_t used = 0;
+ err = zfs_get_snapused_int(cb->cb_firstsnap,
+ cb->cb_prevsnap, &used);
+ cb->cb_snapused += used;
+ zfs_close(cb->cb_firstsnap);
+ cb->cb_firstsnap = NULL;
+ zfs_close(cb->cb_prevsnap);
+ cb->cb_prevsnap = NULL;
+ }
+ zfs_close(zhp);
+ return (err);
+}
- libzfs_print_on_error(g_zfs, B_FALSE);
- szhp = zfs_open(g_zfs, thissnap, ZFS_TYPE_SNAPSHOT);
- libzfs_print_on_error(g_zfs, B_TRUE);
- if (szhp) {
- /*
- * Destroy any clones of this snapshot
- */
- if (zfs_iter_dependents(szhp, B_FALSE, destroy_callback,
- cbp) != 0) {
- zfs_close(szhp);
- if (closezhp)
- zfs_close(zhp);
- return (-1);
+static int
+destroy_print_snapshots(zfs_handle_t *fs_zhp, destroy_cbdata_t *cb)
+{
+ int err = 0;
+ assert(cb->cb_firstsnap == NULL);
+ assert(cb->cb_prevsnap == NULL);
+ err = zfs_iter_snapshots_sorted(fs_zhp, destroy_print_cb, cb);
+ if (cb->cb_firstsnap != NULL) {
+ uint64_t used = 0;
+ if (err == 0) {
+ err = zfs_get_snapused_int(cb->cb_firstsnap,
+ cb->cb_prevsnap, &used);
}
- zfs_close(szhp);
+ cb->cb_snapused += used;
+ zfs_close(cb->cb_firstsnap);
+ cb->cb_firstsnap = NULL;
+ zfs_close(cb->cb_prevsnap);
+ cb->cb_prevsnap = NULL;
}
+ return (err);
+}
- cbp->cb_closezhp = B_TRUE;
- rv = zfs_iter_filesystems(zhp, destroy_snap_clones, arg);
- if (closezhp)
- zfs_close(zhp);
- return (rv);
+static int
+snapshot_to_nvl_cb(zfs_handle_t *zhp, void *arg)
+{
+ destroy_cbdata_t *cb = arg;
+ int err = 0;
+
+ /* Check for clones. */
+ if (!cb->cb_doclones) {
+ cb->cb_target = zhp;
+ cb->cb_first = B_TRUE;
+ err = zfs_iter_dependents(zhp, B_TRUE,
+ destroy_check_dependent, cb);
+ }
+
+ if (err == 0) {
+ if (nvlist_add_boolean(cb->cb_nvl, zfs_get_name(zhp)))
+ nomem();
+ }
+ zfs_close(zhp);
+ return (err);
+}
+
+static int
+gather_snapshots(zfs_handle_t *zhp, void *arg)
+{
+ destroy_cbdata_t *cb = arg;
+ int err = 0;
+
+ err = zfs_iter_snapspec(zhp, cb->cb_snapspec, snapshot_to_nvl_cb, cb);
+ if (err == ENOENT)
+ err = 0;
+ if (err != 0)
+ goto out;
+
+ if (cb->cb_verbose) {
+ err = destroy_print_snapshots(zhp, cb);
+ if (err != 0)
+ goto out;
+ }
+
+ if (cb->cb_recurse)
+ err = zfs_iter_filesystems(zhp, gather_snapshots, cb);
+
+out:
+ zfs_close(zhp);
+ return (err);
+}
+
+static int
+destroy_clones(destroy_cbdata_t *cb)
+{
+ nvpair_t *pair;
+ for (pair = nvlist_next_nvpair(cb->cb_nvl, NULL);
+ pair != NULL;
+ pair = nvlist_next_nvpair(cb->cb_nvl, pair)) {
+ zfs_handle_t *zhp = zfs_open(g_zfs, nvpair_name(pair),
+ ZFS_TYPE_SNAPSHOT);
+ if (zhp != NULL) {
+ boolean_t defer = cb->cb_defer_destroy;
+ int err = 0;
+
+ /*
+ * We can't defer destroy non-snapshots, so set it to
+ * false while destroying the clones.
+ */
+ cb->cb_defer_destroy = B_FALSE;
+ err = zfs_iter_dependents(zhp, B_FALSE,
+ destroy_callback, cb);
+ cb->cb_defer_destroy = defer;
+ zfs_close(zhp);
+ if (err != 0)
+ return (err);
+ }
+ }
+ return (0);
}
static int
@@ -1002,25 +1140,35 @@ zfs_do_destroy(int argc, char **argv)
destroy_cbdata_t cb = { 0 };
int c;
zfs_handle_t *zhp;
- char *cp;
+ char *at;
zfs_type_t type = ZFS_TYPE_DATASET;
/* check options */
- while ((c = getopt(argc, argv, "dfrR")) != -1) {
+ while ((c = getopt(argc, argv, "vpndfrR")) != -1) {
switch (c) {
+ case 'v':
+ cb.cb_verbose = B_TRUE;
+ break;
+ case 'p':
+ cb.cb_verbose = B_TRUE;
+ cb.cb_parsable = B_TRUE;
+ break;
+ case 'n':
+ cb.cb_dryrun = B_TRUE;
+ break;
case 'd':
cb.cb_defer_destroy = B_TRUE;
type = ZFS_TYPE_SNAPSHOT;
break;
case 'f':
- cb.cb_force = 1;
+ cb.cb_force = B_TRUE;
break;
case 'r':
- cb.cb_recurse = 1;
+ cb.cb_recurse = B_TRUE;
break;
case 'R':
- cb.cb_recurse = 1;
- cb.cb_doclones = 1;
+ cb.cb_recurse = B_TRUE;
+ cb.cb_doclones = B_TRUE;
break;
case '?':
default:
@@ -1035,7 +1183,7 @@ zfs_do_destroy(int argc, char **argv)
/* check number of arguments */
if (argc == 0) {
- (void) fprintf(stderr, gettext("missing path argument\n"));
+ (void) fprintf(stderr, gettext("missing dataset argument\n"));
usage(B_FALSE);
}
if (argc > 1) {
@@ -1043,91 +1191,117 @@ zfs_do_destroy(int argc, char **argv)
usage(B_FALSE);
}
- /*
- * If we are doing recursive destroy of a snapshot, then the
- * named snapshot may not exist. Go straight to libzfs.
- */
- if (cb.cb_recurse && (cp = strchr(argv[0], '@'))) {
- int ret;
+ 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();
- *cp = '\0';
- if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_DATASET)) == NULL)
+ *at = '\0';
+ zhp = zfs_open(g_zfs, argv[0],
+ ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
+ if (zhp == NULL)
return (1);
- *cp = '@';
- cp++;
- if (cb.cb_doclones) {
- boolean_t defer = cb.cb_defer_destroy;
+ 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);
+ }
- /*
- * Temporarily ignore the defer_destroy setting since
- * it's not supported for clones.
- */
- cb.cb_defer_destroy = B_FALSE;
- cb.cb_snapname = cp;
- if (destroy_snap_clones(zhp, &cb) != 0) {
- zfs_close(zhp);
- return (1);
+ 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);
+ }
+
+ if (cb.cb_verbose) {
+ char buf[16];
+ zfs_nicenum(cb.cb_snapused, buf, sizeof (buf));
+ if (cb.cb_parsable) {
+ (void) printf("reclaim\t%llu\n",
+ cb.cb_snapused);
+ } else if (cb.cb_dryrun) {
+ (void) printf(gettext("would reclaim %s\n"),
+ buf);
+ } else {
+ (void) printf(gettext("will reclaim %s\n"),
+ buf);
}
- cb.cb_defer_destroy = defer;
}
- ret = zfs_destroy_snaps(zhp, cp, cb.cb_defer_destroy);
- zfs_close(zhp);
- if (ret) {
- (void) fprintf(stderr,
- gettext("no snapshots destroyed\n"));
+ if (!cb.cb_dryrun) {
+ if (cb.cb_doclones)
+ err = destroy_clones(&cb);
+ if (err == 0) {
+ err = zfs_destroy_snaps_nvl(zhp, cb.cb_nvl,
+ cb.cb_defer_destroy);
+ }
}
- return (ret != 0);
- }
- /* Open the given dataset */
- if ((zhp = zfs_open(g_zfs, argv[0], type)) == NULL)
- return (1);
+ zfs_close(zhp);
+ nvlist_free(cb.cb_nvl);
+ if (err != 0)
+ return (1);
+ } else {
+ /* Open the given dataset */
+ if ((zhp = zfs_open(g_zfs, argv[0], type)) == NULL)
+ return (1);
- cb.cb_target = zhp;
+ cb.cb_target = zhp;
- /*
- * Perform an explicit check for pools before going any further.
- */
- if (!cb.cb_recurse && strchr(zfs_get_name(zhp), '/') == NULL &&
- zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) {
- (void) fprintf(stderr, gettext("cannot destroy '%s': "
- "operation does not apply to pools\n"),
- zfs_get_name(zhp));
- (void) fprintf(stderr, gettext("use 'zfs destroy -r "
- "%s' to destroy all datasets in the pool\n"),
- 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);
- }
+ /*
+ * Perform an explicit check for pools before going any further.
+ */
+ if (!cb.cb_recurse && strchr(zfs_get_name(zhp), '/') == NULL &&
+ zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) {
+ (void) fprintf(stderr, gettext("cannot destroy '%s': "
+ "operation does not apply to pools\n"),
+ zfs_get_name(zhp));
+ (void) fprintf(stderr, gettext("use 'zfs destroy -r "
+ "%s' to destroy all datasets in the pool\n"),
+ 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);
+ }
- /*
- * Check for any dependents and/or clones.
- */
- cb.cb_first = B_TRUE;
- if (!cb.cb_doclones && !cb.cb_defer_destroy &&
- zfs_iter_dependents(zhp, B_TRUE, destroy_check_dependent,
- &cb) != 0) {
- zfs_close(zhp);
- return (1);
- }
+ /*
+ * Check for any dependents and/or clones.
+ */
+ cb.cb_first = B_TRUE;
+ if (!cb.cb_doclones &&
+ zfs_iter_dependents(zhp, B_TRUE, destroy_check_dependent,
+ &cb) != 0) {
+ zfs_close(zhp);
+ return (1);
+ }
- if (cb.cb_error || (!cb.cb_defer_destroy &&
- (zfs_iter_dependents(zhp, B_FALSE, destroy_callback, &cb) != 0))) {
- zfs_close(zhp);
- return (1);
- }
+ if (cb.cb_error) {
+ zfs_close(zhp);
+ return (1);
+ }
- /*
- * Do the real thing. The callback will close the handle regardless of
- * whether it succeeds or not.
- */
+ if (zfs_iter_dependents(zhp, B_FALSE, destroy_callback,
+ &cb) != 0) {
+ zfs_close(zhp);
+ return (1);
+ }
- if (destroy_callback(zhp, &cb) != 0)
- return (1);
+ /*
+ * 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);
+ }
return (0);
}
@@ -1229,6 +1403,17 @@ get_callback(zfs_handle_t *zhp, void *da
zprop_print_one_property(zfs_get_name(zhp), cbp,
pl->pl_user_prop, buf, sourcetype, source, NULL);
+ } else if (zfs_prop_written(pl->pl_user_prop)) {
+ sourcetype = ZPROP_SRC_LOCAL;
+
+ if (zfs_prop_get_written(zhp, pl->pl_user_prop,
+ buf, sizeof (buf), cbp->cb_literal) != 0) {
+ sourcetype = ZPROP_SRC_NONE;
+ (void) strlcpy(buf, "-", sizeof (buf));
+ }
+
+ zprop_print_one_property(zfs_get_name(zhp), cbp,
+ pl->pl_user_prop, buf, sourcetype, source, NULL);
} else {
if (nvlist_lookup_nvlist(user_props,
pl->pl_user_prop, &propval) != 0) {
@@ -1273,9 +1458,10 @@ static int
zfs_do_get(int argc, char **argv)
{
zprop_get_cbdata_t cb = { 0 };
- int i, c, flags = 0;
+ int i, c, flags = ZFS_ITER_ARGS_CAN_BE_PATHS;
+ int types = ZFS_TYPE_DATASET;
char *value, *fields;
- int ret;
+ int ret = 0;
int limit = 0;
zprop_list_t fake_name = { 0 };
@@ -1290,7 +1476,7 @@ zfs_do_get(int argc, char **argv)
cb.cb_type = ZFS_TYPE_DATASET;
/* check options */
- while ((c = getopt(argc, argv, ":d:o:s:rHp")) != -1) {
+ while ((c = getopt(argc, argv, ":d:o:s:rt:Hp")) != -1) {
switch (c) {
case 'p':
cb.cb_literal = B_TRUE;
@@ -1408,6 +1594,37 @@ zfs_do_get(int argc, char **argv)
}
break;
+ case 't':
+ types = 0;
+ flags &= ~ZFS_ITER_PROP_LISTSNAPS;
+ while (*optarg != '\0') {
+ static char *type_subopts[] = { "filesystem",
+ "volume", "snapshot", "all", NULL };
+
+ switch (getsubopt(&optarg, type_subopts,
+ &value)) {
+ case 0:
+ types |= ZFS_TYPE_FILESYSTEM;
+ break;
+ case 1:
+ types |= ZFS_TYPE_VOLUME;
+ break;
+ case 2:
+ types |= ZFS_TYPE_SNAPSHOT;
+ break;
+ case 3:
+ types = ZFS_TYPE_DATASET;
+ break;
+
+ default:
+ (void) fprintf(stderr,
+ gettext("invalid type '%s'\n"),
+ value);
+ usage(B_FALSE);
+ }
+ }
+ break;
+
case '?':
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
optopt);
@@ -1451,7 +1668,7 @@ zfs_do_get(int argc, char **argv)
cb.cb_first = B_TRUE;
/* run for each object */
- ret = zfs_for_each(argc, argv, flags, ZFS_TYPE_DATASET, NULL,
+ ret = zfs_for_each(argc, argv, flags, types, NULL,
&cb.cb_proplist, limit, get_callback, &cb);
if (cb.cb_proplist == &fake_name)
@@ -1512,7 +1729,7 @@ zfs_do_inherit(int argc, char **argv)
zfs_prop_t prop;
inherit_cbdata_t cb = { 0 };
char *propname;
- int ret;
+ int ret = 0;
int flags = 0;
boolean_t received = B_FALSE;
@@ -1718,7 +1935,7 @@ zfs_do_upgrade(int argc, char **argv)
{
boolean_t all = B_FALSE;
boolean_t showversions = B_FALSE;
- int ret;
+ int ret = 0;
upgrade_cbdata_t cb = { 0 };
char c;
int flags = ZFS_ITER_ARGS_CAN_BE_PATHS;
@@ -1773,8 +1990,8 @@ zfs_do_upgrade(int argc, char **argv)
"---------------\n");
(void) printf(gettext(" 1 Initial ZFS filesystem version\n"));
(void) printf(gettext(" 2 Enhanced directory entries\n"));
- (void) printf(gettext(" 3 Case insensitive and File system "
- "unique identifier (FUID)\n"));
+ (void) printf(gettext(" 3 Case insensitive and filesystem "
+ "user identifier (FUID)\n"));
(void) printf(gettext(" 4 userquota, groupquota "
"properties\n"));
(void) printf(gettext(" 5 System attributes\n"));
@@ -1823,87 +2040,727 @@ zfs_do_upgrade(int argc, char **argv)
return (ret);
}
+#define USTYPE_USR_BIT (0)
+#define USTYPE_GRP_BIT (1)
+#define USTYPE_PSX_BIT (2)
+#define USTYPE_SMB_BIT (3)
+
+#define USTYPE_USR (1 << USTYPE_USR_BIT)
+#define USTYPE_GRP (1 << USTYPE_GRP_BIT)
+
+#define USTYPE_PSX (1 << USTYPE_PSX_BIT)
+#define USTYPE_SMB (1 << USTYPE_SMB_BIT)
+
+#define USTYPE_PSX_USR (USTYPE_PSX | USTYPE_USR)
+#define USTYPE_SMB_USR (USTYPE_SMB | USTYPE_USR)
+#define USTYPE_PSX_GRP (USTYPE_PSX | USTYPE_GRP)
+#define USTYPE_SMB_GRP (USTYPE_SMB | USTYPE_GRP)
+#define USTYPE_ALL (USTYPE_PSX_USR | USTYPE_SMB_USR \
+ | USTYPE_PSX_GRP | USTYPE_SMB_GRP)
+
+
+#define USPROP_USED_BIT (0)
+#define USPROP_QUOTA_BIT (1)
+
+#define USPROP_USED (1 << USPROP_USED_BIT)
+#define USPROP_QUOTA (1 << USPROP_QUOTA_BIT)
+
+typedef struct us_node {
+ nvlist_t *usn_nvl;
+ uu_avl_node_t usn_avlnode;
+ uu_list_node_t usn_listnode;
+} us_node_t;
+
+typedef struct us_cbdata {
+ nvlist_t **cb_nvlp;
+ uu_avl_pool_t *cb_avl_pool;
+ uu_avl_t *cb_avl;
+ boolean_t cb_numname;
+ boolean_t cb_nicenum;
+ boolean_t cb_sid2posix;
+ zfs_userquota_prop_t cb_prop;
+ zfs_sort_column_t *cb_sortcol;
+ size_t cb_max_typelen;
+ size_t cb_max_namelen;
+ size_t cb_max_usedlen;
+ size_t cb_max_quotalen;
+} us_cbdata_t;
+
+typedef struct {
+ zfs_sort_column_t *si_sortcol;
+ boolean_t si_num_name;
+ boolean_t si_parsable;
+} us_sort_info_t;
+
+static int
+us_compare(const void *larg, const void *rarg, void *unused)
+{
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-vendor
mailing list