]> git.proxmox.com Git - mirror_zfs.git/blobdiff - cmd/zfs/zfs_iter.c
Do not iterate through filesystems unnecessarily
[mirror_zfs.git] / cmd / zfs / zfs_iter.c
index 8892d91f24bad380198f17547e3b0a0925287279..d10bbed7dbd62101fbb07d48dd1bbb2de88b6453 100644 (file)
@@ -23,6 +23,7 @@
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
  * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
  */
 
 #include <libintl.h>
@@ -30,6 +31,7 @@
 #include <stddef.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <strings.h>
 
 #include <libzfs.h>
@@ -71,7 +73,7 @@ uu_avl_pool_t *avl_pool;
  * Include snaps if they were requested or if this a zfs list where types
  * were not specified and the "listsnapshots" property is set on this pool.
  */
-static int
+static boolean_t
 zfs_include_snapshots(zfs_handle_t *zhp, callback_data_t *cb)
 {
        zpool_handle_t *zph;
@@ -91,8 +93,9 @@ static int
 zfs_callback(zfs_handle_t *zhp, void *data)
 {
        callback_data_t *cb = data;
-       int dontclose = 0;
-       int include_snaps = zfs_include_snapshots(zhp, cb);
+       boolean_t should_close = B_TRUE;
+       boolean_t include_snaps = zfs_include_snapshots(zhp, cb);
+       boolean_t include_bmarks = (cb->cb_types & ZFS_TYPE_BOOKMARK);
 
        if ((zfs_get_type(zhp) & cb->cb_types) ||
            ((zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT) && include_snaps)) {
@@ -118,7 +121,7 @@ zfs_callback(zfs_handle_t *zhp, void *data)
                                }
                        }
                        uu_avl_insert(cb->cb_avl, node, idx);
-                       dontclose = 1;
+                       should_close = B_FALSE;
                } else {
                        free(node);
                }
@@ -131,17 +134,35 @@ zfs_callback(zfs_handle_t *zhp, void *data)
            ((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)
+
+               /*
+                * If we are not looking for filesystems, we don't need to
+                * recurse into filesystems when we are at our depth limit.
+                */
+               if ((cb->cb_depth < cb->cb_depth_limit ||
+                   (cb->cb_flags & ZFS_ITER_DEPTH_LIMIT) == 0 ||
+                   (cb->cb_types &
+                   (ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME))) &&
+                   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) {
+               }
+
+               if (((zfs_get_type(zhp) & (ZFS_TYPE_SNAPSHOT |
+                   ZFS_TYPE_BOOKMARK)) == 0) && include_snaps) {
                        (void) zfs_iter_snapshots(zhp,
-                           (cb->cb_flags & ZFS_ITER_SIMPLE) != 0, zfs_callback,
-                           data);
+                           (cb->cb_flags & ZFS_ITER_SIMPLE) != 0,
+                           zfs_callback, data, 0, 0);
+               }
+
+               if (((zfs_get_type(zhp) & (ZFS_TYPE_SNAPSHOT |
+                   ZFS_TYPE_BOOKMARK)) == 0) && include_bmarks) {
+                       (void) zfs_iter_bookmarks(zhp, zfs_callback, data);
                }
+
                cb->cb_depth--;
        }
 
-       if (!dontclose)
+       if (should_close)
                zfs_close(zhp);
 
        return (0);
@@ -328,9 +349,9 @@ zfs_sort(const void *larg, const void *rarg, void *data)
                        rstr = rbuf;
                } else {
                        lvalid = zfs_prop_valid_for_type(psc->sc_prop,
-                           zfs_get_type(l));
+                           zfs_get_type(l), B_FALSE);
                        rvalid = zfs_prop_valid_for_type(psc->sc_prop,
-                           zfs_get_type(r));
+                           zfs_get_type(r), B_FALSE);
 
                        if (lvalid)
                                (void) zfs_prop_get_numeric(l, psc->sc_prop,
@@ -439,13 +460,13 @@ zfs_for_each(int argc, char **argv, int flags, zfs_type_t types,
 
                /*
                 * If we're recursive, then we always allow filesystems as
-                * arguments.  If we also are interested in snapshots, then we
-                * can take volumes as well.
+                * arguments.  If we also are interested in snapshots or
+                * bookmarks, then we can take volumes as well.
                 */
                argtype = types;
                if (flags & ZFS_ITER_RECURSE) {
                        argtype |= ZFS_TYPE_FILESYSTEM;
-                       if (types & ZFS_TYPE_SNAPSHOT)
+                       if (types & (ZFS_TYPE_SNAPSHOT | ZFS_TYPE_BOOKMARK))
                                argtype |= ZFS_TYPE_VOLUME;
                }