summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sys/dsl_dataset.h12
-rw-r--r--man/man8/zfs-program.814
-rw-r--r--module/zfs/dsl_dataset.c13
-rw-r--r--module/zfs/zcp_synctask.c34
-rw-r--r--tests/runfiles/linux.run4
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/synctask_core/Makefile.am4
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.rollback_mult.ksh61
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.rollback_one.ksh51
8 files changed, 177 insertions, 16 deletions
diff --git a/include/sys/dsl_dataset.h b/include/sys/dsl_dataset.h
index 4bf0cb31f..ee822a201 100644
--- a/include/sys/dsl_dataset.h
+++ b/include/sys/dsl_dataset.h
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, 2016 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2017 by Delphix. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
* Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
*/
@@ -245,6 +245,13 @@ typedef struct dsl_dataset_promote_arg {
cred_t *cr;
} dsl_dataset_promote_arg_t;
+typedef struct dsl_dataset_rollback_arg {
+ const char *ddra_fsname;
+ const char *ddra_tosnap;
+ void *ddra_owner;
+ nvlist_t *ddra_result;
+} dsl_dataset_rollback_arg_t;
+
/*
* The max length of a temporary tag prefix is the number of hex digits
* required to express UINT64_MAX plus one for the hyphen.
@@ -394,6 +401,9 @@ void dsl_dataset_set_refreservation_sync_impl(dsl_dataset_t *ds,
void dsl_dataset_zapify(dsl_dataset_t *ds, dmu_tx_t *tx);
boolean_t dsl_dataset_is_zapified(dsl_dataset_t *ds);
boolean_t dsl_dataset_has_resume_receive_state(dsl_dataset_t *ds);
+
+int dsl_dataset_rollback_check(void *arg, dmu_tx_t *tx);
+void dsl_dataset_rollback_sync(void *arg, dmu_tx_t *tx);
int dsl_dataset_rollback(const char *fsname, const char *tosnap, void *owner,
nvlist_t *result);
diff --git a/man/man8/zfs-program.8 b/man/man8/zfs-program.8
index 2e4e9587d..4c7d86ef1 100644
--- a/man/man8/zfs-program.8
+++ b/man/man8/zfs-program.8
@@ -8,7 +8,7 @@
.\" http://www.illumos.org/license/CDDL.
.\"
.\"
-.\" Copyright (c) 2016 by Delphix. All Rights Reserved.
+.\" Copyright (c) 2016, 2017 by Delphix. All Rights Reserved.
.\"
.Dd January 21, 2016
.Dt ZFS-PROGRAM 8
@@ -361,6 +361,17 @@ dataset (string)
.Bd -ragged -compact -offset "xxxx"
Clone to be promoted.
.Ed
+.It Em zfs.sync.rollback(filesystem)
+Rollback to the previous snapshot for a dataset.
+Returns 0 on successful rollback, or a nonzero error code otherwise.
+Rollbacks can be performed on filesystems or zvols, but not on snapshots
+or mounted datasets.
+EBUSY is returned in the case where the filesystem is mounted.
+.Pp
+filesystem (string)
+.Bd -ragged -compact -offset "xxxx"
+Filesystem to rollback.
+.Ed
.El
.It Sy zfs.check submodule
For each function in the zfs.sync submodule, there is a corresponding zfs.check
@@ -380,6 +391,7 @@ The available zfs.check functions are:
.Bl -tag -width "xx"
.It Em zfs.check.destroy(dataset, [defer=true|false])
.It Em zfs.check.promote(dataset)
+.It Em zfs.check.rollback(filesystem)
.El
.It Sy zfs.list submodule
The zfs.list submodule provides functions for iterating over datasets and
diff --git a/module/zfs/dsl_dataset.c b/module/zfs/dsl_dataset.c
index af3dc230a..a35ba1f7e 100644
--- a/module/zfs/dsl_dataset.c
+++ b/module/zfs/dsl_dataset.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, 2016 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2017 by Delphix. All rights reserved.
* Copyright (c) 2014, Joyent, Inc. All rights reserved.
* Copyright (c) 2014 RackTop Systems.
* Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
@@ -2526,14 +2526,7 @@ dsl_dataset_handoff_check(dsl_dataset_t *ds, void *owner, dmu_tx_t *tx)
return (0);
}
-typedef struct dsl_dataset_rollback_arg {
- const char *ddra_fsname;
- const char *ddra_tosnap;
- void *ddra_owner;
- nvlist_t *ddra_result;
-} dsl_dataset_rollback_arg_t;
-
-static int
+int
dsl_dataset_rollback_check(void *arg, dmu_tx_t *tx)
{
dsl_dataset_rollback_arg_t *ddra = arg;
@@ -2641,7 +2634,7 @@ dsl_dataset_rollback_check(void *arg, dmu_tx_t *tx)
return (0);
}
-static void
+void
dsl_dataset_rollback_sync(void *arg, dmu_tx_t *tx)
{
dsl_dataset_rollback_arg_t *ddra = arg;
diff --git a/module/zfs/zcp_synctask.c b/module/zfs/zcp_synctask.c
index 923d5ca67..93797e9f3 100644
--- a/module/zfs/zcp_synctask.c
+++ b/module/zfs/zcp_synctask.c
@@ -14,7 +14,7 @@
*/
/*
- * Copyright (c) 2016 by Delphix. All rights reserved.
+ * Copyright (c) 2016, 2017 by Delphix. All rights reserved.
*/
#include <sys/lua/lua.h>
@@ -177,6 +177,37 @@ zcp_synctask_promote(lua_State *state, boolean_t sync, nvlist_t *err_details)
return (err);
}
+static int zcp_synctask_rollback(lua_State *, boolean_t, nvlist_t *err_details);
+static zcp_synctask_info_t zcp_synctask_rollback_info = {
+ .name = "rollback",
+ .func = zcp_synctask_rollback,
+ .space_check = ZFS_SPACE_CHECK_RESERVED,
+ .blocks_modified = 1,
+ .pargs = {
+ {.za_name = "filesystem", .za_lua_type = LUA_TSTRING},
+ {0, 0}
+ },
+ .kwargs = {
+ {0, 0}
+ }
+};
+
+static int
+zcp_synctask_rollback(lua_State *state, boolean_t sync, nvlist_t *err_details)
+{
+ int err;
+ const char *dsname = lua_tostring(state, 1);
+ dsl_dataset_rollback_arg_t ddra = { 0 };
+
+ ddra.ddra_fsname = dsname;
+ ddra.ddra_result = err_details;
+
+ err = zcp_sync_task(state, dsl_dataset_rollback_check,
+ dsl_dataset_rollback_sync, &ddra, sync, dsname);
+
+ return (err);
+}
+
void
zcp_synctask_wrapper_cleanup(void *arg)
{
@@ -247,6 +278,7 @@ zcp_load_synctask_lib(lua_State *state, boolean_t sync)
zcp_synctask_info_t *zcp_synctask_funcs[] = {
&zcp_synctask_destroy_info,
&zcp_synctask_promote_info,
+ &zcp_synctask_rollback_info,
NULL
};
diff --git a/tests/runfiles/linux.run b/tests/runfiles/linux.run
index 04f0163f3..0320301d2 100644
--- a/tests/runfiles/linux.run
+++ b/tests/runfiles/linux.run
@@ -77,8 +77,8 @@ tests = ['tst.destroy_fs', 'tst.destroy_snap', 'tst.get_count_and_limit',
'tst.get_number_props', 'tst.get_string_props', 'tst.get_type',
'tst.get_userquota', 'tst.get_written', 'tst.list_children',
'tst.list_clones', 'tst.list_snapshots', 'tst.list_system_props',
- 'tst.parse_args_neg','tst.promote_conflict', 'tst.promote_multiple',
- 'tst.promote_simple']
+ 'tst.parse_args_neg', 'tst.promote_conflict', 'tst.promote_multiple',
+ 'tst.promote_simple', 'tst.rollback_mult', 'tst.rollback_one']
tags = ['functional', 'channel_program', 'synctask_core']
[tests/functional/chattr]
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/Makefile.am b/tests/zfs-tests/tests/functional/channel_program/synctask_core/Makefile.am
index cd347472c..29bd68eee 100644
--- a/tests/zfs-tests/tests/functional/channel_program/synctask_core/Makefile.am
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/Makefile.am
@@ -27,4 +27,6 @@ dist_pkgdata_SCRIPTS = \
tst.promote_conflict.ksh \
tst.promote_conflict.zcp \
tst.promote_multiple.ksh \
- tst.promote_simple.ksh
+ tst.promote_simple.ksh \
+ tst.rollback_mult.ksh \
+ tst.rollback_one.ksh
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.rollback_mult.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.rollback_mult.ksh
new file mode 100755
index 000000000..778abc09d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.rollback_mult.ksh
@@ -0,0 +1,61 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2016, 2017 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+verify_runnable "global"
+snap1=$TESTPOOL/$TESTFS@$TESTSNAP1
+snap2=$TESTPOOL/$TESTFS@$TESTSNAP2
+fs=$TESTPOOL/$TESTFS
+file=$TESTDIR/$TESTFILE0
+
+function cleanup
+{
+ datasetexists $snap1 && log_must zfs destroy $snap1 && \
+ log_must rm $file
+}
+
+log_onexit cleanup
+
+log_must mkfile 128b $file
+create_snapshot $TESTPOOL/$TESTFS $TESTSNAP1
+log_must rm $file
+create_snapshot $TESTPOOL/$TESTFS $TESTSNAP2
+
+log_must snapexists $snap1
+log_must snapexists $snap2
+log_must zfs unmount $fs
+
+log_must_program $TESTPOOL - $fs $snap2 <<-EOF
+ arg = ...
+ fs = arg["argv"][1]
+ snap = arg["argv"][2]
+ err = zfs.sync.rollback(fs)
+ if err == 0 then
+ err = zfs.sync.destroy(snap)
+ end
+ if err == 0 then
+ err = zfs.sync.rollback(fs)
+ end
+ msg = "rolling back " .. fs .. " err=" .. err
+ return msg
+EOF
+
+log_must zfs mount $fs
+log_must [ -f $file ]
+log_mustnot snapexists $snap2
+
+log_pass "Rolling back snapshot with channel program works."
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.rollback_one.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.rollback_one.ksh
new file mode 100755
index 000000000..2a8e83913
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.rollback_one.ksh
@@ -0,0 +1,51 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2016, 2017 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+verify_runnable "global"
+snap=$TESTPOOL/$TESTFS@$TESTSNAP
+fs=$TESTPOOL/$TESTFS
+file=$TESTDIR/$TESTFILE0
+
+function cleanup
+{
+ datasetexists $snap && log_must zfs destroy $snap && \
+ log_must rm $file
+
+}
+
+log_onexit cleanup
+
+log_must mkfile 128b $file
+create_snapshot $TESTPOOL/$TESTFS $TESTSNAP
+log_must rm $file
+
+log_must snapexists $snap
+log_must zfs unmount $fs
+
+log_must_program $TESTPOOL - $fs <<-EOF
+ arg = ...
+ fs = arg["argv"][1]
+ err = zfs.sync.rollback(fs)
+ msg = "rolling back " .. fs .. " err=" .. err
+ return msg
+EOF
+
+log_must zfs mount $fs
+log_must [ -f $file ]
+
+log_pass "Rolling back snapshot with channel program works."