Update to onnv_147
[zfs.git] / cmd / zfs / zfs_iter.c
index a22370a..e2ab90e 100644 (file)
@@ -19,8 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #include <libintl.h>
@@ -53,11 +52,14 @@ typedef struct zfs_node {
 } zfs_node_t;
 
 typedef struct callback_data {
-       uu_avl_t        *cb_avl;
-       int             cb_flags;
-       zfs_type_t      cb_types;
-       zfs_sort_column_t *cb_sortcol;
-       zprop_list_t    **cb_proplist;
+       uu_avl_t                *cb_avl;
+       int                     cb_flags;
+       zfs_type_t              cb_types;
+       zfs_sort_column_t       *cb_sortcol;
+       zprop_list_t            **cb_proplist;
+       int                     cb_depth_limit;
+       int                     cb_depth;
+       uint8_t                 cb_props_table[ZFS_NUM_PROPS];
 } callback_data_t;
 
 uu_avl_pool_t *avl_pool;
@@ -98,10 +100,18 @@ zfs_callback(zfs_handle_t *zhp, void *data)
                uu_avl_node_init(node, &node->zn_avlnode, avl_pool);
                if (uu_avl_find(cb->cb_avl, node, cb->cb_sortcol,
                    &idx) == NULL) {
-                       if (cb->cb_proplist &&
-                           zfs_expand_proplist(zhp, cb->cb_proplist) != 0) {
-                               free(node);
-                               return (-1);
+                       if (cb->cb_proplist) {
+                               if ((*cb->cb_proplist) &&
+                                   !(*cb->cb_proplist)->pl_all)
+                                       zfs_prune_proplist(zhp,
+                                           cb->cb_props_table);
+
+                               if (zfs_expand_proplist(zhp, cb->cb_proplist,
+                                   (cb->cb_flags & ZFS_ITER_RECVD_PROPS))
+                                   != 0) {
+                                       free(node);
+                                       return (-1);
+                               }
                        }
                        uu_avl_insert(cb->cb_avl, node, idx);
                        dontclose = 1;
@@ -113,11 +123,15 @@ zfs_callback(zfs_handle_t *zhp, void *data)
        /*
         * Recurse if necessary.
         */
-       if (cb->cb_flags & ZFS_ITER_RECURSE) {
+       if (cb->cb_flags & ZFS_ITER_RECURSE &&
+           ((cb->cb_flags & ZFS_ITER_DEPTH_LIMIT) == 0 ||
+           cb->cb_depth < cb->cb_depth_limit)) {
+               cb->cb_depth++;
                if (zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM)
                        (void) zfs_iter_filesystems(zhp, zfs_callback, data);
                if ((zfs_get_type(zhp) != ZFS_TYPE_SNAPSHOT) && include_snaps)
                        (void) zfs_iter_snapshots(zhp, zfs_callback, data);
+               cb->cb_depth--;
        }
 
        if (!dontclose)
@@ -325,10 +339,10 @@ zfs_sort(const void *larg, const void *rarg, void *data)
 
 int
 zfs_for_each(int argc, char **argv, int flags, zfs_type_t types,
-    zfs_sort_column_t *sortcol, zprop_list_t **proplist,
+    zfs_sort_column_t *sortcol, zprop_list_t **proplist, int limit,
     zfs_iter_f callback, void *data)
 {
-       callback_data_t cb;
+       callback_data_t cb = {0};
        int ret = 0;
        zfs_node_t *node;
        uu_avl_walk_t *walk;
@@ -336,22 +350,55 @@ zfs_for_each(int argc, char **argv, int flags, zfs_type_t types,
        avl_pool = uu_avl_pool_create("zfs_pool", sizeof (zfs_node_t),
            offsetof(zfs_node_t, zn_avlnode), zfs_sort, UU_DEFAULT);
 
-       if (avl_pool == NULL) {
-               (void) fprintf(stderr,
-                   gettext("internal error: out of memory\n"));
-               exit(1);
-       }
+       if (avl_pool == NULL)
+               nomem();
 
        cb.cb_sortcol = sortcol;
        cb.cb_flags = flags;
        cb.cb_proplist = proplist;
        cb.cb_types = types;
-       if ((cb.cb_avl = uu_avl_create(avl_pool, NULL, UU_DEFAULT)) == NULL) {
-               (void) fprintf(stderr,
-                   gettext("internal error: out of memory\n"));
-               exit(1);
+       cb.cb_depth_limit = limit;
+       /*
+        * If cb_proplist is provided then in the zfs_handles created we
+        * retain only those properties listed in cb_proplist and sortcol.
+        * The rest are pruned. So, the caller should make sure that no other
+        * properties other than those listed in cb_proplist/sortcol are
+        * accessed.
+        *
+        * If cb_proplist is NULL then we retain all the properties.  We
+        * always retain the zoned property, which some other properties
+        * need (userquota & friends), and the createtxg property, which
+        * we need to sort snapshots.
+        */
+       if (cb.cb_proplist && *cb.cb_proplist) {
+               zprop_list_t *p = *cb.cb_proplist;
+
+               while (p) {
+                       if (p->pl_prop >= ZFS_PROP_TYPE &&
+                           p->pl_prop < ZFS_NUM_PROPS) {
+                               cb.cb_props_table[p->pl_prop] = B_TRUE;
+                       }
+                       p = p->pl_next;
+               }
+
+               while (sortcol) {
+                       if (sortcol->sc_prop >= ZFS_PROP_TYPE &&
+                           sortcol->sc_prop < ZFS_NUM_PROPS) {
+                               cb.cb_props_table[sortcol->sc_prop] = B_TRUE;
+                       }
+                       sortcol = sortcol->sc_next;
+               }
+
+               cb.cb_props_table[ZFS_PROP_ZONED] = B_TRUE;
+               cb.cb_props_table[ZFS_PROP_CREATETXG] = B_TRUE;
+       } else {
+               (void) memset(cb.cb_props_table, B_TRUE,
+                   sizeof (cb.cb_props_table));
        }
 
+       if ((cb.cb_avl = uu_avl_create(avl_pool, NULL, UU_DEFAULT)) == NULL)
+               nomem();
+
        if (argc == 0) {
                /*
                 * If given no arguments, iterate over all datasets.
@@ -400,11 +447,8 @@ zfs_for_each(int argc, char **argv, int flags, zfs_type_t types,
        /*
         * Finally, clean up the AVL tree.
         */
-       if ((walk = uu_avl_walk_start(cb.cb_avl, UU_WALK_ROBUST)) == NULL) {
-               (void) fprintf(stderr,
-                   gettext("internal error: out of memory"));
-               exit(1);
-       }
+       if ((walk = uu_avl_walk_start(cb.cb_avl, UU_WALK_ROBUST)) == NULL)
+               nomem();
 
        while ((node = uu_avl_walk_next(walk)) != NULL) {
                uu_avl_remove(cb.cb_avl, node);