diff options
author | ahrens <none@none> | 2007-12-22 14:50:27 -0800 |
---|---|---|
committer | ahrens <none@none> | 2007-12-22 14:50:27 -0800 |
commit | c391e322108d10533bc61ba3ef7099b302214341 (patch) | |
tree | b63be41e4121dfe6c38d2404978e71cdb0885f15 | |
parent | f8919bdadda3ebb97bd55cc14a16e0271ed57615 (diff) | |
download | illumos-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.c | 8 | ||||
-rw-r--r-- | usr/src/lib/libzfs/common/libzfs.h | 2 | ||||
-rw-r--r-- | usr/src/lib/libzfs/common/libzfs_dataset.c | 27 |
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, |