mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 02:27:36 +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
@@ -23,6 +23,7 @@
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2010 Nexenta Systems, Inc. All rights reserved.
|
||||
* Copyright (c) 2011 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
@@ -480,6 +481,23 @@ make_dataset_handle_zc(libzfs_handle_t *hdl, zfs_cmd_t *zc)
|
||||
return (zhp);
|
||||
}
|
||||
|
||||
static 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);
|
||||
}
|
||||
|
||||
/*
|
||||
* Opens the given snapshot, filesystem, or volume. The 'types'
|
||||
* argument is a mask of acceptable types. The function will print an
|
||||
@@ -2518,7 +2536,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", "\0", "\0", "\0", 0 };
|
||||
zfs_handle_t *nzhp;
|
||||
@@ -2527,15 +2546,19 @@ zfs_iter_snapshots(zfs_handle_t *zhp, zfs_iter_f func, void *data)
|
||||
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);
|
||||
@@ -2557,7 +2580,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));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3287,7 +3310,7 @@ zfs_promote(zfs_handle_t *zhp)
|
||||
return (-1);
|
||||
(void) zfs_prop_get(pzhp, ZFS_PROP_MOUNTPOINT, pd.cb_mountpoint,
|
||||
sizeof (pd.cb_mountpoint), NULL, NULL, 0, FALSE);
|
||||
ret = zfs_iter_snapshots(pzhp, promote_snap_cb, &pd);
|
||||
ret = zfs_iter_snapshots(pzhp, B_FALSE, promote_snap_cb, &pd);
|
||||
if (ret != 0) {
|
||||
zfs_close(pzhp);
|
||||
return (-1);
|
||||
@@ -3302,7 +3325,8 @@ zfs_promote(zfs_handle_t *zhp)
|
||||
if (ret != 0) {
|
||||
int save_errno = errno;
|
||||
|
||||
(void) zfs_iter_snapshots(pzhp, promote_snap_done_cb, &pd);
|
||||
(void) zfs_iter_snapshots(pzhp, B_FALSE, promote_snap_done_cb,
|
||||
&pd);
|
||||
zfs_close(pzhp);
|
||||
|
||||
switch (save_errno) {
|
||||
@@ -3321,7 +3345,8 @@ zfs_promote(zfs_handle_t *zhp)
|
||||
return (zfs_standard_error(hdl, save_errno, errbuf));
|
||||
}
|
||||
} else {
|
||||
(void) zfs_iter_snapshots(zhp, promote_snap_done_cb, &pd);
|
||||
(void) zfs_iter_snapshots(zhp, B_FALSE, promote_snap_done_cb,
|
||||
&pd);
|
||||
}
|
||||
|
||||
zfs_close(pzhp);
|
||||
|
||||
@@ -21,6 +21,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 <assert.h>
|
||||
@@ -717,7 +719,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);
|
||||
@@ -843,7 +845,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);
|
||||
|
||||
Reference in New Issue
Block a user