svn commit: r302643 - vendor-sys/illumos/dist/uts/common/fs/zfs vendor-sys/illumos/dist/uts/common/fs/zfs/sys vendor/illumos/dist/cmd/zfs vendor/illumos/dist/lib/libzfs/common

Andriy Gapon avg at FreeBSD.org
Tue Jul 12 11:21:43 UTC 2016


Author: avg
Date: Tue Jul 12 11:21:41 2016
New Revision: 302643
URL: https://svnweb.freebsd.org/changeset/base/302643

Log:
  6902 speed up listing of snapshots if requesting name only and sorting by name
  
  illumos/illumos-gate at 0d8fa8f8eba3ea46bc79d73445009505d1dd5d7d
  https://github.com/illumos/illumos-gate/commit/0d8fa8f8eba3ea46bc79d73445009505d1dd5d7d
  
  https://www.illumos.org/issues/6902
    pjd has authored and commited a patch in Jan 21, 2012 that substanially speeds
    up zfs snapshot listing if requesting only the name property and sorting by
    name.
    In this special case, the snapshot properties do not need to be loaded. This
    code has been adopted by zfsonlinux on May 29, 2012.
    Commit message from pjd:
         Dramatically optimize listing snapshots when user requests only
         snapshot
         names and wants to sort them by name, ie. when executes:
            1. zfs list -t snapshot -o name -s name
         Because only name is needed we don't have to read all snapshot
         properties.
         Below you can find how long does it take to list 34509 snapshots from
         a single
         disk pool before and after this change with cold and warm cache:
         before:
            1. time zfs list -t snapshot -o name -s name > /dev/null
               cold cache: 525s
               warm cache: 218s
         after:
            1. time zfs list -t snapshot -o name -s name > /dev/null
               cold cache: 1.7s
               warm cache: 1.1s
    References:
    http://svnweb.freebsd.org/base?view=revision&revision=230438
    https://github.com/freebsd/freebsd/commit/8e3e9863
    https://github.com/zfsonlinux/zfs/commit/0cee2406
  
  Reviewed by: Matthew Ahrens <mahrens at delphix.com>
  Reviewed by: Pawel Dawidek <pjd at freebsd.org>
  Reviewed by: Brian Behlendorf <behlendorf1 at llnl.gov>
  Approved by: Garrett D'Amore <garrett at damore.org>
  Author: Martin Matuska <martin at matuska.org>

Modified:
  vendor/illumos/dist/cmd/zfs/zfs_iter.c
  vendor/illumos/dist/cmd/zfs/zfs_iter.h
  vendor/illumos/dist/cmd/zfs/zfs_main.c
  vendor/illumos/dist/lib/libzfs/common/libzfs.h
  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_iter.c
  vendor/illumos/dist/lib/libzfs/common/libzfs_sendrecv.c

Changes in other areas also in this revision:
Modified:
  vendor-sys/illumos/dist/uts/common/fs/zfs/sys/zfs_ioctl.h
  vendor-sys/illumos/dist/uts/common/fs/zfs/zfs_ioctl.c

Modified: vendor/illumos/dist/cmd/zfs/zfs_iter.c
==============================================================================
--- vendor/illumos/dist/cmd/zfs/zfs_iter.c	Tue Jul 12 11:20:00 2016	(r302642)
+++ vendor/illumos/dist/cmd/zfs/zfs_iter.c	Tue Jul 12 11:21:41 2016	(r302643)
@@ -21,6 +21,7 @@
 
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012 Pawel Jakub Dawidek. All rights reserved.
  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  * Copyright (c) 2013 by Delphix. All rights reserved.
  */
@@ -136,7 +137,9 @@ zfs_callback(zfs_handle_t *zhp, void *da
 			(void) zfs_iter_filesystems(zhp, zfs_callback, data);
 		if (((zfs_get_type(zhp) & (ZFS_TYPE_SNAPSHOT |
 		    ZFS_TYPE_BOOKMARK)) == 0) && include_snaps)
-			(void) zfs_iter_snapshots(zhp, zfs_callback, data);
+			(void) zfs_iter_snapshots(zhp,
+			    (cb->cb_flags & ZFS_ITER_SIMPLE) != 0, zfs_callback,
+			    data);
 		if (((zfs_get_type(zhp) & (ZFS_TYPE_SNAPSHOT |
 		    ZFS_TYPE_BOOKMARK)) == 0) && include_bmarks)
 			(void) zfs_iter_bookmarks(zhp, zfs_callback, data);
@@ -193,6 +196,14 @@ zfs_free_sort_columns(zfs_sort_column_t 
 	}
 }
 
