mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-28 11:25:21 +01:00
zcp: support bookmarks in zfs.sync.destroy
Teach the channel-program synctask destroy path to recognize bookmark targets and route them through the existing bookmark-destroy implementation. This enables zfs.sync.destroy() to remove bookmarks from Lua channel programs, matching the behavior already available for datasets and snapshots. A functional regression test was added to cover bookmark destruction from a channel program. Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Stephen Warren <[email protected]> Closes #18992
This commit is contained in:
1 parent
f7b10b66be
commit
fd639b075a
7 files changed
+83
-12
No files matched your search
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <sys/zfs_context.h>
|
||||
#include <sys/zfs_refcount.h>
|
||||
#include <sys/dmu_tx.h>
|
||||
#include <sys/dsl_dataset.h>
|
||||
#include <sys/dsl_pool.h>
|
||||
|
||||
@@ -115,6 +116,12 @@ typedef struct dsl_bookmark_create_redacted_arg {
|
||||
const void *dbcra_tag;
|
||||
} dsl_bookmark_create_redacted_arg_t;
|
||||
|
||||
typedef struct dsl_bookmark_destroy_arg {
|
||||
nvlist_t *dbda_bmarks;
|
||||
nvlist_t *dbda_success;
|
||||
nvlist_t *dbda_errors;
|
||||
} dsl_bookmark_destroy_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);
|
||||
@@ -125,6 +132,8 @@ int dsl_get_bookmarks(const char *, nvlist_t *, nvlist_t *);
|
||||
int dsl_get_bookmarks_impl(dsl_dataset_t *, nvlist_t *, nvlist_t *);
|
||||
int dsl_get_bookmark_props(const char *, const char *, nvlist_t *);
|
||||
int dsl_bookmark_destroy(nvlist_t *, nvlist_t *);
|
||||
int dsl_bookmark_destroy_check(void *, dmu_tx_t *);
|
||||
void dsl_bookmark_destroy_sync(void *, dmu_tx_t *);
|
||||
int dsl_bookmark_lookup(struct dsl_pool *, const char *,
|
||||
struct dsl_dataset *, zfs_bookmark_phys_t *);
|
||||
int dsl_bookmark_lookup_impl(dsl_dataset_t *, const char *,
|
||||
|
||||
@@ -969,12 +969,6 @@ out:
|
||||
return (err);
|
||||
}
|
||||
|
||||
typedef struct dsl_bookmark_destroy_arg {
|
||||
nvlist_t *dbda_bmarks;
|
||||
nvlist_t *dbda_success;
|
||||
nvlist_t *dbda_errors;
|
||||
} dsl_bookmark_destroy_arg_t;
|
||||
|
||||
static void
|
||||
dsl_bookmark_destroy_sync_impl(dsl_dataset_t *ds, const char *name,
|
||||
dmu_tx_t *tx)
|
||||
@@ -1082,7 +1076,7 @@ dsl_bookmark_destroy_sync_impl(dsl_dataset_t *ds, const char *name,
|
||||
VERIFY0(zap_remove_norm(mos, bmark_zapobj, name, mt, tx));
|
||||
}
|
||||
|
||||
static int
|
||||
int
|
||||
dsl_bookmark_destroy_check(void *arg, dmu_tx_t *tx)
|
||||
{
|
||||
dsl_bookmark_destroy_arg_t *dbda = arg;
|
||||
@@ -1147,7 +1141,7 @@ dsl_bookmark_destroy_check(void *arg, dmu_tx_t *tx)
|
||||
return (rv);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
dsl_bookmark_destroy_sync(void *arg, dmu_tx_t *tx)
|
||||
{
|
||||
dsl_bookmark_destroy_arg_t *dbda = arg;
|
||||
|
||||
@@ -158,7 +158,8 @@ static const zcp_synctask_info_t zcp_synctask_destroy_info = {
|
||||
.name = "destroy",
|
||||
.func = zcp_synctask_destroy,
|
||||
.pargs = {
|
||||
{.za_name = "filesystem | snapshot", .za_lua_type = LUA_TSTRING },
|
||||
{.za_name = "filesystem | snapshot | bookmark",
|
||||
.za_lua_type = LUA_TSTRING },
|
||||
{NULL, 0}
|
||||
},
|
||||
.kwargs = {
|
||||
@@ -172,11 +173,11 @@ static const zcp_synctask_info_t zcp_synctask_destroy_info = {
|
||||
static int
|
||||
zcp_synctask_destroy(lua_State *state, boolean_t sync, nvlist_t *err_details)
|
||||
{
|
||||
(void) err_details;
|
||||
int err;
|
||||
const char *dsname = lua_tostring(state, 1);
|
||||
|
||||
boolean_t issnap = (strchr(dsname, '@') != NULL);
|
||||
boolean_t isbookmark = (strchr(dsname, '#') != NULL);
|
||||
|
||||
if (!issnap && !lua_isnil(state, 2)) {
|
||||
return (luaL_error(state,
|
||||
@@ -195,6 +196,25 @@ zcp_synctask_destroy(lua_State *state, boolean_t sync, nvlist_t *err_details)
|
||||
|
||||
err = zcp_sync_task(state, dsl_destroy_snapshot_check,
|
||||
dsl_destroy_snapshot_sync, &ddsa, sync, dsname);
|
||||
} else if (isbookmark) {
|
||||
dsl_bookmark_destroy_arg_t dbda = { 0 };
|
||||
dbda.dbda_bmarks = fnvlist_alloc();
|
||||
dbda.dbda_success = fnvlist_alloc();
|
||||
dbda.dbda_errors = err_details;
|
||||
fnvlist_add_boolean(dbda.dbda_bmarks, dsname);
|
||||
|
||||
zcp_cleanup_handler_t *zch = zcp_register_cleanup(state,
|
||||
zcp_synctask_cleanup, dbda.dbda_bmarks);
|
||||
zcp_cleanup_handler_t *zch2 = zcp_register_cleanup(state,
|
||||
zcp_synctask_cleanup, dbda.dbda_success);
|
||||
|
||||
err = zcp_sync_task(state, dsl_bookmark_destroy_check,
|
||||
dsl_bookmark_destroy_sync, &dbda, sync, dsname);
|
||||
|
||||
zcp_deregister_cleanup(state, zch2);
|
||||
zcp_deregister_cleanup(state, zch);
|
||||
fnvlist_free(dbda.dbda_success);
|
||||
fnvlist_free(dbda.dbda_bmarks);
|
||||
} else {
|
||||
dsl_destroy_head_arg_t ddha = { 0 };
|
||||
ddha.ddha_name = dsname;
|
||||
|
||||
@@ -133,7 +133,8 @@ tests = ['tst.args_to_lua', 'tst.divide_by_zero', 'tst.exists', 'tst.encryption'
|
||||
tags = ['functional', 'channel_program', 'lua_core']
|
||||
|
||||
[tests/functional/channel_program/synctask_core]
|
||||
tests = ['tst.destroy_fs', 'tst.destroy_snap', 'tst.get_count_and_limit',
|
||||
tests = ['tst.destroy_fs', 'tst.destroy_snap',
|
||||
'tst.destroy_bookmark', 'tst.get_count_and_limit',
|
||||
'tst.get_index_props', 'tst.get_mountpoint', 'tst.get_neg',
|
||||
'tst.get_number_props', 'tst.get_string_props', 'tst.get_type',
|
||||
'tst.get_userquota', 'tst.get_written', 'tst.inherit', 'tst.list_bookmarks',
|
||||
|
||||
@@ -74,7 +74,8 @@ tests = ['tst.args_to_lua', 'tst.divide_by_zero', 'tst.exists', 'tst.encryption'
|
||||
tags = ['functional', 'channel_program', 'lua_core']
|
||||
|
||||
[tests/functional/channel_program/synctask_core]
|
||||
tests = ['tst.destroy_fs', 'tst.destroy_snap', 'tst.get_count_and_limit',
|
||||
tests = ['tst.destroy_fs', 'tst.destroy_snap',
|
||||
'tst.destroy_bookmark', 'tst.get_count_and_limit',
|
||||
'tst.get_index_props', 'tst.get_mountpoint', 'tst.get_neg',
|
||||
'tst.get_number_props', 'tst.get_string_props', 'tst.get_type',
|
||||
'tst.get_userquota', 'tst.get_written', 'tst.inherit', 'tst.list_bookmarks',
|
||||
|
||||
@@ -642,6 +642,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
|
||||
functional/channel_program/synctask_core/tst.bookmark.create.ksh \
|
||||
functional/channel_program/synctask_core/tst.clone.ksh \
|
||||
functional/channel_program/synctask_core/tst.destroy_fs.ksh \
|
||||
functional/channel_program/synctask_core/tst.destroy_bookmark.ksh \
|
||||
functional/channel_program/synctask_core/tst.destroy_snap.ksh \
|
||||
functional/channel_program/synctask_core/tst.get_count_and_limit.ksh \
|
||||
functional/channel_program/synctask_core/tst.get_index_props.ksh \
|
||||
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
#!/bin/ksh -p
|
||||
# SPDX-License-Identifier: CDDL-1.0
|
||||
#
|
||||
# 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
|
||||
# https://opensource.org/license/CDDL-1.0.
|
||||
#
|
||||
|
||||
. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
fs=$TESTPOOL/$TESTFS/testchild
|
||||
snapname=testsnap
|
||||
bookname=testbookmark
|
||||
bookmark=$fs#$bookname
|
||||
snap=$fs@$snapname
|
||||
|
||||
function cleanup
|
||||
{
|
||||
destroy_dataset $fs "-R"
|
||||
}
|
||||
|
||||
log_onexit cleanup
|
||||
|
||||
log_must zfs create $fs
|
||||
log_must zfs snapshot $snap
|
||||
log_must zfs bookmark $snap $bookmark
|
||||
|
||||
log_must_program_sync $TESTPOOL - $bookmark <<-EOF
|
||||
arg = ...
|
||||
bookmark = arg["argv"][1]
|
||||
err = zfs.sync.destroy(bookmark)
|
||||
msg = "destroying " .. bookmark .. " err=" .. err
|
||||
return msg
|
||||
EOF
|
||||
|
||||
log_mustnot zfs list -H -o name -t bookmark $bookmark
|
||||
|
||||
log_pass "Destroying bookmark with channel program works."
|
||||
Reference in new issue
Block a user