summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sys/dsl_bookmark.h17
-rw-r--r--man/man8/zfs-program.816
-rw-r--r--module/zfs/dsl_bookmark.c16
-rw-r--r--module/zfs/zcp_synctask.c45
-rw-r--r--tests/runfiles/common.run2
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/synctask_core/Makefile.am6
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.copy.ksh45
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.copy.zcp32
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.create.ksh43
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.create.zcp26
10 files changed, 231 insertions, 17 deletions
diff --git a/include/sys/dsl_bookmark.h b/include/sys/dsl_bookmark.h
index ec3895d40..73424e5a8 100644
--- a/include/sys/dsl_bookmark.h
+++ b/include/sys/dsl_bookmark.h
@@ -102,8 +102,25 @@ typedef struct redact_block_phys {
typedef int (*rl_traverse_callback_t)(redact_block_phys_t *, void *);
+
+typedef struct dsl_bookmark_create_arg {
+ nvlist_t *dbca_bmarks;
+ nvlist_t *dbca_errors;
+} dsl_bookmark_create_arg_t;
+
+typedef struct dsl_bookmark_create_redacted_arg {
+ const char *dbcra_bmark;
+ const char *dbcra_snap;
+ redaction_list_t **dbcra_rl;
+ uint64_t dbcra_numsnaps;
+ uint64_t *dbcra_snaps;
+ void *dbcra_tag;
+} dsl_bookmark_create_redacted_arg_t;
+
int dsl_bookmark_create(nvlist_t *, nvlist_t *);
int dsl_bookmark_create_nvl_validate(nvlist_t *);
+int dsl_bookmark_create_check(void *arg, dmu_tx_t *tx);
+void dsl_bookmark_create_sync(void *arg, dmu_tx_t *tx);
int dsl_bookmark_create_redacted(const char *, const char *, uint64_t,
uint64_t *, void *, redaction_list_t **);
int dsl_get_bookmarks(const char *, nvlist_t *, nvlist_t *);
diff --git a/man/man8/zfs-program.8 b/man/man8/zfs-program.8
index f953cf18f..c754fcf99 100644
--- a/man/man8/zfs-program.8
+++ b/man/man8/zfs-program.8
@@ -9,6 +9,7 @@
.\"
.\"
.\" Copyright (c) 2016, 2019 by Delphix. All Rights Reserved.
+.\" Copyright (c) 2019, 2020 by Christian Schwarz. All Rights Reserved.
.\" Copyright 2020 Joyent, Inc.
.\"
.Dd January 15, 2020
@@ -419,6 +420,21 @@ dataset (string)
.Bd -ragged -compact -offset "xxxx"
Name of snapshot to create.
.Ed
+.It Em zfs.sync.bookmark(source, newbookmark)
+Create a bookmark of an existing source snapshot or bookmark.
+Returns 0 if the new bookmark was successfully created,
+and a nonzero error code otherwise.
+.Pp
+Note: Bookmarking requires the corresponding pool feature to be enabled.
+.Pp
+source (string)
+.Bd -ragged -compact -offset "xxxx"
+Full name of the existing snapshot or bookmark.
+.Ed
+.Pp
+newbookmark (string)
+.Bd -ragged -compact -offset "xxxx"
+Full name of the new bookmark.
.El
.It Sy zfs.check submodule
For each function in the zfs.sync submodule, there is a corresponding zfs.check
diff --git a/module/zfs/dsl_bookmark.c b/module/zfs/dsl_bookmark.c
index 5a73c5300..45ba4b557 100644
--- a/module/zfs/dsl_bookmark.c
+++ b/module/zfs/dsl_bookmark.c
@@ -205,20 +205,6 @@ dsl_bookmark_create_nvl_validate(nvlist_t *bmarks)
return (0);
}
-typedef struct dsl_bookmark_create_redacted_arg {
- const char *dbcra_bmark;
- const char *dbcra_snap;
- redaction_list_t **dbcra_rl;
- uint64_t dbcra_numsnaps;
- uint64_t *dbcra_snaps;
- void *dbcra_tag;
-} dsl_bookmark_create_redacted_arg_t;
-
-typedef struct dsl_bookmark_create_arg {
- nvlist_t *dbca_bmarks;
- nvlist_t *dbca_errors;
-} dsl_bookmark_create_arg_t;
-
/*
* expects that newbm and source have been validated using
* dsl_bookmark_create_nvl_validate_pair
@@ -301,7 +287,7 @@ eholdnewbmds:
return (error);
}
-static int
+int
dsl_bookmark_create_check(void *arg, dmu_tx_t *tx)
{
dsl_bookmark_create_arg_t *dbca = arg;
diff --git a/module/zfs/zcp_synctask.c b/module/zfs/zcp_synctask.c
index 22fec6f3f..a6f7a04c7 100644
--- a/module/zfs/zcp_synctask.c
+++ b/module/zfs/zcp_synctask.c
@@ -15,6 +15,7 @@
/*
* Copyright (c) 2016, 2017 by Delphix. All rights reserved.
+ * Copyright (c) 2019, 2020 by Christian Schwarz. All rights reserved.
* Copyright 2020 Joyent, Inc.
*/
@@ -370,6 +371,49 @@ zcp_synctask_inherit_prop(lua_State *state, boolean_t sync,
return (err);
}
+static int zcp_synctask_bookmark(lua_State *, boolean_t, nvlist_t *);
+static zcp_synctask_info_t zcp_synctask_bookmark_info = {
+ .name = "bookmark",
+ .func = zcp_synctask_bookmark,
+ .pargs = {
+ {.za_name = "snapshot | bookmark", .za_lua_type = LUA_TSTRING},
+ {.za_name = "bookmark", .za_lua_type = LUA_TSTRING},
+ {NULL, 0}
+ },
+ .kwargs = {
+ {NULL, 0}
+ },
+ .space_check = ZFS_SPACE_CHECK_NORMAL,
+ .blocks_modified = 1,
+};
+
+/* ARGSUSED */
+static int
+zcp_synctask_bookmark(lua_State *state, boolean_t sync, nvlist_t *err_details)
+{
+ int err;
+ const char *source = lua_tostring(state, 1);
+ const char *new = lua_tostring(state, 2);
+
+ nvlist_t *bmarks = fnvlist_alloc();
+ fnvlist_add_string(bmarks, new, source);
+
+ zcp_cleanup_handler_t *zch = zcp_register_cleanup(state,
+ (zcp_cleanup_t *)&fnvlist_free, bmarks);
+
+ dsl_bookmark_create_arg_t dbca = {
+ .dbca_bmarks = bmarks,
+ .dbca_errors = NULL,
+ };
+ err = zcp_sync_task(state, dsl_bookmark_create_check,
+ dsl_bookmark_create_sync, &dbca, sync, source);
+
+ zcp_deregister_cleanup(state, zch);
+ fnvlist_free(bmarks);
+
+ return (err);
+}
+
static int
zcp_synctask_wrapper(lua_State *state)
{
@@ -439,6 +483,7 @@ zcp_load_synctask_lib(lua_State *state, boolean_t sync)
&zcp_synctask_rollback_info,
&zcp_synctask_snapshot_info,
&zcp_synctask_inherit_prop_info,
+ &zcp_synctask_bookmark_info,
NULL
};
diff --git a/tests/runfiles/common.run b/tests/runfiles/common.run
index 691cae9cb..e4593a53e 100644
--- a/tests/runfiles/common.run
+++ b/tests/runfiles/common.run
@@ -87,7 +87,7 @@ tests = ['tst.destroy_fs', 'tst.destroy_snap', 'tst.get_count_and_limit',
'tst.promote_multiple', 'tst.promote_simple', 'tst.rollback_mult',
'tst.rollback_one', 'tst.snapshot_destroy', 'tst.snapshot_neg',
'tst.snapshot_recursive', 'tst.snapshot_simple',
- 'tst.bookmark.create', 'tst.bookmark.clone',
+ 'tst.bookmark.create', 'tst.bookmark.copy',
'tst.terminate_by_signal'
]
tags = ['functional', 'channel_program', 'synctask_core']
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 5330edaf2..e74c5223b 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
@@ -30,6 +30,8 @@ dist_pkgdata_SCRIPTS = \
tst.snapshot_destroy.ksh \
tst.snapshot_neg.ksh \
tst.snapshot_recursive.ksh \
+ tst.bookmark.create.ksh \
+ tst.bookmark.copy.ksh \
tst.snapshot_simple.ksh \
tst.terminate_by_signal.ksh
@@ -44,4 +46,6 @@ dist_pkgdata_DATA = \
tst.snapshot_destroy.zcp \
tst.snapshot_neg.zcp \
tst.snapshot_recursive.zcp \
- tst.snapshot_simple.zcp
+ tst.snapshot_simple.zcp \
+ tst.bookmark.create.zcp \
+ tst.bookmark.copy.zcp
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.copy.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.copy.ksh
new file mode 100755
index 000000000..81f570d9e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.copy.ksh
@@ -0,0 +1,45 @@
+#!/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) 2019, 2020 by Christian Schwarz. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION: Make sure bookmark copying works in channel programs
+#
+
+verify_runnable "global"
+
+fs=$TESTPOOL/$TESTFS/testchild
+snapname=testsnap
+bookname=testbookmark
+bookcopyname=testbookmark_copy
+
+function cleanup
+{
+ destroy_dataset $fs "-R"
+}
+
+log_onexit cleanup
+
+log_must zfs create $fs
+
+log_must zfs snapshot $fs@$snapname
+log_must zfs bookmark $fs@$snapname "$fs#$bookname"
+
+log_must_program_sync $TESTPOOL \
+ $ZCP_ROOT/synctask_core/tst.bookmark.copy.zcp $fs $bookname $bookcopyname
+
+log_pass "Simple bookmark copying works"
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.copy.zcp b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.copy.zcp
new file mode 100644
index 000000000..9473035f0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.copy.zcp
@@ -0,0 +1,32 @@
+--
+-- 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) 2019, 2020 by Christian Schwarz. All rights reserved.
+--
+
+-- This program should be invoked as "zfs program <pool> <prog> <fs> <source_book> <new_book>"
+
+args = ...
+argv = args["argv"]
+fs = argv[1]
+source = fs .. "#" .. argv[2]
+new = fs .. "#" .. argv[3]
+assert(zfs.sync.bookmark(source, new) == 0)
+books = {}
+count = 0
+for s in zfs.list.bookmarks(fs) do
+ count = count + 1
+ books[s] = 1
+end
+assert(count == 2)
+assert(books[source] == 1)
+assert(books[new] == 1)
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.create.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.create.ksh
new file mode 100755
index 000000000..05ec9cc67
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.create.ksh
@@ -0,0 +1,43 @@
+#!/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) 2019, 2020 by Christian Schwarz. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION: Make sure basic bookmark functionality works in channel programs
+#
+
+verify_runnable "global"
+
+fs=$TESTPOOL/$TESTFS/testchild
+snapname=testsnap
+bookname=testbookmark
+
+function cleanup
+{
+ destroy_dataset $fs "-R"
+}
+
+log_onexit cleanup
+
+log_must zfs create $fs
+
+log_must zfs snapshot $fs@$snapname
+
+log_must_program_sync $TESTPOOL \
+ $ZCP_ROOT/synctask_core/tst.bookmark.create.zcp $fs $snapname $bookname
+
+log_pass "Simple bookmark creation works"
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.create.zcp b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.create.zcp
new file mode 100644
index 000000000..eb53fd16c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.create.zcp
@@ -0,0 +1,26 @@
+--
+-- 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) 2019, 2020 by Christian Schwarz. All rights reserved.
+--
+
+-- This program should be invoked as "zfs program <pool> <prog> <fs> <snap> <book>"
+
+args = ...
+argv = args["argv"]
+assert(zfs.sync.bookmark(argv[1] .. "@" .. argv[2], argv[1] .. "#" .. argv[3]) == 0)
+books = {}
+for s in zfs.list.bookmarks(argv[1]) do
+ table.insert(books, s)
+end
+assert(#books == 1)
+assert(books[1] == (argv[1] .. "#" .. argv[3]))