fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * CDDL HEADER START
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The contents of this file are subject to the terms of the
99653d4ee642c6528e88224f12409a5f23060994eschrock * Common Development and Distribution License (the "License").
99653d4ee642c6528e88224f12409a5f23060994eschrock * You may not use this file except in compliance with the License.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fa9e4066f08beec538e775443c5be79dd423fcabahrens * or http://www.opensolaris.org/os/licensing.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * See the License for the specific language governing permissions
fa9e4066f08beec538e775443c5be79dd423fcabahrens * and limitations under the License.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * When distributing Covered Code, include this CDDL HEADER in each
fa9e4066f08beec538e775443c5be79dd423fcabahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If applicable, add the following below this CDDL HEADER, with the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * fields enclosed by brackets "[]" replaced with your own identifying
fa9e4066f08beec538e775443c5be79dd423fcabahrens * information: Portions Copyright [yyyy] [name of copyright owner]
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * CDDL HEADER END
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
43d68d68c1ce08fb35026bebfb141af422e7082eYuri Pankov
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
a8b6ddaf31808c845e00161dda0a3d1fe31ae281Mark J Musante * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
0d8fa8f8eba3ea46bc79d73445009505d1dd5d7dMartin Matuska * Copyright (c) 2012 Pawel Jakub Dawidek. All rights reserved.
43d68d68c1ce08fb35026bebfb141af422e7082eYuri Pankov * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
78f171005391b928aaf1642b3206c534ed644332Matthew Ahrens * Copyright (c) 2013 by Delphix. All rights reserved.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <libintl.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <libuutil.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <stddef.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <stdio.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <stdlib.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <strings.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <libzfs.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include "zfs_util.h"
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek#include "zfs_iter.h"
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * This is a private interface used to gather up all the datasets specified on
fa9e4066f08beec538e775443c5be79dd423fcabahrens * the command line so that we can iterate over them in order.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * First, we iterate over all filesystems, gathering them together into an
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek * AVL tree. We report errors for any explicitly specified datasets
fa9e4066f08beec538e775443c5be79dd423fcabahrens * that we couldn't open.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * When finished, we have an AVL tree of ZFS handles. We go through and execute
fa9e4066f08beec538e775443c5be79dd423fcabahrens * the provided callback for each one, passing whatever data the user supplied.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrenstypedef struct zfs_node {
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfs_handle_t *zn_handle;
fa9e4066f08beec538e775443c5be79dd423fcabahrens uu_avl_node_t zn_avlnode;
fa9e4066f08beec538e775443c5be79dd423fcabahrens} zfs_node_t;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrenstypedef struct callback_data {
ae1726b6ae69a6882b0d520f4bc3433f501f2065Chris Gerhard uu_avl_t *cb_avl;
ae1726b6ae69a6882b0d520f4bc3433f501f2065Chris Gerhard int cb_flags;
ae1726b6ae69a6882b0d520f4bc3433f501f2065Chris Gerhard zfs_type_t cb_types;
ae1726b6ae69a6882b0d520f4bc3433f501f2065Chris Gerhard zfs_sort_column_t *cb_sortcol;
ae1726b6ae69a6882b0d520f4bc3433f501f2065Chris Gerhard zprop_list_t **cb_proplist;
ae1726b6ae69a6882b0d520f4bc3433f501f2065Chris Gerhard int cb_depth_limit;
ae1726b6ae69a6882b0d520f4bc3433f501f2065Chris Gerhard int cb_depth;
ae1726b6ae69a6882b0d520f4bc3433f501f2065Chris Gerhard uint8_t cb_props_table[ZFS_NUM_PROPS];
fa9e4066f08beec538e775443c5be79dd423fcabahrens} callback_data_t;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensuu_avl_pool_t *avl_pool;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
d5b5bb256c576fe5ef26e0795bd40abe77f93246Rich Morris * Include snaps if they were requested or if this a zfs list where types
d5b5bb256c576fe5ef26e0795bd40abe77f93246Rich Morris * were not specified and the "listsnapshots" property is set on this pool.
d5b5bb256c576fe5ef26e0795bd40abe77f93246Rich Morris */
78f171005391b928aaf1642b3206c534ed644332Matthew Ahrensstatic boolean_t
d5b5bb256c576fe5ef26e0795bd40abe77f93246Rich Morriszfs_include_snapshots(zfs_handle_t *zhp, callback_data_t *cb)
d5b5bb256c576fe5ef26e0795bd40abe77f93246Rich Morris{
d5b5bb256c576fe5ef26e0795bd40abe77f93246Rich Morris zpool_handle_t *zph;
d5b5bb256c576fe5ef26e0795bd40abe77f93246Rich Morris
d5b5bb256c576fe5ef26e0795bd40abe77f93246Rich Morris if ((cb->cb_flags & ZFS_ITER_PROP_LISTSNAPS) == 0)
d5b5bb256c576fe5ef26e0795bd40abe77f93246Rich Morris return (cb->cb_types & ZFS_TYPE_SNAPSHOT);
d5b5bb256c576fe5ef26e0795bd40abe77f93246Rich Morris
d5b5bb256c576fe5ef26e0795bd40abe77f93246Rich Morris zph = zfs_get_pool_handle(zhp);
d5b5bb256c576fe5ef26e0795bd40abe77f93246Rich Morris return (zpool_get_prop_int(zph, ZPOOL_PROP_LISTSNAPS, NULL));
d5b5bb256c576fe5ef26e0795bd40abe77f93246Rich Morris}
d5b5bb256c576fe5ef26e0795bd40abe77f93246Rich Morris
d5b5bb256c576fe5ef26e0795bd40abe77f93246Rich Morris/*
d5b5bb256c576fe5ef26e0795bd40abe77f93246Rich Morris * Called for each dataset. If the object is of an appropriate type,
fa9e4066f08beec538e775443c5be79dd423fcabahrens * add it to the avl tree and recurse over any children as necessary.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
3cb34c601f3ef3016f638574f5982e80c3735c71ahrensstatic int
fa9e4066f08beec538e775443c5be79dd423fcabahrenszfs_callback(zfs_handle_t *zhp, void *data)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens callback_data_t *cb = data;
d189620258b3c9b0e2f7e2104840be2eee7c68e5David Schwartz boolean_t should_close = B_TRUE;
78f171005391b928aaf1642b3206c534ed644332Matthew Ahrens boolean_t include_snaps = zfs_include_snapshots(zhp, cb);
78f171005391b928aaf1642b3206c534ed644332Matthew Ahrens boolean_t include_bmarks = (cb->cb_types & ZFS_TYPE_BOOKMARK);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
d5b5bb256c576fe5ef26e0795bd40abe77f93246Rich Morris if ((zfs_get_type(zhp) & cb->cb_types) ||
d5b5bb256c576fe5ef26e0795bd40abe77f93246Rich Morris ((zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT) && include_snaps)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens uu_avl_index_t idx;
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfs_node_t *node = safe_malloc(sizeof (zfs_node_t));
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens node->zn_handle = zhp;
fa9e4066f08beec538e775443c5be79dd423fcabahrens uu_avl_node_init(node, &node->zn_avlnode, avl_pool);
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek if (uu_avl_find(cb->cb_avl, node, cb->cb_sortcol,
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek &idx) == NULL) {
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi if (cb->cb_proplist) {
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi if ((*cb->cb_proplist) &&
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi !(*cb->cb_proplist)->pl_all)
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi zfs_prune_proplist(zhp,
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi cb->cb_props_table);
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson if (zfs_expand_proplist(zhp, cb->cb_proplist,
43d68d68c1ce08fb35026bebfb141af422e7082eYuri Pankov (cb->cb_flags & ZFS_ITER_RECVD_PROPS),
43d68d68c1ce08fb35026bebfb141af422e7082eYuri Pankov (cb->cb_flags & ZFS_ITER_LITERAL_PROPS))
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi != 0) {
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi free(node);
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi return (-1);
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi }
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock }
fa9e4066f08beec538e775443c5be79dd423fcabahrens uu_avl_insert(cb->cb_avl, node, idx);
d189620258b3c9b0e2f7e2104840be2eee7c68e5David Schwartz should_close = B_FALSE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens free(node);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
7f7322febbcfe774b7270abc3b191c094bfcc517eschrock * Recurse if necessary.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
ae1726b6ae69a6882b0d520f4bc3433f501f2065Chris Gerhard if (cb->cb_flags & ZFS_ITER_RECURSE &&
ae1726b6ae69a6882b0d520f4bc3433f501f2065Chris Gerhard ((cb->cb_flags & ZFS_ITER_DEPTH_LIMIT) == 0 ||
ae1726b6ae69a6882b0d520f4bc3433f501f2065Chris Gerhard cb->cb_depth < cb->cb_depth_limit)) {
ae1726b6ae69a6882b0d520f4bc3433f501f2065Chris Gerhard cb->cb_depth++;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens if (zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM)
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens (void) zfs_iter_filesystems(zhp, zfs_callback, data);
78f171005391b928aaf1642b3206c534ed644332Matthew Ahrens if (((zfs_get_type(zhp) & (ZFS_TYPE_SNAPSHOT |
78f171005391b928aaf1642b3206c534ed644332Matthew Ahrens ZFS_TYPE_BOOKMARK)) == 0) && include_snaps)
0d8fa8f8eba3ea46bc79d73445009505d1dd5d7dMartin Matuska (void) zfs_iter_snapshots(zhp,
0d8fa8f8eba3ea46bc79d73445009505d1dd5d7dMartin Matuska (cb->cb_flags & ZFS_ITER_SIMPLE) != 0, zfs_callback,
0d8fa8f8eba3ea46bc79d73445009505d1dd5d7dMartin Matuska data);
78f171005391b928aaf1642b3206c534ed644332Matthew Ahrens if (((zfs_get_type(zhp) & (ZFS_TYPE_SNAPSHOT |
78f171005391b928aaf1642b3206c534ed644332Matthew Ahrens ZFS_TYPE_BOOKMARK)) == 0) && include_bmarks)
78f171005391b928aaf1642b3206c534ed644332Matthew Ahrens (void) zfs_iter_bookmarks(zhp, zfs_callback, data);
ae1726b6ae69a6882b0d520f4bc3433f501f2065Chris Gerhard cb->cb_depth--;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
d189620258b3c9b0e2f7e2104840be2eee7c68e5David Schwartz if (should_close)
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfs_close(zhp);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrockint
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrockzfs_add_sort_column(zfs_sort_column_t **sc, const char *name,
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek boolean_t reverse)
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek{
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek zfs_sort_column_t *col;
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock zfs_prop_t prop;
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock
990b4856d0eaada6f8140335733a1b1771ed2746lling if ((prop = zfs_name_to_prop(name)) == ZPROP_INVAL &&
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock !zfs_prop_user(name))
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock return (-1);
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek col = safe_malloc(sizeof (zfs_sort_column_t));
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek col->sc_prop = prop;
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek col->sc_reverse = reverse;
990b4856d0eaada6f8140335733a1b1771ed2746lling if (prop == ZPROP_INVAL) {
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock col->sc_user_prop = safe_malloc(strlen(name) + 1);
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock (void) strcpy(col->sc_user_prop, name);
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock }
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek if (*sc == NULL) {
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek col->sc_last = col;
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek *sc = col;
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek } else {
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek (*sc)->sc_last->sc_next = col;
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek (*sc)->sc_last = col;
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek }
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock return (0);
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek}
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinekvoid
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinekzfs_free_sort_columns(zfs_sort_column_t *sc)
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek{
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek zfs_sort_column_t *col;
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek while (sc != NULL) {
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek col = sc->sc_next;
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock free(sc->sc_user_prop);
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek free(sc);
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek sc = col;
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek }
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek}
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek
0d8fa8f8eba3ea46bc79d73445009505d1dd5d7dMartin Matuskaboolean_t
0d8fa8f8eba3ea46bc79d73445009505d1dd5d7dMartin Matuskazfs_sort_only_by_name(const zfs_sort_column_t *sc)
0d8fa8f8eba3ea46bc79d73445009505d1dd5d7dMartin Matuska{
0d8fa8f8eba3ea46bc79d73445009505d1dd5d7dMartin Matuska
0d8fa8f8eba3ea46bc79d73445009505d1dd5d7dMartin Matuska return (sc != NULL && sc->sc_next == NULL &&
0d8fa8f8eba3ea46bc79d73445009505d1dd5d7dMartin Matuska sc->sc_prop == ZFS_PROP_NAME);
0d8fa8f8eba3ea46bc79d73445009505d1dd5d7dMartin Matuska}
0d8fa8f8eba3ea46bc79d73445009505d1dd5d7dMartin Matuska
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int
fa9e4066f08beec538e775443c5be79dd423fcabahrenszfs_compare(const void *larg, const void *rarg, void *unused)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfs_handle_t *l = ((zfs_node_t *)larg)->zn_handle;
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfs_handle_t *r = ((zfs_node_t *)rarg)->zn_handle;
fa9e4066f08beec538e775443c5be79dd423fcabahrens const char *lname = zfs_get_name(l);
fa9e4066f08beec538e775443c5be79dd423fcabahrens const char *rname = zfs_get_name(r);
fa9e4066f08beec538e775443c5be79dd423fcabahrens char *lat, *rat;
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint64_t lcreate, rcreate;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int ret;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens lat = (char *)strchr(lname, '@');
fa9e4066f08beec538e775443c5be79dd423fcabahrens rat = (char *)strchr(rname, '@');
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (lat != NULL)
fa9e4066f08beec538e775443c5be79dd423fcabahrens *lat = '\0';
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (rat != NULL)
fa9e4066f08beec538e775443c5be79dd423fcabahrens *rat = '\0';
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens ret = strcmp(lname, rname);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ret == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If we're comparing a dataset to one of its snapshots, we
fa9e4066f08beec538e775443c5be79dd423fcabahrens * always make the full dataset first.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (lat == NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens ret = -1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else if (rat == NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens ret = 1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If we have two snapshots from the same dataset, then
fa9e4066f08beec538e775443c5be79dd423fcabahrens * we want to sort them according to creation time. We
fa9e4066f08beec538e775443c5be79dd423fcabahrens * use the hidden CREATETXG property to get an absolute
fa9e4066f08beec538e775443c5be79dd423fcabahrens * ordering of snapshots.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens lcreate = zfs_prop_get_int(l, ZFS_PROP_CREATETXG);
fa9e4066f08beec538e775443c5be79dd423fcabahrens rcreate = zfs_prop_get_int(r, ZFS_PROP_CREATETXG);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
0d8fa8f8eba3ea46bc79d73445009505d1dd5d7dMartin Matuska /*
0d8fa8f8eba3ea46bc79d73445009505d1dd5d7dMartin Matuska * Both lcreate and rcreate being 0 means we don't have
0d8fa8f8eba3ea46bc79d73445009505d1dd5d7dMartin Matuska * properties and we should compare full name.
0d8fa8f8eba3ea46bc79d73445009505d1dd5d7dMartin Matuska */
0d8fa8f8eba3ea46bc79d73445009505d1dd5d7dMartin Matuska if (lcreate == 0 && rcreate == 0)
0d8fa8f8eba3ea46bc79d73445009505d1dd5d7dMartin Matuska ret = strcmp(lat + 1, rat + 1);
0d8fa8f8eba3ea46bc79d73445009505d1dd5d7dMartin Matuska else if (lcreate < rcreate)
fa9e4066f08beec538e775443c5be79dd423fcabahrens ret = -1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens else if (lcreate > rcreate)
fa9e4066f08beec538e775443c5be79dd423fcabahrens ret = 1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (lat != NULL)
fa9e4066f08beec538e775443c5be79dd423fcabahrens *lat = '@';
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (rat != NULL)
fa9e4066f08beec538e775443c5be79dd423fcabahrens *rat = '@';
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (ret);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek/*
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek * Sort datasets by specified columns.
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek *
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek * o Numeric types sort in ascending order.
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek * o String types sort in alphabetical order.
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek * o Types inappropriate for a row sort that row to the literal
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek * bottom, regardless of the specified ordering.
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek *
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek * If no sort columns are specified, or two datasets compare equally
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek * across all specified columns, they are sorted alphabetically by name
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek * with snapshots grouped under their parents.
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek */
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinekstatic int
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinekzfs_sort(const void *larg, const void *rarg, void *data)
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek{
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek zfs_handle_t *l = ((zfs_node_t *)larg)->zn_handle;
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek zfs_handle_t *r = ((zfs_node_t *)rarg)->zn_handle;
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek zfs_sort_column_t *sc = (zfs_sort_column_t *)data;
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek zfs_sort_column_t *psc;
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek for (psc = sc; psc != NULL; psc = psc->sc_next) {
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock char lbuf[ZFS_MAXPROPLEN], rbuf[ZFS_MAXPROPLEN];
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock char *lstr, *rstr;
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek uint64_t lnum, rnum;
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock boolean_t lvalid, rvalid;
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek int ret = 0;
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock /*
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock * We group the checks below the generic code. If 'lstr' and
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock * 'rstr' are non-NULL, then we do a string based comparison.
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock * Otherwise, we compare 'lnum' and 'rnum'.
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock */
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock lstr = rstr = NULL;
990b4856d0eaada6f8140335733a1b1771ed2746lling if (psc->sc_prop == ZPROP_INVAL) {
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock nvlist_t *luser, *ruser;
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock nvlist_t *lval, *rval;
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock luser = zfs_get_user_props(l);
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock ruser = zfs_get_user_props(r);
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock lvalid = (nvlist_lookup_nvlist(luser,
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock psc->sc_user_prop, &lval) == 0);
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock rvalid = (nvlist_lookup_nvlist(ruser,
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock psc->sc_user_prop, &rval) == 0);
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock if (lvalid)
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock verify(nvlist_lookup_string(lval,
990b4856d0eaada6f8140335733a1b1771ed2746lling ZPROP_VALUE, &lstr) == 0);
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock if (rvalid)
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock verify(nvlist_lookup_string(rval,
990b4856d0eaada6f8140335733a1b1771ed2746lling ZPROP_VALUE, &rstr) == 0);
0d8fa8f8eba3ea46bc79d73445009505d1dd5d7dMartin Matuska } else if (psc->sc_prop == ZFS_PROP_NAME) {
0d8fa8f8eba3ea46bc79d73445009505d1dd5d7dMartin Matuska lvalid = rvalid = B_TRUE;
0d8fa8f8eba3ea46bc79d73445009505d1dd5d7dMartin Matuska
0d8fa8f8eba3ea46bc79d73445009505d1dd5d7dMartin Matuska (void) strlcpy(lbuf, zfs_get_name(l), sizeof (lbuf));
0d8fa8f8eba3ea46bc79d73445009505d1dd5d7dMartin Matuska (void) strlcpy(rbuf, zfs_get_name(r), sizeof (rbuf));
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock
0d8fa8f8eba3ea46bc79d73445009505d1dd5d7dMartin Matuska lstr = lbuf;
0d8fa8f8eba3ea46bc79d73445009505d1dd5d7dMartin Matuska rstr = rbuf;
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock } else if (zfs_prop_is_string(psc->sc_prop)) {
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock lvalid = (zfs_prop_get(l, psc->sc_prop, lbuf,
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock sizeof (lbuf), NULL, NULL, 0, B_TRUE) == 0);
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock rvalid = (zfs_prop_get(r, psc->sc_prop, rbuf,
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock sizeof (rbuf), NULL, NULL, 0, B_TRUE) == 0);
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock lstr = lbuf;
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock rstr = rbuf;
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek } else {
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek lvalid = zfs_prop_valid_for_type(psc->sc_prop,
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek zfs_get_type(l));
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek rvalid = zfs_prop_valid_for_type(psc->sc_prop,
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek zfs_get_type(r));
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock if (lvalid)
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock (void) zfs_prop_get_numeric(l, psc->sc_prop,
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock &lnum, NULL, NULL, 0);
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock if (rvalid)
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock (void) zfs_prop_get_numeric(r, psc->sc_prop,
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock &rnum, NULL, NULL, 0);
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock }
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock if (!lvalid && !rvalid)
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock continue;
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock else if (!lvalid)
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock return (1);
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock else if (!rvalid)
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock return (-1);
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock if (lstr)
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock ret = strcmp(lstr, rstr);
b8a9e29c67ce838c791f49c3fd888b702b45c2fbrm else if (lnum < rnum)
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock ret = -1;
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock else if (lnum > rnum)
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock ret = 1;
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek if (ret != 0) {
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek if (psc->sc_reverse == B_TRUE)
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek ret = (ret < 0) ? 1 : -1;
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek return (ret);
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek }
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek }
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek return (zfs_compare(larg, rarg, NULL));
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek}
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek
fa9e4066f08beec538e775443c5be79dd423fcabahrensint
d5b5bb256c576fe5ef26e0795bd40abe77f93246Rich Morriszfs_for_each(int argc, char **argv, int flags, zfs_type_t types,
ae1726b6ae69a6882b0d520f4bc3433f501f2065Chris Gerhard zfs_sort_column_t *sortcol, zprop_list_t **proplist, int limit,
d5b5bb256c576fe5ef26e0795bd40abe77f93246Rich Morris zfs_iter_f callback, void *data)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi callback_data_t cb = {0};
fa9e4066f08beec538e775443c5be79dd423fcabahrens int ret = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfs_node_t *node;
fa9e4066f08beec538e775443c5be79dd423fcabahrens uu_avl_walk_t *walk;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens avl_pool = uu_avl_pool_create("zfs_pool", sizeof (zfs_node_t),
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek offsetof(zfs_node_t, zn_avlnode), zfs_sort, UU_DEFAULT);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
a8b6ddaf31808c845e00161dda0a3d1fe31ae281Mark J Musante if (avl_pool == NULL)
a8b6ddaf31808c845e00161dda0a3d1fe31ae281Mark J Musante nomem();
fa9e4066f08beec538e775443c5be79dd423fcabahrens
b6825278356f1c9ddb8765d2f2b1d4fb62be1dbdsjelinek cb.cb_sortcol = sortcol;
d5b5bb256c576fe5ef26e0795bd40abe77f93246Rich Morris cb.cb_flags = flags;
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock cb.cb_proplist = proplist;
fa9e4066f08beec538e775443c5be79dd423fcabahrens cb.cb_types = types;
ae1726b6ae69a6882b0d520f4bc3433f501f2065Chris Gerhard cb.cb_depth_limit = limit;
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi /*
842727c2f41f01b380de4f5e787d905702870f23Chris Kirby * If cb_proplist is provided then in the zfs_handles created we
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi * retain only those properties listed in cb_proplist and sortcol.
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi * The rest are pruned. So, the caller should make sure that no other
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi * properties other than those listed in cb_proplist/sortcol are
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi * accessed.
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi *
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens * If cb_proplist is NULL then we retain all the properties. We
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens * always retain the zoned property, which some other properties
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens * need (userquota & friends), and the createtxg property, which
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens * we need to sort snapshots.
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi */
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi if (cb.cb_proplist && *cb.cb_proplist) {
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi zprop_list_t *p = *cb.cb_proplist;
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi while (p) {
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi if (p->pl_prop >= ZFS_PROP_TYPE &&
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi p->pl_prop < ZFS_NUM_PROPS) {
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi cb.cb_props_table[p->pl_prop] = B_TRUE;
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi }
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi p = p->pl_next;
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi }
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi while (sortcol) {
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi if (sortcol->sc_prop >= ZFS_PROP_TYPE &&
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi sortcol->sc_prop < ZFS_NUM_PROPS) {
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi cb.cb_props_table[sortcol->sc_prop] = B_TRUE;
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi }
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi sortcol = sortcol->sc_next;
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi }
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens cb.cb_props_table[ZFS_PROP_ZONED] = B_TRUE;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens cb.cb_props_table[ZFS_PROP_CREATETXG] = B_TRUE;
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi } else {
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi (void) memset(cb.cb_props_table, B_TRUE,
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi sizeof (cb.cb_props_table));
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi }
2e5e9e19867a0d75685f5beb2fe1b0e31491d49bSanjeev Bagewadi
a8b6ddaf31808c845e00161dda0a3d1fe31ae281Mark J Musante if ((cb.cb_avl = uu_avl_create(avl_pool, NULL, UU_DEFAULT)) == NULL)
a8b6ddaf31808c845e00161dda0a3d1fe31ae281Mark J Musante nomem();
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (argc == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If given no arguments, iterate over all datasets.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
d5b5bb256c576fe5ef26e0795bd40abe77f93246Rich Morris cb.cb_flags |= ZFS_ITER_RECURSE;
99653d4ee642c6528e88224f12409a5f23060994eschrock ret = zfs_iter_root(g_zfs, zfs_callback, &cb);
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens int i;
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfs_handle_t *zhp;
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfs_type_t argtype;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If we're recursive, then we always allow filesystems as
fa9e4066f08beec538e775443c5be79dd423fcabahrens * arguments. If we also are interested in snapshots, then we
fa9e4066f08beec538e775443c5be79dd423fcabahrens * can take volumes as well.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens argtype = types;
d5b5bb256c576fe5ef26e0795bd40abe77f93246Rich Morris if (flags & ZFS_ITER_RECURSE) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens argtype |= ZFS_TYPE_FILESYSTEM;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (types & ZFS_TYPE_SNAPSHOT)
fa9e4066f08beec538e775443c5be79dd423fcabahrens argtype |= ZFS_TYPE_VOLUME;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (i = 0; i < argc; i++) {
d5b5bb256c576fe5ef26e0795bd40abe77f93246Rich Morris if (flags & ZFS_ITER_ARGS_CAN_BE_PATHS) {
5aba80db367b061758a29154d304977d00d8e4f4ck zhp = zfs_path_to_zhandle(g_zfs, argv[i],
5aba80db367b061758a29154d304977d00d8e4f4ck argtype);
5aba80db367b061758a29154d304977d00d8e4f4ck } else {
5aba80db367b061758a29154d304977d00d8e4f4ck zhp = zfs_open(g_zfs, argv[i], argtype);
5aba80db367b061758a29154d304977d00d8e4f4ck }
5aba80db367b061758a29154d304977d00d8e4f4ck if (zhp != NULL)
99653d4ee642c6528e88224f12409a5f23060994eschrock ret |= zfs_callback(zhp, &cb);
fa9e4066f08beec538e775443c5be79dd423fcabahrens else
fa9e4066f08beec538e775443c5be79dd423fcabahrens ret = 1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * At this point we've got our AVL tree full of zfs handles, so iterate
fa9e4066f08beec538e775443c5be79dd423fcabahrens * over each one and execute the real user callback.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (node = uu_avl_first(cb.cb_avl); node != NULL;
fa9e4066f08beec538e775443c5be79dd423fcabahrens node = uu_avl_next(cb.cb_avl, node))
fa9e4066f08beec538e775443c5be79dd423fcabahrens ret |= callback(node->zn_handle, data);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Finally, clean up the AVL tree.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
a8b6ddaf31808c845e00161dda0a3d1fe31ae281Mark J Musante if ((walk = uu_avl_walk_start(cb.cb_avl, UU_WALK_ROBUST)) == NULL)
a8b6ddaf31808c845e00161dda0a3d1fe31ae281Mark J Musante nomem();
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens while ((node = uu_avl_walk_next(walk)) != NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens uu_avl_remove(cb.cb_avl, node);
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfs_close(node->zn_handle);
fa9e4066f08beec538e775443c5be79dd423fcabahrens free(node);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens uu_avl_walk_end(walk);
fa9e4066f08beec538e775443c5be79dd423fcabahrens uu_avl_destroy(cb.cb_avl);
fa9e4066f08beec538e775443c5be79dd423fcabahrens uu_avl_pool_destroy(avl_pool);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (ret);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}