summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorahrens <none@none>2007-12-22 14:50:27 -0800
committerahrens <none@none>2007-12-22 14:50:27 -0800
commitc391e322108d10533bc61ba3ef7099b302214341 (patch)
treeb63be41e4121dfe6c38d2404978e71cdb0885f15
parentf8919bdadda3ebb97bd55cc14a16e0271ed57615 (diff)
downloadillumos-gate-c391e322108d10533bc61ba3ef7099b302214341.tar.gz
PSARC/2007/699 zfs rollback -f operative
6641210 zfs rollback -R fails with EBUSY if there is a clone
-rw-r--r--usr/src/cmd/zfs/zfs_main.c8
-rw-r--r--usr/src/lib/libzfs/common/libzfs.h2
-rw-r--r--usr/src/lib/libzfs/common/libzfs_dataset.c27
3 files changed, 26 insertions, 11 deletions
diff --git a/usr/src/cmd/zfs/zfs_main.c b/usr/src/cmd/zfs/zfs_main.c
index 4709b388c9..d5840f5521 100644
--- a/usr/src/cmd/zfs/zfs_main.c
+++ b/usr/src/cmd/zfs/zfs_main.c
@@ -2003,6 +2003,7 @@ zfs_do_rollback(int argc, char **argv)
{
int ret;
int c;
+ boolean_t force = B_FALSE;
rollback_cbdata_t cb = { 0 };
zfs_handle_t *zhp, *snap;
char parentname[ZFS_MAXNAMELEN];
@@ -2019,10 +2020,7 @@ zfs_do_rollback(int argc, char **argv)
cb.cb_doclones = 1;
break;
case 'f':
- /*
- * this is accepted and ignored for backwards
- * compatability.
- */
+ force = B_TRUE;
break;
case '?':
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
@@ -2074,7 +2072,7 @@ zfs_do_rollback(int argc, char **argv)
/*
* Rollback parent to the given snapshot.
*/
- ret = zfs_rollback(zhp, snap);
+ ret = zfs_rollback(zhp, snap, force);
out:
zfs_close(snap);
diff --git a/usr/src/lib/libzfs/common/libzfs.h b/usr/src/lib/libzfs/common/libzfs.h
index 42aeace50b..afd95ee87e 100644
--- a/usr/src/lib/libzfs/common/libzfs.h
+++ b/usr/src/lib/libzfs/common/libzfs.h
@@ -417,7 +417,7 @@ extern int zfs_destroy(zfs_handle_t *);
extern int zfs_destroy_snaps(zfs_handle_t *, char *);
extern int zfs_clone(zfs_handle_t *, const char *, nvlist_t *);
extern int zfs_snapshot(libzfs_handle_t *, const char *, boolean_t);
-extern int zfs_rollback(zfs_handle_t *, zfs_handle_t *);
+extern int zfs_rollback(zfs_handle_t *, zfs_handle_t *, boolean_t);
extern int zfs_rename(zfs_handle_t *, const char *, boolean_t);
extern int zfs_send(zfs_handle_t *, const char *, const char *,
boolean_t, boolean_t, boolean_t, boolean_t, int);
diff --git a/usr/src/lib/libzfs/common/libzfs_dataset.c b/usr/src/lib/libzfs/common/libzfs_dataset.c
index 347faa485c..5459514662 100644
--- a/usr/src/lib/libzfs/common/libzfs_dataset.c
+++ b/usr/src/lib/libzfs/common/libzfs_dataset.c
@@ -3331,8 +3331,9 @@ zfs_snapshot(libzfs_handle_t *hdl, const char *path, boolean_t recursive)
typedef struct rollback_data {
const char *cb_target; /* the snapshot */
uint64_t cb_create; /* creation time reference */
- int cb_error;
+ boolean_t cb_error;
boolean_t cb_dependent;
+ boolean_t cb_force;
} rollback_data_t;
static int
@@ -3358,7 +3359,22 @@ rollback_destroy(zfs_handle_t *zhp, void *data)
zhp->zfs_hdl->libzfs_log_str = logstr;
}
} else {
- cbp->cb_error |= zfs_destroy(zhp);
+ /* We must destroy this clone; first unmount it */
+ prop_changelist_t *clp;
+
+ clp = changelist_gather(zhp, ZFS_PROP_NAME,
+ cbp->cb_force ? MS_FORCE: 0);
+ if (clp == NULL || changelist_prefix(clp) != 0) {
+ cbp->cb_error = B_TRUE;
+ zfs_close(zhp);
+ return (0);
+ }
+ if (zfs_destroy(zhp) != 0)
+ cbp->cb_error = B_TRUE;
+ else
+ changelist_remove(clp, zhp->zfs_name);
+ changelist_postfix(clp);
+ changelist_free(clp);
}
zfs_close(zhp);
@@ -3373,7 +3389,7 @@ rollback_destroy(zfs_handle_t *zhp, void *data)
* their dependents.
*/
int
-zfs_rollback(zfs_handle_t *zhp, zfs_handle_t *snap)
+zfs_rollback(zfs_handle_t *zhp, zfs_handle_t *snap, boolean_t force)
{
rollback_data_t cb = { 0 };
int err;
@@ -3388,12 +3404,13 @@ zfs_rollback(zfs_handle_t *zhp, zfs_handle_t *snap)
/*
* Destroy all recent snapshots and its dependends.
*/
+ cb.cb_force = force;
cb.cb_target = snap->zfs_name;
cb.cb_create = zfs_prop_get_int(snap, ZFS_PROP_CREATETXG);
(void) zfs_iter_children(zhp, rollback_destroy, &cb);
- if (cb.cb_error != 0)
- return (cb.cb_error);
+ if (cb.cb_error)
+ return (-1);
/*
* Now that we have verified that the snapshot is the latest,