summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorAlek P <[email protected]>2019-03-12 13:13:22 -0700
committerBrian Behlendorf <[email protected]>2019-03-12 13:13:22 -0700
commit4c0883fb4af0d5565459099b98fcf90ecbfa1ca1 (patch)
tree6f99d61588b8168485f903467b271259d00882ee /lib
parentdd785b5b86bbb7ebbfe1d22668f3dd27c5704994 (diff)
Avoid retrieving unused snapshot props
This patch modifies the zfs_ioc_snapshot_list_next() ioctl to enable it to take input parameters that alter the way looping through the list of snapshots is performed. The idea here is to restrict functions that throw away some of the snapshots returned by the ioctl to a range of snapshots that these functions actually use. This improves efficiency and execution speed for some rollback and send operations. Reviewed-by: Tom Caputi <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Reviewed by: Matt Ahrens <[email protected]> Signed-off-by: Alek Pinchuk <[email protected]> Closes #8077
Diffstat (limited to 'lib')
-rw-r--r--lib/libzfs/libzfs_dataset.c11
-rw-r--r--lib/libzfs/libzfs_iter.c37
-rw-r--r--lib/libzfs/libzfs_sendrecv.c85
3 files changed, 90 insertions, 43 deletions
diff --git a/lib/libzfs/libzfs_dataset.c b/lib/libzfs/libzfs_dataset.c
index 0537b631e..de94021a6 100644
--- a/lib/libzfs/libzfs_dataset.c
+++ b/lib/libzfs/libzfs_dataset.c
@@ -30,7 +30,7 @@
* Copyright 2017 Nexenta Systems, Inc.
* Copyright 2016 Igor Kozhukhov <[email protected]>
* Copyright 2017-2018 RackTop Systems.
- * Copyright (c) 2018 Datto Inc.
+ * Copyright (c) 2019 Datto Inc.
*/
#include <ctype.h>
@@ -4367,6 +4367,7 @@ zfs_rollback(zfs_handle_t *zhp, zfs_handle_t *snap, boolean_t force)
boolean_t restore_resv = 0;
uint64_t old_volsize = 0, new_volsize;
zfs_prop_t resv_prop = { 0 };
+ uint64_t min_txg = 0;
assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM ||
zhp->zfs_type == ZFS_TYPE_VOLUME);
@@ -4377,7 +4378,13 @@ 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, B_FALSE, rollback_destroy, &cb);
+
+ if (cb.cb_create > 0)
+ min_txg = cb.cb_create;
+
+ (void) zfs_iter_snapshots(zhp, B_FALSE, rollback_destroy, &cb,
+ min_txg, 0);
+
(void) zfs_iter_bookmarks(zhp, rollback_destroy, &cb);
if (cb.cb_error)
diff --git a/lib/libzfs/libzfs_iter.c b/lib/libzfs/libzfs_iter.c
index b1bdc4a6d..e765a7ee7 100644
--- a/lib/libzfs/libzfs_iter.c
+++ b/lib/libzfs/libzfs_iter.c
@@ -23,7 +23,7 @@
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2015 by Delphix. All rights reserved.
* Copyright 2014 Nexenta Systems, Inc. All rights reserved.
- * Copyright (c) 2018 Datto Inc.
+ * Copyright (c) 2019 Datto Inc.
*/
#include <stdio.h>
@@ -141,11 +141,12 @@ zfs_iter_filesystems(zfs_handle_t *zhp, zfs_iter_f func, void *data)
*/
int
zfs_iter_snapshots(zfs_handle_t *zhp, boolean_t simple, zfs_iter_f func,
- void *data)
+ void *data, uint64_t min_txg, uint64_t max_txg)
{
zfs_cmd_t zc = {"\0"};
zfs_handle_t *nzhp;
int ret;
+ nvlist_t *range_nvl = NULL;
if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT ||
zhp->zfs_type == ZFS_TYPE_BOOKMARK)
@@ -155,6 +156,24 @@ zfs_iter_snapshots(zfs_handle_t *zhp, boolean_t simple, zfs_iter_f func,
if (zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0)
return (-1);
+
+ if (min_txg != 0) {
+ range_nvl = fnvlist_alloc();
+ fnvlist_add_uint64(range_nvl, SNAP_ITER_MIN_TXG, min_txg);
+ }
+ if (max_txg != 0) {
+ if (range_nvl == NULL)
+ range_nvl = fnvlist_alloc();
+ fnvlist_add_uint64(range_nvl, SNAP_ITER_MAX_TXG, max_txg);
+ }
+
+ if (range_nvl != NULL &&
+ zcmd_write_src_nvlist(zhp->zfs_hdl, &zc, range_nvl) != 0) {
+ zcmd_free_nvlists(&zc);
+ fnvlist_free(range_nvl);
+ return (-1);
+ }
+
while ((ret = zfs_do_list_ioctl(zhp, ZFS_IOC_SNAPSHOT_LIST_NEXT,
&zc)) == 0) {
@@ -167,10 +186,12 @@ zfs_iter_snapshots(zfs_handle_t *zhp, boolean_t simple, zfs_iter_f func,
if ((ret = func(nzhp, data)) != 0) {
zcmd_free_nvlists(&zc);
+ fnvlist_free(range_nvl);
return (ret);
}
}
zcmd_free_nvlists(&zc);
+ fnvlist_free(range_nvl);
return ((ret < 0) ? ret : 0);
}
@@ -282,7 +303,8 @@ zfs_snapshot_compare(const void *larg, const void *rarg)
}
int
-zfs_iter_snapshots_sorted(zfs_handle_t *zhp, zfs_iter_f callback, void *data)
+zfs_iter_snapshots_sorted(zfs_handle_t *zhp, zfs_iter_f callback, void *data,
+ uint64_t min_txg, uint64_t max_txg)
{
int ret = 0;
zfs_node_t *node;
@@ -292,7 +314,8 @@ 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, B_FALSE, zfs_sort_snaps, &avl);
+ ret = zfs_iter_snapshots(zhp, B_FALSE, zfs_sort_snaps, &avl, min_txg,
+ max_txg);
for (node = avl_first(&avl); node != NULL; node = AVL_NEXT(&avl, node))
ret |= callback(node->zn_handle, data);
@@ -395,7 +418,7 @@ zfs_iter_snapspec(zfs_handle_t *fs_zhp, const char *spec_orig,
}
err = zfs_iter_snapshots_sorted(fs_zhp,
- snapspec_cb, &ssa);
+ snapspec_cb, &ssa, 0, 0);
if (ret == 0)
ret = err;
if (ret == 0 && (!ssa.ssa_seenfirst ||
@@ -435,7 +458,7 @@ zfs_iter_children(zfs_handle_t *zhp, zfs_iter_f func, void *data)
{
int ret;
- if ((ret = zfs_iter_snapshots(zhp, B_FALSE, func, data)) != 0)
+ if ((ret = zfs_iter_snapshots(zhp, B_FALSE, func, data, 0, 0)) != 0)
return (ret);
return (zfs_iter_filesystems(zhp, func, data));
@@ -501,7 +524,7 @@ iter_dependents_cb(zfs_handle_t *zhp, void *arg)
err = zfs_iter_filesystems(zhp, iter_dependents_cb, ida);
if (err == 0)
err = zfs_iter_snapshots(zhp, B_FALSE,
- iter_dependents_cb, ida);
+ iter_dependents_cb, ida, 0, 0);
ida->stack = isf.next;
}
diff --git a/lib/libzfs/libzfs_sendrecv.c b/lib/libzfs/libzfs_sendrecv.c
index 2aa0fd222..8096089f6 100644
--- a/lib/libzfs/libzfs_sendrecv.c
+++ b/lib/libzfs/libzfs_sendrecv.c
@@ -29,7 +29,7 @@
* Copyright 2015, OmniTI Computer Consulting, Inc. All rights reserved.
* Copyright 2016 Igor Kozhukhov <[email protected]>
* Copyright (c) 2018, loli10K <[email protected]>. All rights reserved.
- * Copyright (c) 2018 Datto Inc.
+ * Copyright (c) 2019 Datto Inc.
*/
#include <assert.h>
@@ -623,10 +623,11 @@ typedef struct send_data {
const char *fsname;
const char *fromsnap;
const char *tosnap;
- boolean_t raw;
- boolean_t backup;
boolean_t recursive;
+ boolean_t raw;
+ boolean_t replicate;
boolean_t verbose;
+ boolean_t backup;
boolean_t seenfrom;
boolean_t seento;
boolean_t holds; /* were holds requested with send -h */
@@ -845,6 +846,7 @@ send_iterate_fs(zfs_handle_t *zhp, void *arg)
send_data_t *sd = arg;
nvlist_t *nvfs = NULL, *nv = NULL;
int rv = 0;
+ uint64_t min_txg = 0, max_txg = 0;
uint64_t parent_fromsnap_guid_save = sd->parent_fromsnap_guid;
uint64_t fromsnap_txg_save = sd->fromsnap_txg;
uint64_t tosnap_txg_save = sd->tosnap_txg;
@@ -888,10 +890,10 @@ send_iterate_fs(zfs_handle_t *zhp, void *arg)
goto out;
}
- VERIFY(0 == nvlist_alloc(&nvfs, NV_UNIQUE_NAME, 0));
- VERIFY(0 == nvlist_add_string(nvfs, "name", zhp->zfs_name));
- VERIFY(0 == nvlist_add_uint64(nvfs, "parentfromsnap",
- sd->parent_fromsnap_guid));
+ nvfs = fnvlist_alloc();
+ fnvlist_add_string(nvfs, "name", zhp->zfs_name);
+ fnvlist_add_uint64(nvfs, "parentfromsnap",
+ sd->parent_fromsnap_guid);
if (zhp->zfs_dmustats.dds_origin[0]) {
zfs_handle_t *origin = zfs_open(zhp->zfs_hdl,
@@ -900,15 +902,15 @@ send_iterate_fs(zfs_handle_t *zhp, void *arg)
rv = -1;
goto out;
}
- VERIFY(0 == nvlist_add_uint64(nvfs, "origin",
- origin->zfs_dmustats.dds_guid));
+ fnvlist_add_uint64(nvfs, "origin",
+ origin->zfs_dmustats.dds_guid);
zfs_close(origin);
}
/* iterate over props */
if (sd->props || sd->backup || sd->recursive) {
- VERIFY(0 == nvlist_alloc(&nv, NV_UNIQUE_NAME, 0));
+ nv = fnvlist_alloc();
send_iterate_prop(zhp, sd->backup, nv);
}
if (zfs_prop_get_int(zhp, ZFS_PROP_ENCRYPTION) != ZIO_CRYPT_OFF) {
@@ -921,7 +923,7 @@ send_iterate_fs(zfs_handle_t *zhp, void *arg)
}
if (encroot)
- VERIFY(0 == nvlist_add_boolean(nvfs, "is_encroot"));
+ fnvlist_add_boolean(nvfs, "is_encroot");
/*
* Encrypted datasets can only be sent with properties if
@@ -941,28 +943,32 @@ send_iterate_fs(zfs_handle_t *zhp, void *arg)
}
if (nv != NULL)
- VERIFY(0 == nvlist_add_nvlist(nvfs, "props", nv));
+ fnvlist_add_nvlist(nvfs, "props", nv);
/* iterate over snaps, and set sd->parent_fromsnap_guid */
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));
+ sd->parent_snaps = fnvlist_alloc();
+ sd->snapprops = fnvlist_alloc();
+ if (!sd->replicate && fromsnap_txg != 0)
+ min_txg = fromsnap_txg;
+ if (!sd->replicate && tosnap_txg != 0)
+ max_txg = tosnap_txg;
if (sd->holds)
VERIFY(0 == nvlist_alloc(&sd->snapholds, NV_UNIQUE_NAME, 0));
- (void) zfs_iter_snapshots_sorted(zhp, send_iterate_snap, sd);
- VERIFY(0 == nvlist_add_nvlist(nvfs, "snaps", sd->parent_snaps));
- VERIFY(0 == nvlist_add_nvlist(nvfs, "snapprops", sd->snapprops));
+ (void) zfs_iter_snapshots_sorted(zhp, send_iterate_snap, sd,
+ min_txg, max_txg);
+ fnvlist_add_nvlist(nvfs, "snaps", sd->parent_snaps);
+ fnvlist_add_nvlist(nvfs, "snapprops", sd->snapprops);
if (sd->holds)
- VERIFY(0 == nvlist_add_nvlist(nvfs, "snapholds",
- sd->snapholds));
- nvlist_free(sd->parent_snaps);
- nvlist_free(sd->snapprops);
- nvlist_free(sd->snapholds);
+ fnvlist_add_nvlist(nvfs, "snapholds", sd->snapholds);
+ fnvlist_free(sd->parent_snaps);
+ fnvlist_free(sd->snapprops);
+ fnvlist_free(sd->snapholds);
/* add this fs to nvlist */
(void) snprintf(guidstring, sizeof (guidstring),
"0x%llx", (longlong_t)guid);
- VERIFY(0 == nvlist_add_nvlist(sd->fss, guidstring, nvfs));
+ fnvlist_add_nvlist(sd->fss, guidstring, nvfs);
/* iterate over children */
if (sd->recursive)
@@ -972,8 +978,8 @@ out:
sd->parent_fromsnap_guid = parent_fromsnap_guid_save;
sd->fromsnap_txg = fromsnap_txg_save;
sd->tosnap_txg = tosnap_txg_save;
- nvlist_free(nv);
- nvlist_free(nvfs);
+ fnvlist_free(nv);
+ fnvlist_free(nvfs);
zfs_close(zhp);
return (rv);
@@ -981,8 +987,9 @@ out:
static int
gather_nvlist(libzfs_handle_t *hdl, const char *fsname, const char *fromsnap,
- const char *tosnap, boolean_t recursive, boolean_t raw, boolean_t verbose,
- boolean_t backup, boolean_t holds, boolean_t props, nvlist_t **nvlp,
+ const char *tosnap, boolean_t recursive, boolean_t raw, boolean_t replicate,
+ boolean_t verbose, boolean_t backup, boolean_t holds, boolean_t props,
+ nvlist_t **nvlp,
avl_tree_t **avlp)
{
zfs_handle_t *zhp;
@@ -999,6 +1006,7 @@ gather_nvlist(libzfs_handle_t *hdl, const char *fsname, const char *fromsnap,
sd.tosnap = tosnap;
sd.recursive = recursive;
sd.raw = raw;
+ sd.replicate = replicate;
sd.verbose = verbose;
sd.backup = backup;
sd.holds = holds;
@@ -1437,6 +1445,7 @@ dump_filesystem(zfs_handle_t *zhp, void *arg)
send_dump_data_t *sdd = arg;
boolean_t missingfrom = B_FALSE;
zfs_cmd_t zc = {"\0"};
+ uint64_t min_txg = 0, max_txg = 0;
(void) snprintf(zc.zc_name, sizeof (zc.zc_name), "%s@%s",
zhp->zfs_name, sdd->tosnap);
@@ -1469,7 +1478,15 @@ dump_filesystem(zfs_handle_t *zhp, void *arg)
if (sdd->fromsnap == NULL || missingfrom)
sdd->seenfrom = B_TRUE;
- rv = zfs_iter_snapshots_sorted(zhp, dump_snapshot, arg);
+ if (!sdd->replicate && sdd->fromsnap != NULL)
+ min_txg = get_snap_txg(zhp->zfs_hdl, zhp->zfs_name,
+ sdd->fromsnap);
+ if (!sdd->replicate && sdd->tosnap != NULL)
+ max_txg = get_snap_txg(zhp->zfs_hdl, zhp->zfs_name,
+ sdd->tosnap);
+
+ rv = zfs_iter_snapshots_sorted(zhp, dump_snapshot, arg,
+ min_txg, max_txg);
if (!sdd->seenfrom) {
(void) fprintf(stderr, dgettext(TEXT_DOMAIN,
"WARNING: could not send %s@%s:\n"
@@ -1948,8 +1965,8 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
err = gather_nvlist(zhp->zfs_hdl, zhp->zfs_name,
fromsnap, tosnap, flags->replicate, flags->raw,
- flags->verbose, flags->backup, flags->holds,
- flags->props, &fss, &fsavl);
+ flags->replicate, flags->verbose, flags->backup,
+ flags->holds, flags->props, &fss, &fsavl);
if (err)
goto err_out;
VERIFY(0 == nvlist_add_nvlist(hdrnv, "fss", fss));
@@ -2853,8 +2870,8 @@ again:
VERIFY(0 == nvlist_alloc(&deleted, NV_UNIQUE_NAME, 0));
if ((error = gather_nvlist(hdl, tofs, fromsnap, NULL,
- recursive, B_TRUE, B_FALSE, B_FALSE, B_FALSE, B_TRUE, &local_nv,
- &local_avl)) != 0)
+ recursive, B_TRUE, recursive, B_FALSE, B_FALSE, B_FALSE, B_TRUE,
+ &local_nv, &local_avl)) != 0)
return (error);
/*
@@ -4287,8 +4304,8 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
*/
*cp = '\0';
if (gather_nvlist(hdl, destsnap, NULL, NULL, B_FALSE, B_TRUE,
- B_FALSE, B_FALSE, B_FALSE, B_TRUE, &local_nv, &local_avl)
- == 0) {
+ B_FALSE, B_FALSE, B_FALSE, B_FALSE, B_TRUE, &local_nv,
+ &local_avl) == 0) {
*cp = '@';
fs = fsavl_find(local_avl, drrb->drr_toguid, NULL);
fsavl_destroy(local_avl);