summaryrefslogtreecommitdiffstats
path: root/cmd/zfs/zfs_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/zfs/zfs_main.c')
-rw-r--r--cmd/zfs/zfs_main.c41
1 files changed, 34 insertions, 7 deletions
diff --git a/cmd/zfs/zfs_main.c b/cmd/zfs/zfs_main.c
index 12a5cf6cf..21c4d4334 100644
--- a/cmd/zfs/zfs_main.c
+++ b/cmd/zfs/zfs_main.c
@@ -27,7 +27,7 @@
* Copyright (c) 2013 Steven Hartland. All rights reserved.
* Copyright 2016 Igor Kozhukhov <[email protected]>.
* Copyright 2016 Nexenta Systems, Inc.
- * Copyright (c) 2018 Datto Inc.
+ * Copyright (c) 2019 Datto Inc.
*/
#include <assert.h>
@@ -1255,7 +1255,7 @@ destroy_print_snapshots(zfs_handle_t *fs_zhp, destroy_cbdata_t *cb)
int err;
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) {
@@ -3581,6 +3581,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;
@@ -3612,15 +3613,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);
@@ -3649,9 +3655,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);
}
@@ -3665,6 +3686,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) {
@@ -3720,7 +3742,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;