mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-25 03:37:45 +03:00
Speed up 'zfs list -t snapshot -o name -s name'
FreeBSD #xxx: 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
NOTE: This patch only appears in FreeBSD. If/when Illumos picks up
the change we may want to drop this patch and adopt their version.
However, for now this addresses a real issue.
Ported-by: Brian Behlendorf <behlendorf1@llnl.gov>
Issue #450
This commit is contained in:
committed by
Brian Behlendorf
parent
74497b7ab6
commit
0cee24064a
+27
-3
@@ -20,6 +20,7 @@
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
|
||||
*/
|
||||
|
||||
#include <libintl.h>
|
||||
@@ -129,8 +130,11 @@ zfs_callback(zfs_handle_t *zhp, void *data)
|
||||
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 +188,13 @@ zfs_free_sort_columns(zfs_sort_column_t *sc)
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
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 +235,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;
|
||||
@@ -290,7 +307,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);
|
||||
|
||||
@@ -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 *);
|
||||
int zfs_sort_only_by_name(const zfs_sort_column_t *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
+13
-1
@@ -2650,7 +2650,12 @@ print_dataset(zfs_handle_t *zhp, zprop_list_t *pl, boolean_t scripted)
|
||||
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 = "-";
|
||||
@@ -2810,6 +2815,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.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user