Date: Wed, 18 Jul 2012 10:19:51 +0000 (UTC) From: Martin Matuska <mm@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-vendor@freebsd.org Subject: 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 Message-ID: <201207181019.q6IAJpp0054639@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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@..."); (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 ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201207181019.q6IAJpp0054639>