summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Caputi <[email protected]>2019-04-01 14:58:59 -0400
committerBrian Behlendorf <[email protected]>2019-04-01 11:58:59 -0700
commitdf583073eb49e602d07ff4ec7d769732b9b9f077 (patch)
treeda83ad73e760ef2b6828ae828512bacc21ee11e6
parente03b25a56443c79a53327806fa4cc5a2b6acd70c (diff)
Do not iterate through filesystems unnecessarily
Currently, when attempting to list snapshots ZFS may do a lot of extra work checking child datasets. This is because the code does not realize that it will not be able to reach any snapshots contained within snapshots that are at the depth limit since the snapshots of those datasets are counted as an additional layer deeper. This patch corrects this issue. In addition, this patch adds the ability to do perform the commands: $ zfs list -t snapshot <dataset> $ zfs get -t snapshot <prop> <dataset> as a convenient way to list out properties of all snapshots of a given dataset without having to use the depth limit. Reviewed-by: Alek Pinchuk <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Richard Laager <[email protected]> Reviewed-by: Matt Ahrens <[email protected]> Reviewed-by: George Melikov <[email protected]> Signed-off-by: Tom Caputi <[email protected]> Closes #8539
-rw-r--r--cmd/zfs/zfs_iter.c25
-rw-r--r--cmd/zfs/zfs_main.c20
-rw-r--r--tests/zfs-tests/include/libtest.shlib1
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_009_pos.ksh5
4 files changed, 45 insertions, 6 deletions
diff --git a/cmd/zfs/zfs_iter.c b/cmd/zfs/zfs_iter.c
index 9ad691938..d10bbed7d 100644
--- a/cmd/zfs/zfs_iter.c
+++ b/cmd/zfs/zfs_iter.c
@@ -134,16 +134,31 @@ 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 |
- ZFS_TYPE_BOOKMARK)) == 0) && include_snaps)
+ ZFS_TYPE_BOOKMARK)) == 0) && include_snaps) {
(void) zfs_iter_snapshots(zhp,
- (cb->cb_flags & ZFS_ITER_SIMPLE) != 0, zfs_callback,
- data, 0, 0);
+ (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)
+ ZFS_TYPE_BOOKMARK)) == 0) && include_bmarks) {
(void) zfs_iter_bookmarks(zhp, zfs_callback, data);
+ }
+
cb->cb_depth--;
}
diff --git a/cmd/zfs/zfs_main.c b/cmd/zfs/zfs_main.c
index 21c4d4334..57eb30528 100644
--- a/cmd/zfs/zfs_main.c
+++ b/cmd/zfs/zfs_main.c
@@ -1922,6 +1922,16 @@ zfs_do_get(int argc, char **argv)
fields = argv[0];
+ /*
+ * Handle users who want to get all snapshots of the current
+ * dataset (ex. 'zfs get -t snapshot refer <dataset>').
+ */
+ if (types == ZFS_TYPE_SNAPSHOT &&
+ (flags & ZFS_ITER_RECURSE) == 0 && limit == 0) {
+ flags |= (ZFS_ITER_DEPTH_LIMIT | ZFS_ITER_RECURSE);
+ limit = 1;
+ }
+
if (zprop_get_list(g_zfs, fields, &cb.cb_proplist, ZFS_TYPE_DATASET)
!= 0)
usage(B_FALSE);
@@ -3417,6 +3427,16 @@ zfs_do_list(int argc, char **argv)
types &= ~ZFS_TYPE_SNAPSHOT;
/*
+ * Handle users who want to list all snapshots of the current
+ * dataset (ex. 'zfs list -t snapshot <dataset>').
+ */
+ if (types == ZFS_TYPE_SNAPSHOT &&
+ (flags & ZFS_ITER_RECURSE) == 0 && limit == 0) {
+ flags |= (ZFS_ITER_DEPTH_LIMIT | ZFS_ITER_RECURSE);
+ limit = 1;
+ }
+
+ /*
* If the user specifies '-o all', the zprop_get_list() doesn't
* normally include the name of the dataset. For 'zfs list', we always
* want this property to be first.
diff --git a/tests/zfs-tests/include/libtest.shlib b/tests/zfs-tests/include/libtest.shlib
index 748a4f96d..ea9448353 100644
--- a/tests/zfs-tests/include/libtest.shlib
+++ b/tests/zfs-tests/include/libtest.shlib
@@ -2594,7 +2594,6 @@ function verify_opt_p_ops
"when ops is $ops."
fi
log_must datasetexists $dataset
- log_mustnot snapexists $dataset
;;
*)
log_fail "$ops is not supported."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_009_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_009_pos.ksh
index 383b19ca8..2d97c5918 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_009_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_009_pos.ksh
@@ -87,5 +87,10 @@ for dp in ${depth_array[@]}; do
(( old_val=dp ))
done
+# Ensure 'zfs get -t snapshot <dataset>' works as though -d 1 was specified
+log_must eval "zfs get -H -t snapshot -o name creation $DEPTH_FS > $DEPTH_OUTPUT"
+log_must eval "zfs get -H -t snapshot -d 1 -o name creation $DEPTH_FS > $EXPECT_OUTPUT"
+log_must diff $DEPTH_OUTPUT $EXPECT_OUTPUT
+
log_pass "'zfs get -d <n>' should get expected output."