6902 speed up listing of snapshots if requesting name only and sorting by name
illumos/illumos-gate@0d8fa8f8eb
0d8fa8f8eb
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@delphix.com>
Reviewed by: Pawel Dawidek <pjd@freebsd.org>
Reviewed by: Brian Behlendorf <behlendorf1@llnl.gov>
Approved by: Garrett D'Amore <garrett@damore.org>
Author: Martin Matuska <martin@matuska.org>
This commit is contained in:
parent
21bdd8ff9f
commit
73f0e3e3e5
@ -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 *data)
|
||||
(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 *sc)
|
||||
}
|
||||
}
|
||||
|
||||
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 *rarg, void *unused)
|
||||
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 *rarg, void *data)
|
||||
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);
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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_cbdata_t *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)
|
||||
@ -3140,6 +3146,13 @@ zfs_do_list(int argc, char **argv)
|
||||
if (fields == NULL)
|
||||
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.
|
||||
*/
|
||||
@ -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;
|
||||
|
@ -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 *, zfs_iter_f, void *);
|
||||
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 *);
|
||||
|
@ -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.
|
||||
@ -518,6 +519,22 @@ make_dataset_handle_zc(libzfs_handle_t *hdl, zfs_cmd_t *zc)
|
||||
return (zhp);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -3776,7 +3793,7 @@ zfs_rollback(zfs_handle_t *zhp, zfs_handle_t *snap, boolean_t force)
|
||||
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)
|
||||
|
@ -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_handle_t *, int, const char *, ...);
|
||||
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 *);
|
||||
|
@ -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, zfs_iter_f func, void *data)
|
||||
* 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, zfs_iter_f func, void *data)
|
||||
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 *zhp, zfs_iter_f callback, void *data)
|
||||
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_iter_f func, void *data)
|
||||
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, void *arg)
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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 *arg)
|
||||
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);
|
||||
|
@ -20,6 +20,7 @@
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011-2012 Pawel Jakub Dawidek. All rights reserved.
|
||||
* Copyright (c) 2012, 2015 by Delphix. All rights reserved.
|
||||
* Copyright 2016 RackTop Systems.
|
||||
* Copyright (c) 2014 Integros [integros.com]
|
||||
@ -370,6 +371,7 @@ typedef struct zfs_cmd {
|
||||
uint32_t zc_flags;
|
||||
uint64_t zc_action_handle;
|
||||
int zc_cleanup_fd;
|
||||
uint8_t zc_simple;
|
||||
boolean_t zc_resumable;
|
||||
uint64_t zc_sendobj;
|
||||
uint64_t zc_fromobj;
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011-2012 Pawel Jakub Dawidek. All rights reserved.
|
||||
* Portions Copyright 2011 Martin Matuska
|
||||
* Copyright 2015, OmniTI Computer Consulting, Inc. All rights reserved.
|
||||
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
|
||||
@ -2268,6 +2269,7 @@ zfs_ioc_dataset_list_next(zfs_cmd_t *zc)
|
||||
* 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
|
||||
@ -2300,7 +2302,7 @@ zfs_ioc_snapshot_list_next(zfs_cmd_t *zc)
|
||||
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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user