]> git.proxmox.com Git - mirror_zfs.git/commitdiff
zcp: add zfs.sync.bookmark
authorChristian Schwarz <me@cschwarz.com>
Thu, 16 Jan 2020 01:15:05 +0000 (02:15 +0100)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Tue, 11 Feb 2020 21:19:17 +0000 (13:19 -0800)
Add support for bookmark creation and cloning.

Reviewed-by: Matt Ahrens <matt@delphix.com>
Reviewed-by: Paul Dagnelie <pcd@delphix.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Christian Schwarz <me@cschwarz.com>
Closes #9571

include/sys/dsl_bookmark.h
man/man8/zfs-program.8
module/zfs/dsl_bookmark.c
module/zfs/zcp_synctask.c
tests/runfiles/common.run
tests/zfs-tests/tests/functional/channel_program/synctask_core/Makefile.am
tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.copy.ksh [new file with mode: 0755]
tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.copy.zcp [new file with mode: 0644]
tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.create.ksh [new file with mode: 0755]
tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.create.zcp [new file with mode: 0644]

index ec3895d405037b37538cd10af13e29e8d3f75253..73424e5a86f90472d138c4acb79338b60e612a92 100644 (file)
@@ -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 *);
index f953cf18fa0ecb09e2d793cca4927ca349787979..c754fcf99fa4ea9598f222243d292c6acae055d5 100644 (file)
@@ -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
index 5a73c5300dc77917096cbe5d9a338ef2afa7b688..45ba4b5571525344d24cfd7e3d4e22ab58e7bd42 100644 (file)
@@ -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;
index 22fec6f3fe7e2ec62163d9259cc1ce7b8a2e6dc0..a6f7a04c7131349f5e373e586361873637353c11 100644 (file)
@@ -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
        };
 
index 691cae9cbbb158d69a7a572cb1cd9502269559eb..e4593a53ec02d63e010b75698809075496e3373c 100644 (file)
@@ -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']
index 5330edaf277c3d0544ff8297fb015873bb68e296..e74c5223b552a4d7eba46c8d39cb507ed0eaba83 100644 (file)
@@ -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 (executable)
index 0000000..81f570d
--- /dev/null
@@ -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 (file)
index 0000000..9473035
--- /dev/null
@@ -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 (executable)
index 0000000..05ec9cc
--- /dev/null
@@ -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 (file)
index 0000000..eb53fd1
--- /dev/null
@@ -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]))