aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cddl/contrib/opensolaris/cmd/zfs/zfs_iter.c2
-rw-r--r--cddl/contrib/opensolaris/cmd/zfs/zfs_main.c41
-rw-r--r--cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h8
-rw-r--r--cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c11
-rw-r--r--cddl/contrib/opensolaris/lib/libzfs/common/libzfs_iter.c36
-rw-r--r--cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c45
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c78
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h9
8 files changed, 179 insertions, 51 deletions
diff --git a/cddl/contrib/opensolaris/cmd/zfs/zfs_iter.c b/cddl/contrib/opensolaris/cmd/zfs/zfs_iter.c
index 2ee4f97248a9..a291db083568 100644
--- a/cddl/contrib/opensolaris/cmd/zfs/zfs_iter.c
+++ b/cddl/contrib/opensolaris/cmd/zfs/zfs_iter.c
@@ -139,7 +139,7 @@ zfs_callback(zfs_handle_t *zhp, void *data)
ZFS_TYPE_BOOKMARK)) == 0) && include_snaps)
(void) zfs_iter_snapshots(zhp,
(cb->cb_flags & ZFS_ITER_SIMPLE) != 0, zfs_callback,
- data);
+ data, 0, 0);
if (((zfs_get_type(zhp) & (ZFS_TYPE_SNAPSHOT |
ZFS_TYPE_BOOKMARK)) == 0) && include_bmarks)
(void) zfs_iter_bookmarks(zhp, zfs_callback, data);
diff --git a/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c b/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c
index c2f9f9548ca3..3f389d1a51ff 100644
--- a/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c
+++ b/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c
@@ -30,7 +30,7 @@
* Copyright (c) 2014 Integros [integros.com]
* Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
* Copyright 2016 Nexenta Systems, Inc.
- * Copyright (c) 2018 Datto Inc.
+ * Copyright (c) 2019 Datto Inc.
*/
#include <assert.h>
@@ -1174,7 +1174,7 @@ destroy_print_snapshots(zfs_handle_t *fs_zhp, destroy_cbdata_t *cb)
int err = 0;
assert(cb->cb_firstsnap == NULL);
assert(cb->cb_prevsnap == NULL);
- err = zfs_iter_snapshots_sorted(fs_zhp, destroy_print_cb, cb);
+ err = zfs_iter_snapshots_sorted(fs_zhp, destroy_print_cb, cb, 0, 0);
if (cb->cb_firstsnap != NULL) {
uint64_t used = 0;
if (err == 0) {
@@ -3437,6 +3437,7 @@ zfs_do_promote(int argc, char **argv)
*/
typedef struct rollback_cbdata {
uint64_t cb_create;
+ uint8_t cb_younger_ds_printed;
boolean_t cb_first;
int cb_doclones;
char *cb_target;
@@ -3467,15 +3468,20 @@ rollback_check_dependent(zfs_handle_t *zhp, void *data)
}
/*
- * Report any snapshots more recent than the one specified. Used when '-r' is
- * not specified. We reuse this same callback for the snapshot dependents - if
- * 'cb_dependent' is set, then this is a dependent and we should report it
- * without checking the transaction group.
+ * Report some snapshots/bookmarks more recent than the one specified.
+ * Used when '-r' is not specified. We reuse this same callback for the
+ * snapshot dependents - if 'cb_dependent' is set, then this is a
+ * dependent and we should report it without checking the transaction group.
*/
static int
rollback_check(zfs_handle_t *zhp, void *data)
{
rollback_cbdata_t *cbp = data;
+ /*
+ * Max number of younger snapshots and/or bookmarks to display before
+ * we stop the iteration.
+ */
+ const uint8_t max_younger = 32;
if (cbp->cb_doclones) {
zfs_close(zhp);
@@ -3504,9 +3510,24 @@ rollback_check(zfs_handle_t *zhp, void *data)
} else {
(void) fprintf(stderr, "%s\n",
zfs_get_name(zhp));
+ cbp->cb_younger_ds_printed++;
}
}
zfs_close(zhp);
+
+ if (cbp->cb_younger_ds_printed == max_younger) {
+ /*
+ * This non-recursive rollback is going to fail due to the
+ * presence of snapshots and/or bookmarks that are younger than
+ * the rollback target.
+ * We printed some of the offending objects, now we stop
+ * zfs_iter_snapshot/bookmark iteration so we can fail fast and
+ * avoid iterating over the rest of the younger objects
+ */
+ (void) fprintf(stderr, gettext("Output limited to %d "
+ "snapshots/bookmarks\n"), max_younger);
+ return (-1);
+ }
return (0);
}
@@ -3520,6 +3541,7 @@ zfs_do_rollback(int argc, char **argv)
zfs_handle_t *zhp, *snap;
char parentname[ZFS_MAX_DATASET_NAME_LEN];
char *delim;
+ uint64_t min_txg = 0;
/* check options */
while ((c = getopt(argc, argv, "rRf")) != -1) {
@@ -3575,7 +3597,12 @@ 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, B_FALSE, rollback_check, &cb)) != 0)
+
+ if (cb.cb_create > 0)
+ min_txg = cb.cb_create;
+
+ if ((ret = zfs_iter_snapshots(zhp, B_FALSE, rollback_check, &cb,
+ min_txg, 0)) != 0)
goto out;
if ((ret = zfs_iter_bookmarks(zhp, rollback_check, &cb)) != 0)
goto out;
diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h
index 15b1d54e6341..c0e235476fed 100644
--- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h
+++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h
@@ -28,7 +28,7 @@
* Copyright (c) 2013 Steven Hartland. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
* Copyright 2016 Nexenta Systems, Inc.
- * Copyright (c) 2017 Datto Inc.
+ * Copyright (c) 2019 Datto Inc.
*/
#ifndef _LIBZFS_H
@@ -570,8 +570,10 @@ 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 *, boolean_t, zfs_iter_f, void *);
-extern int zfs_iter_snapshots_sorted(zfs_handle_t *, zfs_iter_f, void *);
+extern int zfs_iter_snapshots(zfs_handle_t *, boolean_t, zfs_iter_f, void *,
+ uint64_t, uint64_t);
+extern int zfs_iter_snapshots_sorted(zfs_handle_t *, zfs_iter_f, void *,
+ uint64_t, uint64_t);
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 *);
diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c
index 76a71f39d987..b6a17c2c85c1 100644
--- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c
+++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c
@@ -31,6 +31,7 @@
* Copyright 2017 Nexenta Systems, Inc.
* Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
* Copyright 2017-2018 RackTop Systems.
+ * Copyright (c) 2019 Datto Inc.
*/
#include <ctype.h>
@@ -4163,7 +4164,7 @@ zfs_rollback(zfs_handle_t *zhp, zfs_handle_t *snap, boolean_t force)
rollback_data_t cb = { 0 };
int err;
boolean_t restore_resv = 0;
- uint64_t old_volsize = 0, new_volsize;
+ uint64_t min_txg = 0, old_volsize = 0, new_volsize;
zfs_prop_t resv_prop;
assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM ||
@@ -4175,7 +4176,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/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_iter.c b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_iter.c
index 6bca98816f7c..36138676e7db 100644
--- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_iter.c
+++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_iter.c
@@ -24,6 +24,7 @@
* 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.
+ * Copyright (c) 2019 Datto Inc.
*/
#include <stdio.h>
@@ -139,11 +140,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)
@@ -153,6 +155,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) {
@@ -165,10 +185,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);
}
@@ -276,7 +298,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;
@@ -286,7 +309,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);
@@ -389,7 +413,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 ||
@@ -429,7 +453,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));
@@ -495,7 +519,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/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c
index 4360f96a0b9f..a4539f6d6e4b 100644
--- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c
+++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c
@@ -28,6 +28,7 @@
* Copyright 2015, OmniTI Computer Consulting, Inc. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
* Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
+ * Copyright (c) 2019 Datto Inc.
*/
#include <assert.h>
@@ -612,6 +613,7 @@ typedef struct send_data {
const char *tosnap;
boolean_t recursive;
boolean_t verbose;
+ boolean_t replicate;
/*
* The header nvlist is of the following format:
@@ -789,6 +791,7 @@ send_iterate_fs(zfs_handle_t *zhp, void *arg)
send_data_t *sd = arg;
nvlist_t *nvfs, *nv;
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;
@@ -832,10 +835,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,
@@ -855,14 +858,19 @@ send_iterate_fs(zfs_handle_t *zhp, void *arg)
nvlist_free(nv);
/* iterate over snaps, and set sd->parent_fromsnap_guid */
+ if (!sd->replicate && fromsnap_txg != 0)
+ min_txg = fromsnap_txg;
+ if (!sd->replicate && tosnap_txg != 0)
+ max_txg = tosnap_txg;
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_sorted(zhp, send_iterate_snap, sd);
+ (void) zfs_iter_snapshots_sorted(zhp, send_iterate_snap, sd,
+ min_txg, max_txg);
VERIFY(0 == nvlist_add_nvlist(nvfs, "snaps", sd->parent_snaps));
VERIFY(0 == nvlist_add_nvlist(nvfs, "snapprops", sd->snapprops));
- nvlist_free(sd->parent_snaps);
- nvlist_free(sd->snapprops);
+ fnvlist_free(sd->parent_snaps);
+ fnvlist_free(sd->snapprops);
/* add this fs to nvlist */
(void) snprintf(guidstring, sizeof (guidstring),
@@ -886,11 +894,12 @@ out:
static int
gather_nvlist(libzfs_handle_t *hdl, const char *fsname, const char *fromsnap,
const char *tosnap, boolean_t recursive, boolean_t verbose,
- nvlist_t **nvlp, avl_tree_t **avlp)
+ boolean_t replicate, nvlist_t **nvlp, avl_tree_t **avlp)
{
zfs_handle_t *zhp;
- send_data_t sd = { 0 };
int error;
+ uint64_t min_txg = 0, max_txg = 0;
+ send_data_t sd = { 0 };
zhp = zfs_open(hdl, fsname, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
if (zhp == NULL)
@@ -902,6 +911,7 @@ gather_nvlist(libzfs_handle_t *hdl, const char *fsname, const char *fromsnap,
sd.tosnap = tosnap;
sd.recursive = recursive;
sd.verbose = verbose;
+ sd.replicate = replicate;
if ((error = send_iterate_fs(zhp, &sd)) != 0) {
nvlist_free(sd.fss);
@@ -1338,6 +1348,7 @@ static int
dump_filesystem(zfs_handle_t *zhp, void *arg)
{
int rv = 0;
+ uint64_t min_txg = 0, max_txg = 0;
send_dump_data_t *sdd = arg;
boolean_t missingfrom = B_FALSE;
zfs_cmd_t zc = { 0 };
@@ -1373,7 +1384,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"
@@ -1834,7 +1853,7 @@ 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->verbose,
- &fss, &fsavl);
+ flags->replicate, &fss, &fsavl);
if (err)
goto err_out;
VERIFY(0 == nvlist_add_nvlist(hdrnv, "fss", fss));
@@ -2477,7 +2496,7 @@ again:
VERIFY(0 == nvlist_alloc(&deleted, NV_UNIQUE_NAME, 0));
if ((error = gather_nvlist(hdl, tofs, fromsnap, NULL,
- recursive, B_FALSE, &local_nv, &local_avl)) != 0)
+ recursive, B_FALSE, B_FALSE, &local_nv, &local_avl)) != 0)
return (error);
/*
@@ -3554,7 +3573,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
*/
*cp = '\0';
if (gather_nvlist(hdl, zc.zc_value, NULL, NULL, B_FALSE,
- B_FALSE, &local_nv, &local_avl) == 0) {
+ B_FALSE, B_FALSE, &local_nv, &local_avl) == 0) {
*cp = '@';
fs = fsavl_find(local_avl, drrb->drr_toguid, NULL);
fsavl_destroy(local_avl);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
index 6a92fda1a515..88c691ae77ac 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
@@ -33,7 +33,7 @@
* Copyright (c) 2014 Integros [integros.com]
* Copyright 2016 Toomas Soome <tsoome@me.com>
* Copyright 2017 RackTop Systems.
- * Copyright (c) 2017 Datto Inc.
+ * Copyright (c) 2019 Datto Inc.
*/
/*
@@ -2345,7 +2345,8 @@ dataset_name_hidden(const char *name)
* inputs:
* zc_name name of filesystem
* zc_cookie zap cursor
- * zc_nvlist_dst_size size of buffer for property nvlist
+ * zc_nvlist_src iteration range nvlist
+ * zc_nvlist_src_size size of iteration range nvlist
*
* outputs:
* zc_name name of next filesystem
@@ -2414,8 +2415,23 @@ top:
static int
zfs_ioc_snapshot_list_next(zfs_cmd_t *zc)
{
- objset_t *os;
int error;
+ objset_t *os, *ossnap;
+ dsl_dataset_t *ds;
+ uint64_t min_txg = 0, max_txg = 0;
+
+ if (zc->zc_nvlist_src_size != 0) {
+ nvlist_t *props = NULL;
+ error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size,
+ zc->zc_iflags, &props);
+ if (error != 0)
+ return (error);
+ (void) nvlist_lookup_uint64(props, SNAP_ITER_MIN_TXG,
+ &min_txg);
+ (void) nvlist_lookup_uint64(props, SNAP_ITER_MAX_TXG,
+ &max_txg);
+ nvlist_free(props);
+ }
error = dmu_objset_hold(zc->zc_name, FTAG, &os);
if (error != 0) {
@@ -2432,26 +2448,52 @@ zfs_ioc_snapshot_list_next(zfs_cmd_t *zc)
return (SET_ERROR(ESRCH));
}
- error = dmu_snapshot_list_next(os,
- sizeof (zc->zc_name) - strlen(zc->zc_name),
- zc->zc_name + strlen(zc->zc_name), &zc->zc_obj, &zc->zc_cookie,
- NULL);
+ while (error == 0) {
+ if (issig(JUSTLOOKING) && issig(FORREAL)) {
+ error = SET_ERROR(EINTR);
+ break;
+ }
- if (error == 0 && !zc->zc_simple) {
- dsl_dataset_t *ds;
- dsl_pool_t *dp = os->os_dsl_dataset->ds_dir->dd_pool;
+ error = dmu_snapshot_list_next(os,
+ sizeof (zc->zc_name) - strlen(zc->zc_name),
+ zc->zc_name + strlen(zc->zc_name), &zc->zc_obj,
+ &zc->zc_cookie, NULL);
+ if (error == ENOENT) {
+ error = SET_ERROR(ESRCH);
+ break;
+ } else if (error != 0) {
+ break;
+ }
- error = dsl_dataset_hold_obj(dp, zc->zc_obj, FTAG, &ds);
- if (error == 0) {
- objset_t *ossnap;
+ error = dsl_dataset_hold_obj(dmu_objset_pool(os), zc->zc_obj,
+ FTAG, &ds);
+ if (error != 0)
+ break;
- error = dmu_objset_from_ds(ds, &ossnap);
- if (error == 0)
- error = zfs_ioc_objset_stats_impl(zc, ossnap);
+ if ((min_txg != 0 && dsl_get_creationtxg(ds) < min_txg) ||
+ (max_txg != 0 && dsl_get_creationtxg(ds) > max_txg)) {
dsl_dataset_rele(ds, FTAG);
+ /* undo snapshot name append */
+ *(strchr(zc->zc_name, '@') + 1) = '\0';
+ /* skip snapshot */
+ continue;
}
- } else if (error == ENOENT) {
- error = SET_ERROR(ESRCH);
+
+ if (zc->zc_simple) {
+ dsl_dataset_rele(ds, FTAG);
+ break;
+ }
+
+ if ((error = dmu_objset_from_ds(ds, &ossnap)) != 0) {
+ dsl_dataset_rele(ds, FTAG);
+ break;
+ }
+ if ((error = zfs_ioc_objset_stats_impl(zc, ossnap)) != 0) {
+ dsl_dataset_rele(ds, FTAG);
+ break;
+ }
+ dsl_dataset_rele(ds, FTAG);
+ break;
}
dmu_objset_rele(os, FTAG);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h b/sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h
index 461ecc34c80c..35e537f2094d 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h
@@ -26,7 +26,7 @@
* Copyright (c) 2012, Martin Matuska <mm@FreeBSD.org>. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
* Copyright 2017 Joyent, Inc.
- * Copyright (c) 2017 Datto Inc.
+ * Copyright (c) 2019 Datto Inc.
*/
/* Portions Copyright 2010 Robert Milkowski */
@@ -1124,6 +1124,13 @@ typedef enum {
#define ZCP_MAX_MEMLIMIT (10 * ZCP_DEFAULT_MEMLIMIT)
/*
+ * nvlist name constants. Facilitate restricting snapshot iteration range for
+ * the "list next snapshot" ioctl
+ */
+#define SNAP_ITER_MIN_TXG "snap_iter_min_txg"
+#define SNAP_ITER_MAX_TXG "snap_iter_max_txg"
+
+/*
* Sysevent payload members. ZFS will generate the following sysevents with the
* given payloads:
*