Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 20 Feb 2012 21:10:14 +0000 (UTC)
From:      Martin Matuska <mm@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org
Subject:   svn commit: r231946 - in stable/9: cddl/contrib/opensolaris/cmd/zfs cddl/contrib/opensolaris/lib/libzfs/common sys/cddl/contrib/opensolaris/uts/common/fs/zfs sys/cddl/contrib/opensolaris/uts/common...
Message-ID:  <201202202110.q1KLAEeV068061@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mm
Date: Mon Feb 20 21:10:14 2012
New Revision: 231946
URL: http://svn.freebsd.org/changeset/base/231946

Log:
  MFC r230397, r230438:
  
  MFC r230397 (pjd):
  By default turn off prefetch when listing snapshots.
  In my tests it makes listing snapshots 19% faster with cold cache and
  47% faster with warm cache.
  
  MFC r230438 (pjd):
  Dramatically optimize listing snapshots when user requests only snapshot
  names and wants to sort them by name, ie. when executes:
  
  	# 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:
  
  	# time zfs list -t snapshot -o name -s name > /dev/null
  	cold cache: 525s
  	warm cache: 218s
  
  after:
  
  	# time zfs list -t snapshot -o name -s name > /dev/null
  	cold cache: 1.7s
  	warm cache: 1.1s

Modified:
  stable/9/cddl/contrib/opensolaris/cmd/zfs/zfs_iter.c
  stable/9/cddl/contrib/opensolaris/cmd/zfs/zfs_iter.h
  stable/9/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c
  stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h
  stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c
  stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h
  stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_iter.c
  stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_ioctl.h
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
Directory Properties:
  stable/9/cddl/contrib/opensolaris/   (props changed)
  stable/9/sys/   (props changed)
  stable/9/sys/cddl/contrib/opensolaris/   (props changed)

Modified: stable/9/cddl/contrib/opensolaris/cmd/zfs/zfs_iter.c
==============================================================================
--- stable/9/cddl/contrib/opensolaris/cmd/zfs/zfs_iter.c	Mon Feb 20 20:46:27 2012	(r231945)
+++ stable/9/cddl/contrib/opensolaris/cmd/zfs/zfs_iter.c	Mon Feb 20 21:10:14 2012	(r231946)
@@ -20,6 +20,8 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
+ * All rights reserved.
  */
 
 #include <libintl.h>
@@ -129,8 +131,11 @@ zfs_callback(zfs_handle_t *zhp, void *da
 		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);
+		if ((zfs_get_type(zhp) != ZFS_TYPE_SNAPSHOT) && include_snaps) {
+			(void) zfs_iter_snapshots(zhp,
+			    (cb->cb_flags & ZFS_ITER_SIMPLE) != 0, zfs_callback,
+			    data);
+		}
 		cb->cb_depth--;
 	}
 
@@ -184,6 +189,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)
@@ -224,7 +237,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;
@@ -290,7 +309,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: stable/9/cddl/contrib/opensolaris/cmd/zfs/zfs_iter.h
==============================================================================
--- stable/9/cddl/contrib/opensolaris/cmd/zfs/zfs_iter.h	Mon Feb 20 20:46:27 2012	(r231945)
+++ stable/9/cddl/contrib/opensolaris/cmd/zfs/zfs_iter.h	Mon Feb 20 21:10:14 2012	(r231946)
@@ -43,11 +43,13 @@ 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_SIMPLE		   (1 << 5)
 
 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: stable/9/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c
==============================================================================
--- stable/9/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c	Mon Feb 20 20:46:27 2012	(r231945)
+++ stable/9/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c	Mon Feb 20 21:10:14 2012	(r231946)
@@ -23,7 +23,7 @@
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
  * Copyright (c) 2011 by Delphix. All rights reserved.
- * Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
+ * Copyright (c) 2011-2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
  * All rights reserved.
  * Copyright (c) 2011 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
  */
@@ -2838,7 +2838,12 @@ print_dataset(zfs_handle_t *zhp, zprop_l
 			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, B_FALSE) != 0)
 				propstr = "-";
@@ -3005,6 +3010,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)

Modified: stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h
==============================================================================
--- stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h	Mon Feb 20 20:46:27 2012	(r231945)
+++ stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h	Mon Feb 20 21:10:14 2012	(r231946)
@@ -507,7 +507,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 *);
 

Modified: stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c
==============================================================================
--- stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c	Mon Feb 20 20:46:27 2012	(r231945)
+++ stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c	Mon Feb 20 21:10:14 2012	(r231946)
@@ -23,7 +23,7 @@
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
  * Copyright (c) 2011 by Delphix. All rights reserved.
- * Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
+ * Copyright (c) 2011-2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
  * All rights reserved.
  */
 
@@ -514,6 +514,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);

Modified: stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h
==============================================================================
--- stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h	Mon Feb 20 20:46:27 2012	(r231945)
+++ stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h	Mon Feb 20 21:10:14 2012	(r231946)
@@ -150,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: stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_iter.c
==============================================================================
--- stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_iter.c	Mon Feb 20 20:46:27 2012	(r231945)
+++ stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_iter.c	Mon Feb 20 21:10:14 2012	(r231946)
@@ -23,6 +23,8 @@
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
  * Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright (c) 2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
+ * All rights reserved.
  */
 
 #include <stdio.h>
@@ -137,7 +139,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;
@@ -146,15 +149,19 @@ zfs_iter_snapshots(zfs_handle_t *zhp, zf
 	if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT)
 		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);
@@ -234,7 +241,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);
@@ -378,7 +385,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));
 }
 
 
@@ -439,8 +446,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;
 	}
 	if (!first && err == 0)

Modified: stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c
==============================================================================
--- stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c	Mon Feb 20 20:46:27 2012	(r231945)
+++ stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c	Mon Feb 20 21:10:14 2012	(r231946)
@@ -22,6 +22,8 @@
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright (c) 2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
+ * All rights reserved.
  */
 
 #include <assert.h>
@@ -717,7 +719,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);

Modified: stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_ioctl.h
==============================================================================
--- stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_ioctl.h	Mon Feb 20 20:46:27 2012	(r231945)
+++ stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_ioctl.h	Mon Feb 20 21:10:14 2012	(r231946)
@@ -300,7 +300,8 @@ typedef struct zfs_cmd {
 	boolean_t	zc_temphold;
 	uint64_t	zc_action_handle;
 	int		zc_cleanup_fd;
-	uint8_t		zc_pad[4];		/* alignment */
+	uint8_t		zc_simple;
+	uint8_t		zc_pad[3];		/* alignment */
 	uint64_t	zc_sendobj;
 	uint64_t	zc_fromobj;
 	uint64_t	zc_createtxg;

Modified: stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
==============================================================================
--- stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c	Mon Feb 20 20:46:27 2012	(r231945)
+++ stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c	Mon Feb 20 21:10:14 2012	(r231946)
@@ -20,7 +20,7 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
+ * Copyright (c) 2011-2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
  * All rights reserved.
  * Portions Copyright 2011 Martin Matuska <mm@FreeBSD.org>
  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
@@ -81,6 +81,12 @@
 
 CTASSERT(sizeof(zfs_cmd_t) < IOCPARM_MAX);
 
+static int snapshot_list_prefetch;
+SYSCTL_DECL(_vfs_zfs);
+TUNABLE_INT("vfs.zfs.snapshot_list_prefetch", &snapshot_list_prefetch);
+SYSCTL_INT(_vfs_zfs, OID_AUTO, snapshot_list_prefetch, CTLFLAG_RW,
+    &snapshot_list_prefetch, 0, "Prefetch data when listing snapshots");
+
 static struct cdev *zfsdev;
 
 extern void zfs_init(void);
@@ -2030,6 +2036,7 @@ top:
  * zc_name		name of filesystem
  * zc_cookie		zap cursor
  * zc_nvlist_dst_size	size of buffer for property nvlist
+ * zc_simple		when set, only name is requested
  *
  * outputs:
  * zc_name		name of next snapshot
@@ -2044,7 +2051,7 @@ zfs_ioc_snapshot_list_next(zfs_cmd_t *zc
 	int error;
 
 top:
-	if (zc->zc_cookie == 0)
+	if (snapshot_list_prefetch && zc->zc_cookie == 0 && !zc->zc_simple)
 		(void) dmu_objset_find(zc->zc_name, dmu_objset_prefetch,
 		    NULL, DS_FIND_SNAPSHOTS);
 
@@ -2066,7 +2073,7 @@ top:
 	    zc->zc_name + strlen(zc->zc_name), &zc->zc_obj, &zc->zc_cookie,
 	    NULL);
 
-	if (error == 0) {
+	if (error == 0 && !zc->zc_simple) {
 		dsl_dataset_t *ds;
 		dsl_pool_t *dp = os->os_dsl_dataset->ds_dir->dd_pool;
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201202202110.q1KLAEeV068061>