Add zfs.sync.snapshot_rename

Only the single snapshot rename is provided.
The recursive or more complex rename can be scripted.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: George Melikov <mail@gmelikov.ru>
Signed-off-by: Andriy Gapon <avg@FreeBSD.org>
Closes #13802
This commit is contained in:
Andriy Gapon 2022-09-02 23:31:19 +03:00 committed by GitHub
parent 7bb707ffaf
commit ee9f3bca55
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 133 additions and 10 deletions

View File

@ -301,6 +301,14 @@ typedef struct dsl_dataset_snapshot_arg {
proc_t *ddsa_proc; proc_t *ddsa_proc;
} dsl_dataset_snapshot_arg_t; } dsl_dataset_snapshot_arg_t;
typedef struct dsl_dataset_rename_snapshot_arg {
const char *ddrsa_fsname;
const char *ddrsa_oldsnapname;
const char *ddrsa_newsnapname;
boolean_t ddrsa_recursive;
dmu_tx_t *ddrsa_tx;
} dsl_dataset_rename_snapshot_arg_t;
/* /*
* The max length of a temporary tag prefix is the number of hex digits * The max length of a temporary tag prefix is the number of hex digits
* required to express UINT64_MAX plus one for the hyphen. * required to express UINT64_MAX plus one for the hyphen.
@ -473,6 +481,9 @@ void dsl_dataset_rollback_sync(void *arg, dmu_tx_t *tx);
int dsl_dataset_rollback(const char *fsname, const char *tosnap, void *owner, int dsl_dataset_rollback(const char *fsname, const char *tosnap, void *owner,
nvlist_t *result); nvlist_t *result);
int dsl_dataset_rename_snapshot_check(void *arg, dmu_tx_t *tx);
void dsl_dataset_rename_snapshot_sync(void *arg, dmu_tx_t *tx);
uint64_t dsl_dataset_get_remap_deadlist_object(dsl_dataset_t *ds); uint64_t dsl_dataset_get_remap_deadlist_object(dsl_dataset_t *ds);
void dsl_dataset_create_remap_deadlist(dsl_dataset_t *ds, dmu_tx_t *tx); void dsl_dataset_create_remap_deadlist(dsl_dataset_t *ds, dmu_tx_t *tx);
boolean_t dsl_dataset_remap_deadlist_exists(dsl_dataset_t *ds); boolean_t dsl_dataset_remap_deadlist_exists(dsl_dataset_t *ds);

View File

@ -424,6 +424,19 @@ To enable taking snapshots from ZCP scripts, the pool must be upgraded.
.It Ar dataset Pq string .It Ar dataset Pq string
Name of snapshot to create. Name of snapshot to create.
.El .El
.It Fn zfs.sync.rename_snapshot dataset oldsnapname newsnapname
Rename a snapshot of a filesystem or a volume.
Returns 0 if the snapshot was successfully renamed,
and a nonzero error code otherwise.
.Pp
.Bl -tag -compact -width "newbookmark (string)"
.It Ar dataset Pq string
Name of the snapshot's parent dataset.
.It Ar oldsnapname Pq string
Original name of the snapshot.
.It Ar newsnapname Pq string
New name of the snapshot.
.El
.It Fn zfs.sync.bookmark source newbookmark .It Fn zfs.sync.bookmark source newbookmark
Create a bookmark of an existing source snapshot or bookmark. Create a bookmark of an existing source snapshot or bookmark.
Returns 0 if the new bookmark was successfully created, Returns 0 if the new bookmark was successfully created,

View File

@ -2915,14 +2915,6 @@ dsl_dataset_modified_since_snap(dsl_dataset_t *ds, dsl_dataset_t *snap)
return (B_FALSE); return (B_FALSE);
} }
typedef struct dsl_dataset_rename_snapshot_arg {
const char *ddrsa_fsname;
const char *ddrsa_oldsnapname;
const char *ddrsa_newsnapname;
boolean_t ddrsa_recursive;
dmu_tx_t *ddrsa_tx;
} dsl_dataset_rename_snapshot_arg_t;
static int static int
dsl_dataset_rename_snapshot_check_impl(dsl_pool_t *dp, dsl_dataset_rename_snapshot_check_impl(dsl_pool_t *dp,
dsl_dataset_t *hds, void *arg) dsl_dataset_t *hds, void *arg)
@ -2953,7 +2945,7 @@ dsl_dataset_rename_snapshot_check_impl(dsl_pool_t *dp,
return (error); return (error);
} }
static int int
dsl_dataset_rename_snapshot_check(void *arg, dmu_tx_t *tx) dsl_dataset_rename_snapshot_check(void *arg, dmu_tx_t *tx)
{ {
dsl_dataset_rename_snapshot_arg_t *ddrsa = arg; dsl_dataset_rename_snapshot_arg_t *ddrsa = arg;
@ -3015,7 +3007,7 @@ dsl_dataset_rename_snapshot_sync_impl(dsl_pool_t *dp,
return (0); return (0);
} }
static void void
dsl_dataset_rename_snapshot_sync(void *arg, dmu_tx_t *tx) dsl_dataset_rename_snapshot_sync(void *arg, dmu_tx_t *tx)
{ {
dsl_dataset_rename_snapshot_arg_t *ddrsa = arg; dsl_dataset_rename_snapshot_arg_t *ddrsa = arg;

View File

@ -302,6 +302,42 @@ zcp_synctask_snapshot(lua_State *state, boolean_t sync, nvlist_t *err_details)
return (err); return (err);
} }
static int zcp_synctask_rename_snapshot(lua_State *, boolean_t, nvlist_t *);
static const zcp_synctask_info_t zcp_synctask_rename_snapshot_info = {
.name = "rename_snapshot",
.func = zcp_synctask_rename_snapshot,
.pargs = {
{.za_name = "filesystem | volume", .za_lua_type = LUA_TSTRING },
{.za_name = "oldsnapname", .za_lua_type = LUA_TSTRING },
{.za_name = "newsnapname", .za_lua_type = LUA_TSTRING },
{NULL, 0}
},
.space_check = ZFS_SPACE_CHECK_RESERVED,
.blocks_modified = 1
};
static int
zcp_synctask_rename_snapshot(lua_State *state, boolean_t sync,
nvlist_t *err_details)
{
(void) err_details;
int err;
const char *fsname = lua_tostring(state, 1);
const char *oldsnapname = lua_tostring(state, 2);
const char *newsnapname = lua_tostring(state, 3);
struct dsl_dataset_rename_snapshot_arg ddrsa = { 0 };
ddrsa.ddrsa_fsname = fsname;
ddrsa.ddrsa_oldsnapname = oldsnapname;
ddrsa.ddrsa_newsnapname = newsnapname;
ddrsa.ddrsa_recursive = B_FALSE;
err = zcp_sync_task(state, dsl_dataset_rename_snapshot_check,
dsl_dataset_rename_snapshot_sync, &ddrsa, sync, NULL);
return (err);
}
static int zcp_synctask_inherit_prop(lua_State *, boolean_t, static int zcp_synctask_inherit_prop(lua_State *, boolean_t,
nvlist_t *err_details); nvlist_t *err_details);
static const zcp_synctask_info_t zcp_synctask_inherit_prop_info = { static const zcp_synctask_info_t zcp_synctask_inherit_prop_info = {
@ -529,6 +565,7 @@ zcp_load_synctask_lib(lua_State *state, boolean_t sync)
&zcp_synctask_promote_info, &zcp_synctask_promote_info,
&zcp_synctask_rollback_info, &zcp_synctask_rollback_info,
&zcp_synctask_snapshot_info, &zcp_synctask_snapshot_info,
&zcp_synctask_rename_snapshot_info,
&zcp_synctask_inherit_prop_info, &zcp_synctask_inherit_prop_info,
&zcp_synctask_bookmark_info, &zcp_synctask_bookmark_info,
&zcp_synctask_set_prop_info, &zcp_synctask_set_prop_info,

View File

@ -129,6 +129,7 @@ nobase_dist_datadir_zfs_tests_tests_DATA += \
functional/channel_program/synctask_core/tst.snapshot_destroy.zcp \ functional/channel_program/synctask_core/tst.snapshot_destroy.zcp \
functional/channel_program/synctask_core/tst.snapshot_neg.zcp \ functional/channel_program/synctask_core/tst.snapshot_neg.zcp \
functional/channel_program/synctask_core/tst.snapshot_recursive.zcp \ functional/channel_program/synctask_core/tst.snapshot_recursive.zcp \
functional/channel_program/synctask_core/tst.snapshot_rename.zcp \
functional/channel_program/synctask_core/tst.snapshot_simple.zcp \ functional/channel_program/synctask_core/tst.snapshot_simple.zcp \
functional/checksum/default.cfg \ functional/checksum/default.cfg \
functional/clean_mirror/clean_mirror_common.kshlib \ functional/clean_mirror/clean_mirror_common.kshlib \
@ -536,6 +537,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/channel_program/synctask_core/tst.snapshot_destroy.ksh \ functional/channel_program/synctask_core/tst.snapshot_destroy.ksh \
functional/channel_program/synctask_core/tst.snapshot_neg.ksh \ functional/channel_program/synctask_core/tst.snapshot_neg.ksh \
functional/channel_program/synctask_core/tst.snapshot_recursive.ksh \ functional/channel_program/synctask_core/tst.snapshot_recursive.ksh \
functional/channel_program/synctask_core/tst.snapshot_rename.ksh \
functional/channel_program/synctask_core/tst.snapshot_simple.ksh \ functional/channel_program/synctask_core/tst.snapshot_simple.ksh \
functional/channel_program/synctask_core/tst.terminate_by_signal.ksh \ functional/channel_program/synctask_core/tst.terminate_by_signal.ksh \
functional/chattr/chattr_001_pos.ksh \ functional/chattr/chattr_001_pos.ksh \

View File

@ -0,0 +1,41 @@
#!/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) 2022 by Andriy Gapon. All rights reserved.
#
. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
#
# DESCRIPTION: Make sure basic snapshot functionality works in channel programs
#
verify_runnable "global"
fs=$TESTPOOL/$TESTFS/testchild
snapname1=testsnap1
snapname2=testsnap2
function cleanup
{
destroy_dataset $fs "-R"
}
log_onexit cleanup
log_must zfs create $fs
log_must_program_sync $TESTPOOL \
$ZCP_ROOT/synctask_core/tst.snapshot_rename.zcp $fs $snapname1 $snapname2
log_pass "Snapshot renaming works"

View File

@ -0,0 +1,27 @@
--
-- 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) 2022 by Andriy Gapon. All rights reserved.
--
-- This program should be invoked as "zfs program <pool> <prog> <fs> <snap>"
args = ...
argv = args["argv"]
assert(zfs.sync.snapshot(argv[1] .. "@" .. argv[2]) == 0)
assert(zfs.sync.rename_snapshot(argv[1], argv[2], argv[3]) == 0)
snaps = {}
for s in zfs.list.snapshots(argv[1]) do
table.insert(snaps, s)
end
assert(#snaps == 1)
assert(snaps[1] == (argv[1] .. "@" .. argv[3]))