+boolean_t
+zfs_sort_only_by_name(const zfs_sort_column_t *sc)
+{
+
+	return (sc != NULL && sc->sc_next == NULL &&
+	    sc->sc_prop == ZFS_PROP_NAME);
+}
+
 /* ARGSUSED */
 static int
 zfs_compare(const void *larg, const void *rarg, void *unused)
@@ -233,7 +244,13 @@ zfs_compare(const void *larg, const void
 			lcreate = zfs_prop_get_int(l, ZFS_PROP_CREATETXG);
 			rcreate = zfs_prop_get_int(r, ZFS_PROP_CREATETXG);
 
-			if (lcreate < rcreate)
+			/*
+			 * Both lcreate and rcreate being 0 means we don't have
+			 * properties and we should compare full name.
+			 */
+			if (lcreate == 0 && rcreate == 0)
+				ret = strcmp(lat + 1, rat + 1);
+			else if (lcreate < rcreate)
 				ret = -1;
 			else if (lcreate > rcreate)
 				ret = 1;
@@ -299,7 +316,14 @@ zfs_sort(const void *larg, const void *r
 			if (rvalid)
 				verify(nvlist_lookup_string(rval,
 				    ZPROP_VALUE, &rstr) == 0);
+		} else if (psc->sc_prop == ZFS_PROP_NAME) {
+			lvalid = rvalid = B_TRUE;
+
+			(void) strlcpy(lbuf, zfs_get_name(l), sizeof (lbuf));
+			(void) strlcpy(rbuf, zfs_get_name(r), sizeof (rbuf));
 
+			lstr = lbuf;
+			rstr = rbuf;
 		} else if (zfs_prop_is_string(psc->sc_prop)) {
 			lvalid = (zfs_prop_get(l, psc->sc_prop, lbuf,
 			    sizeof (lbuf), NULL, NULL, 0, B_TRUE) == 0);

Modified: vendor/illumos/dist/cmd/zfs/zfs_iter.h
==============================================================================
--- vendor/illumos/dist/cmd/zfs/zfs_iter.h	Tue Jul 12 11:20:00 2016	(r302642)
+++ vendor/illumos/dist/cmd/zfs/zfs_iter.h	Tue Jul 12 11:21:41 2016	(r302643)
@@ -22,6 +22,7 @@
 /*
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ * Copyright (c) 2011-2012 Pawel Jakub Dawidek. All rights reserved.
  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  */
 
@@ -45,12 +46,14 @@ typedef struct zfs_sort_column {
 #define	ZFS_ITER_PROP_LISTSNAPS    (1 << 2)
 #define	ZFS_ITER_DEPTH_LIMIT	   (1 << 3)
 #define	ZFS_ITER_RECVD_PROPS	   (1 << 4)
-#define	ZFS_ITER_LITERAL_PROPS	   (1 << 5)
+#define	ZFS_ITER_SIMPLE		   (1 << 5)
+#define	ZFS_ITER_LITERAL_PROPS	   (1 << 6)
 
 int zfs_for_each(int, char **, int options, zfs_type_t,
     zfs_sort_column_t *, zprop_list_t **, int, zfs_iter_f, void *);
 int zfs_add_sort_column(zfs_sort_column_t **, const char *, boolean_t);
 void zfs_free_sort_columns(zfs_sort_column_t *);
+boolean_t zfs_sort_only_by_name(const zfs_sort_column_t *);
 
 #ifdef	__cplusplus
 }

Modified: vendor/illumos/dist/cmd/zfs/zfs_main.c
==============================================================================
--- vendor/illumos/dist/cmd/zfs/zfs_main.c	Tue Jul 12 11:20:00 2016	(r302642)
+++ vendor/illumos/dist/cmd/zfs/zfs_main.c	Tue Jul 12 11:21:41 2016	(r302643)
@@ -24,6 +24,7 @@
  * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
  * Copyright 2012 Milan Jurik. All rights reserved.
  * Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2011-2012 Pawel Jakub Dawidek. All rights reserved.
  * Copyright (c) 2013 Steven Hartland.  All rights reserved.
  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  * Copyright (c) 2014 Integros [integros.com]
@@ -2968,7 +2969,12 @@ print_dataset(zfs_handle_t *zhp, list_cb
 			first = B_FALSE;
 		}
 
-		if (pl->pl_prop != ZPROP_INVAL) {
+		if (pl->pl_prop == ZFS_PROP_NAME) {
+			(void) strlcpy(property, zfs_get_name(zhp),
+			    sizeof (property));
+			propstr = property;
+			right_justify = zfs_prop_align_right(pl->pl_prop);
+		} else if (pl->pl_prop != ZPROP_INVAL) {
 			if (zfs_prop_get(zhp, pl->pl_prop, property,
 			    sizeof (property), NULL, NULL, 0,
 			    cb->cb_literal) != 0)
@@ -3141,6 +3147,13 @@ zfs_do_list(int argc, char **argv)
 		fields = default_fields;
 
 	/*
+	 * If we are only going to list snapshot names and sort by name,
+	 * then we can use faster version.
+	 */
+	if (strcmp(fields, "name") == 0 && zfs_sort_only_by_name(sortcol))
+		flags |= ZFS_ITER_SIMPLE;
+
+	/*
 	 * If "-o space" and no types were specified, don't display snapshots.
 	 */
 	if (strcmp(fields, "space") == 0 && types_specified == B_FALSE)
@@ -3449,7 +3462,7 @@ zfs_do_rollback(int argc, char **argv)
 	cb.cb_create = zfs_prop_get_int(snap, ZFS_PROP_CREATETXG);
 	cb.cb_first = B_TRUE;
 	cb.cb_error = 0;
-	if ((ret = zfs_iter_snapshots(zhp, rollback_check, &cb)) != 0)
+	if ((ret = zfs_iter_snapshots(zhp, B_FALSE, rollback_check, &cb)) != 0)
 		goto out;
 	if ((ret = zfs_iter_bookmarks(zhp, rollback_check, &cb)) != 0)
 		goto out;

Modified: vendor/illumos/dist/lib/libzfs/common/libzfs.h
==============================================================================
--- vendor/illumos/dist/lib/libzfs/common/libzfs.h	Tue Jul 12 11:20:00 2016	(r302642)
+++ vendor/illumos/dist/lib/libzfs/common/libzfs.h	Tue Jul 12 11:21:41 2016	(r302643)
@@ -21,6 +21,7 @@
 
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011 Pawel Jakub Dawidek. All rights reserved.
  * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
  * Copyright (c) 2012, Joyent, Inc. All rights reserved.
  * Copyright (c) 2013 Steven Hartland. All rights reserved.
@@ -534,7 +535,7 @@ extern int zfs_iter_root(libzfs_handle_t
 extern int zfs_iter_children(zfs_handle_t *, zfs_iter_f, void *);
 extern int zfs_iter_dependents(zfs_handle_t *, boolean_t, zfs_iter_f, void *);
 extern int zfs_iter_filesystems(zfs_handle_t *, zfs_iter_f, void *);
-extern int zfs_iter_snapshots(zfs_handle_t *, zfs_iter_f, void *);
+extern int zfs_iter_snapshots(zfs_handle_t *, boolean_t, zfs_iter_f, void *);
 extern int zfs_iter_snapshots_sorted(zfs_handle_t *, zfs_iter_f, void *);
 extern int zfs_iter_snapspec(zfs_handle_t *, const char *, zfs_iter_f, void *);
 extern int zfs_iter_bookmarks(zfs_handle_t *, zfs_iter_f, void *);

Modified: vendor/illumos/dist/lib/libzfs/common/libzfs_dataset.c
==============================================================================
--- vendor/illumos/dist/lib/libzfs/common/libzfs_dataset.c	Tue Jul 12 11:20:00 2016	(r302642)
+++ vendor/illumos/dist/lib/libzfs/common/libzfs_dataset.c	Tue Jul 12 11:21:41 2016	(r302643)
@@ -24,6 +24,7 @@
  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
  * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
  * Copyright (c) 2012 DEY Storage Systems, Inc.  All rights reserved.
+ * Copyright (c) 2011-2012 Pawel Jakub Dawidek. All rights reserved.
  * Copyright (c) 2013 Martin Matuska. All rights reserved.
  * Copyright (c) 2013 Steven Hartland. All rights reserved.
  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
@@ -519,6 +520,22 @@ make_dataset_handle_zc(libzfs_handle_t *
 }
 
 zfs_handle_t *
+make_dataset_simple_handle_zc(zfs_handle_t *pzhp, zfs_cmd_t *zc)
+{
+	zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1);
+
+	if (zhp == NULL)
+		return (NULL);
+
+	zhp->zfs_hdl = pzhp->zfs_hdl;
+	(void) strlcpy(zhp->zfs_name, zc->zc_name, sizeof (zhp->zfs_name));
+	zhp->zfs_head_type = pzhp->zfs_type;
+	zhp->zfs_type = ZFS_TYPE_SNAPSHOT;
+	zhp->zpool_hdl = zpool_handle(zhp);
+	return (zhp);
+}
+
+zfs_handle_t *
 zfs_handle_dup(zfs_handle_t *zhp_orig)
 {
 	zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1);
@@ -3776,7 +3793,7 @@ zfs_rollback(zfs_handle_t *zhp, zfs_hand
 	cb.cb_force = force;
 	cb.cb_target = snap->zfs_name;
 	cb.cb_create = zfs_prop_get_int(snap, ZFS_PROP_CREATETXG);
-	(void) zfs_iter_snapshots(zhp, rollback_destroy, &cb);
+	(void) zfs_iter_snapshots(zhp, B_FALSE, rollback_destroy, &cb);
 	(void) zfs_iter_bookmarks(zhp, rollback_destroy, &cb);
 
 	if (cb.cb_error)

Modified: vendor/illumos/dist/lib/libzfs/common/libzfs_impl.h
==============================================================================
--- vendor/illumos/dist/lib/libzfs/common/libzfs_impl.h	Tue Jul 12 11:20:00 2016	(r302642)
+++ vendor/illumos/dist/lib/libzfs/common/libzfs_impl.h	Tue Jul 12 11:21:41 2016	(r302643)
@@ -21,6 +21,7 @@
 
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011 Pawel Jakub Dawidek. All rights reserved.
  * Copyright (c) 2013 by Delphix. All rights reserved.
  */
 
@@ -149,7 +150,7 @@ int zpool_standard_error_fmt(libzfs_hand
 int get_dependents(libzfs_handle_t *, boolean_t, const char *, char ***,
     size_t *);
 zfs_handle_t *make_dataset_handle_zc(libzfs_handle_t *, zfs_cmd_t *);
-
+zfs_handle_t *make_dataset_simple_handle_zc(zfs_handle_t *, zfs_cmd_t *);
 
 int zprop_parse_value(libzfs_handle_t *, nvpair_t *, int, zfs_type_t,
     nvlist_t *, char **, uint64_t *, const char *);

Modified: vendor/illumos/dist/lib/libzfs/common/libzfs_iter.c
==============================================================================
--- vendor/illumos/dist/lib/libzfs/common/libzfs_iter.c	Tue Jul 12 11:20:00 2016	(r302642)
+++ vendor/illumos/dist/lib/libzfs/common/libzfs_iter.c	Tue Jul 12 11:21:41 2016	(r302643)
@@ -22,6 +22,7 @@
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2013, 2015 by Delphix. All rights reserved.
+ * Copyright (c) 2012 Pawel Jakub Dawidek. All rights reserved.
  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
  */
 
@@ -137,7 +138,8 @@ zfs_iter_filesystems(zfs_handle_t *zhp, 
  * Iterate over all snapshots
  */
 int
-zfs_iter_snapshots(zfs_handle_t *zhp, zfs_iter_f func, void *data)
+zfs_iter_snapshots(zfs_handle_t *zhp, boolean_t simple, zfs_iter_f func,
+    void *data)
 {
 	zfs_cmd_t zc = { 0 };
 	zfs_handle_t *nzhp;
@@ -147,15 +149,19 @@ zfs_iter_snapshots(zfs_handle_t *zhp, zf
 	    zhp->zfs_type == ZFS_TYPE_BOOKMARK)
 		return (0);
 
+	zc.zc_simple = simple;
+
 	if (zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0)
 		return (-1);
 	while ((ret = zfs_do_list_ioctl(zhp, ZFS_IOC_SNAPSHOT_LIST_NEXT,
 	    &zc)) == 0) {
 
-		if ((nzhp = make_dataset_handle_zc(zhp->zfs_hdl,
-		    &zc)) == NULL) {
+		if (simple)
+			nzhp = make_dataset_simple_handle_zc(zhp, &zc);
+		else
+			nzhp = make_dataset_handle_zc(zhp->zfs_hdl, &zc);
+		if (nzhp == NULL)
 			continue;
-		}
 
 		if ((ret = func(nzhp, data)) != 0) {
 			zcmd_free_nvlists(&zc);
@@ -285,7 +291,7 @@ zfs_iter_snapshots_sorted(zfs_handle_t *
 	avl_create(&avl, zfs_snapshot_compare,
 	    sizeof (zfs_node_t), offsetof(zfs_node_t, zn_avlnode));
 
-	ret = zfs_iter_snapshots(zhp, zfs_sort_snaps, &avl);
+	ret = zfs_iter_snapshots(zhp, B_FALSE, zfs_sort_snaps, &avl);
 
 	for (node = avl_first(&avl); node != NULL; node = AVL_NEXT(&avl, node))
 		ret |= callback(node->zn_handle, data);
@@ -430,7 +436,7 @@ zfs_iter_children(zfs_handle_t *zhp, zfs
 	if ((ret = zfs_iter_filesystems(zhp, func, data)) != 0)
 		return (ret);
 
-	return (zfs_iter_snapshots(zhp, func, data));
+	return (zfs_iter_snapshots(zhp, B_FALSE, func, data));
 }
 
 
@@ -491,8 +497,10 @@ iter_dependents_cb(zfs_handle_t *zhp, vo
 		isf.next = ida->stack;
 		ida->stack = &isf;
 		err = zfs_iter_filesystems(zhp, iter_dependents_cb, ida);
-		if (err == 0)
-			err = zfs_iter_snapshots(zhp, iter_dependents_cb, ida);
+		if (err == 0) {
+			err = zfs_iter_snapshots(zhp, B_FALSE,
+			    iter_dependents_cb, ida);
+		}
 		ida->stack = isf.next;
 	}
 

Modified: vendor/illumos/dist/lib/libzfs/common/libzfs_sendrecv.c
==============================================================================
--- vendor/illumos/dist/lib/libzfs/common/libzfs_sendrecv.c	Tue Jul 12 11:20:00 2016	(r302642)
+++ vendor/illumos/dist/lib/libzfs/common/libzfs_sendrecv.c	Tue Jul 12 11:21:41 2016	(r302643)
@@ -23,6 +23,7 @@
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
  * Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2012 Pawel Jakub Dawidek. All rights reserved.
  * Copyright (c) 2013 Steven Hartland. All rights reserved.
  * Copyright 2015, OmniTI Computer Consulting, Inc. All rights reserved.
  * Copyright (c) 2014 Integros [integros.com]
@@ -746,7 +747,7 @@ send_iterate_fs(zfs_handle_t *zhp, void 
 	sd->parent_fromsnap_guid = 0;
 	VERIFY(0 == nvlist_alloc(&sd->parent_snaps, NV_UNIQUE_NAME, 0));
 	VERIFY(0 == nvlist_alloc(&sd->snapprops, NV_UNIQUE_NAME, 0));
-	(void) zfs_iter_snapshots(zhp, send_iterate_snap, sd);
+	(void) zfs_iter_snapshots(zhp, B_FALSE, send_iterate_snap, sd);
 	VERIFY(0 == nvlist_add_nvlist(nvfs, "snaps", sd->parent_snaps));
 	VERIFY(0 == nvlist_add_nvlist(nvfs, "snapprops", sd->snapprops));
 	nvlist_free(sd->parent_snaps);


More information about the svn-src-all mailing list