Support inheriting properties in channel programs
This adds support in channel programs to inherit properties analogous to `zfs inherit` by adding `zfs.sync.inherit` and `zfs.check.inherit` functions to the ZFS LUA API. Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Jason King <jason.king@joyent.com> Closes #9738
This commit is contained in:
parent
79add96766
commit
e2ef1cbf04
|
@ -21,6 +21,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||||
|
* Copyright 2019 Joyent, Inc.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _SYS_DSL_PROP_H
|
#ifndef _SYS_DSL_PROP_H
|
||||||
|
@ -61,6 +62,12 @@ typedef struct dsl_props_arg {
|
||||||
zprop_source_t pa_source;
|
zprop_source_t pa_source;
|
||||||
} dsl_props_arg_t;
|
} dsl_props_arg_t;
|
||||||
|
|
||||||
|
typedef struct dsl_props_set_arg {
|
||||||
|
const char *dpsa_dsname;
|
||||||
|
zprop_source_t dpsa_source;
|
||||||
|
nvlist_t *dpsa_props;
|
||||||
|
} dsl_props_set_arg_t;
|
||||||
|
|
||||||
void dsl_prop_init(dsl_dir_t *dd);
|
void dsl_prop_init(dsl_dir_t *dd);
|
||||||
void dsl_prop_fini(dsl_dir_t *dd);
|
void dsl_prop_fini(dsl_dir_t *dd);
|
||||||
int dsl_prop_register(struct dsl_dataset *ds, const char *propname,
|
int dsl_prop_register(struct dsl_dataset *ds, const char *propname,
|
||||||
|
@ -85,6 +92,8 @@ int dsl_prop_get_dd(struct dsl_dir *dd, const char *propname,
|
||||||
int intsz, int numints, void *buf, char *setpoint,
|
int intsz, int numints, void *buf, char *setpoint,
|
||||||
boolean_t snapshot);
|
boolean_t snapshot);
|
||||||
|
|
||||||
|
int dsl_props_set_check(void *arg, dmu_tx_t *tx);
|
||||||
|
void dsl_props_set_sync(void *arg, dmu_tx_t *tx);
|
||||||
void dsl_props_set_sync_impl(struct dsl_dataset *ds, zprop_source_t source,
|
void dsl_props_set_sync_impl(struct dsl_dataset *ds, zprop_source_t source,
|
||||||
nvlist_t *props, dmu_tx_t *tx);
|
nvlist_t *props, dmu_tx_t *tx);
|
||||||
void dsl_prop_set_sync_impl(struct dsl_dataset *ds, const char *propname,
|
void dsl_prop_set_sync_impl(struct dsl_dataset *ds, const char *propname,
|
||||||
|
|
|
@ -9,8 +9,9 @@
|
||||||
.\"
|
.\"
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 2016, 2019 by Delphix. All Rights Reserved.
|
.\" Copyright (c) 2016, 2019 by Delphix. All Rights Reserved.
|
||||||
|
.\" Copyright 2020 Joyent, Inc.
|
||||||
.\"
|
.\"
|
||||||
.Dd February 26, 2019
|
.Dd January 15, 2020
|
||||||
.Dt ZFS-PROGRAM 8
|
.Dt ZFS-PROGRAM 8
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
|
@ -364,6 +365,27 @@ Valid only for destroying snapshots.
|
||||||
If set to true, and the snapshot has holds or clones, allows the snapshot to be
|
If set to true, and the snapshot has holds or clones, allows the snapshot to be
|
||||||
marked for deferred deletion rather than failing.
|
marked for deferred deletion rather than failing.
|
||||||
.Ed
|
.Ed
|
||||||
|
.It Em zfs.sync.inherit(dataset, property)
|
||||||
|
Clears the specified property in the given dataset, causing it to be inherited
|
||||||
|
from an ancestor, or restored to the default if no ancestor property is set.
|
||||||
|
The
|
||||||
|
.Ql zfs inherit -S
|
||||||
|
option has not been implemented.
|
||||||
|
Returns 0 on success, or a nonzero error code if the property could not be
|
||||||
|
cleared.
|
||||||
|
.Pp
|
||||||
|
dataset (string)
|
||||||
|
.Bd -ragged -compact -offset "xxxx"
|
||||||
|
Filesystem or snapshot containing the property to clear.
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
property (string)
|
||||||
|
.Bd -ragged -compact -offset "xxxx"
|
||||||
|
The property to clear.
|
||||||
|
Allowed properties are the same as those for the
|
||||||
|
.Nm zfs Cm inherit
|
||||||
|
command.
|
||||||
|
.Ed
|
||||||
.It Em zfs.sync.promote(dataset)
|
.It Em zfs.sync.promote(dataset)
|
||||||
Promote the given clone to a filesystem.
|
Promote the given clone to a filesystem.
|
||||||
Returns 0 on successful promotion, or a nonzero error code otherwise.
|
Returns 0 on successful promotion, or a nonzero error code otherwise.
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012, 2015 by Delphix. All rights reserved.
|
* Copyright (c) 2012, 2015 by Delphix. All rights reserved.
|
||||||
* Copyright (c) 2013 Martin Matuska. All rights reserved.
|
* Copyright (c) 2013 Martin Matuska. All rights reserved.
|
||||||
* Copyright 2015, Joyent, Inc.
|
* Copyright 2019 Joyent, Inc.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/zfs_context.h>
|
#include <sys/zfs_context.h>
|
||||||
|
@ -856,13 +856,7 @@ dsl_prop_inherit(const char *dsname, const char *propname,
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct dsl_props_set_arg {
|
int
|
||||||
const char *dpsa_dsname;
|
|
||||||
zprop_source_t dpsa_source;
|
|
||||||
nvlist_t *dpsa_props;
|
|
||||||
} dsl_props_set_arg_t;
|
|
||||||
|
|
||||||
static int
|
|
||||||
dsl_props_set_check(void *arg, dmu_tx_t *tx)
|
dsl_props_set_check(void *arg, dmu_tx_t *tx)
|
||||||
{
|
{
|
||||||
dsl_props_set_arg_t *dpsa = arg;
|
dsl_props_set_arg_t *dpsa = arg;
|
||||||
|
@ -940,7 +934,7 @@ dsl_props_set_sync_impl(dsl_dataset_t *ds, zprop_source_t source,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
dsl_props_set_sync(void *arg, dmu_tx_t *tx)
|
dsl_props_set_sync(void *arg, dmu_tx_t *tx)
|
||||||
{
|
{
|
||||||
dsl_props_set_arg_t *dpsa = arg;
|
dsl_props_set_arg_t *dpsa = arg;
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, 2017 by Delphix. All rights reserved.
|
* Copyright (c) 2016, 2017 by Delphix. All rights reserved.
|
||||||
|
* Copyright 2020 Joyent, Inc.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/lua/lua.h>
|
#include <sys/lua/lua.h>
|
||||||
|
@ -35,6 +36,12 @@
|
||||||
|
|
||||||
#define DST_AVG_BLKSHIFT 14
|
#define DST_AVG_BLKSHIFT 14
|
||||||
|
|
||||||
|
typedef struct zcp_inherit_prop_arg {
|
||||||
|
lua_State *zipa_state;
|
||||||
|
const char *zipa_prop;
|
||||||
|
dsl_props_set_arg_t zipa_dpsa;
|
||||||
|
} zcp_inherit_prop_arg_t;
|
||||||
|
|
||||||
typedef int (zcp_synctask_func_t)(lua_State *, boolean_t, nvlist_t *);
|
typedef int (zcp_synctask_func_t)(lua_State *, boolean_t, nvlist_t *);
|
||||||
typedef struct zcp_synctask_info {
|
typedef struct zcp_synctask_info {
|
||||||
const char *name;
|
const char *name;
|
||||||
|
@ -275,6 +282,84 @@ zcp_synctask_snapshot(lua_State *state, boolean_t sync, nvlist_t *err_details)
|
||||||
return (err);
|
return (err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int zcp_synctask_inherit_prop(lua_State *, boolean_t,
|
||||||
|
nvlist_t *err_details);
|
||||||
|
static zcp_synctask_info_t zcp_synctask_inherit_prop_info = {
|
||||||
|
.name = "inherit",
|
||||||
|
.func = zcp_synctask_inherit_prop,
|
||||||
|
.space_check = ZFS_SPACE_CHECK_RESERVED,
|
||||||
|
.blocks_modified = 2, /* 2 * numprops */
|
||||||
|
.pargs = {
|
||||||
|
{ .za_name = "dataset", .za_lua_type = LUA_TSTRING },
|
||||||
|
{ .za_name = "property", .za_lua_type = LUA_TSTRING },
|
||||||
|
{ NULL, 0 }
|
||||||
|
},
|
||||||
|
.kwargs = {
|
||||||
|
{ NULL, 0 }
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
zcp_synctask_inherit_prop_check(void *arg, dmu_tx_t *tx)
|
||||||
|
{
|
||||||
|
zcp_inherit_prop_arg_t *args = arg;
|
||||||
|
zfs_prop_t prop = zfs_name_to_prop(args->zipa_prop);
|
||||||
|
|
||||||
|
if (prop == ZPROP_INVAL) {
|
||||||
|
if (zfs_prop_user(args->zipa_prop))
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
return (EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zfs_prop_readonly(prop))
|
||||||
|
return (EINVAL);
|
||||||
|
|
||||||
|
if (!zfs_prop_inheritable(prop))
|
||||||
|
return (EINVAL);
|
||||||
|
|
||||||
|
return (dsl_props_set_check(&args->zipa_dpsa, tx));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
zcp_synctask_inherit_prop_sync(void *arg, dmu_tx_t *tx)
|
||||||
|
{
|
||||||
|
zcp_inherit_prop_arg_t *args = arg;
|
||||||
|
dsl_props_set_arg_t *dpsa = &args->zipa_dpsa;
|
||||||
|
|
||||||
|
dsl_props_set_sync(dpsa, tx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
zcp_synctask_inherit_prop(lua_State *state, boolean_t sync,
|
||||||
|
nvlist_t *err_details)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
zcp_inherit_prop_arg_t zipa = { 0 };
|
||||||
|
dsl_props_set_arg_t *dpsa = &zipa.zipa_dpsa;
|
||||||
|
|
||||||
|
const char *dsname = lua_tostring(state, 1);
|
||||||
|
const char *prop = lua_tostring(state, 2);
|
||||||
|
|
||||||
|
zipa.zipa_state = state;
|
||||||
|
zipa.zipa_prop = prop;
|
||||||
|
dpsa->dpsa_dsname = dsname;
|
||||||
|
dpsa->dpsa_source = ZPROP_SRC_INHERITED;
|
||||||
|
dpsa->dpsa_props = fnvlist_alloc();
|
||||||
|
fnvlist_add_boolean(dpsa->dpsa_props, prop);
|
||||||
|
|
||||||
|
zcp_cleanup_handler_t *zch = zcp_register_cleanup(state,
|
||||||
|
(zcp_cleanup_t *)&fnvlist_free, dpsa->dpsa_props);
|
||||||
|
|
||||||
|
err = zcp_sync_task(state, zcp_synctask_inherit_prop_check,
|
||||||
|
zcp_synctask_inherit_prop_sync, &zipa, sync, dsname);
|
||||||
|
|
||||||
|
zcp_deregister_cleanup(state, zch);
|
||||||
|
fnvlist_free(dpsa->dpsa_props);
|
||||||
|
|
||||||
|
return (err);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
zcp_synctask_wrapper(lua_State *state)
|
zcp_synctask_wrapper(lua_State *state)
|
||||||
{
|
{
|
||||||
|
@ -343,6 +428,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_inherit_prop_info,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -80,7 +80,7 @@ tags = ['functional', 'channel_program', 'lua_core']
|
||||||
tests = ['tst.destroy_fs', 'tst.destroy_snap', 'tst.get_count_and_limit',
|
tests = ['tst.destroy_fs', 'tst.destroy_snap', 'tst.get_count_and_limit',
|
||||||
'tst.get_index_props', 'tst.get_mountpoint', 'tst.get_neg',
|
'tst.get_index_props', 'tst.get_mountpoint', 'tst.get_neg',
|
||||||
'tst.get_number_props', 'tst.get_string_props', 'tst.get_type',
|
'tst.get_number_props', 'tst.get_string_props', 'tst.get_type',
|
||||||
'tst.get_userquota', 'tst.get_written', 'tst.list_bookmarks',
|
'tst.get_userquota', 'tst.get_written', 'tst.inherit', 'tst.list_bookmarks',
|
||||||
'tst.list_children', 'tst.list_clones', 'tst.list_holds',
|
'tst.list_children', 'tst.list_clones', 'tst.list_holds',
|
||||||
'tst.list_snapshots', 'tst.list_system_props',
|
'tst.list_snapshots', 'tst.list_system_props',
|
||||||
'tst.list_user_props', 'tst.parse_args_neg','tst.promote_conflict',
|
'tst.list_user_props', 'tst.parse_args_neg','tst.promote_conflict',
|
||||||
|
|
|
@ -13,6 +13,7 @@ dist_pkgdata_SCRIPTS = \
|
||||||
tst.get_type.ksh \
|
tst.get_type.ksh \
|
||||||
tst.get_userquota.ksh \
|
tst.get_userquota.ksh \
|
||||||
tst.get_written.ksh \
|
tst.get_written.ksh \
|
||||||
|
tst.inherit.ksh \
|
||||||
tst.list_bookmarks.ksh \
|
tst.list_bookmarks.ksh \
|
||||||
tst.list_children.ksh \
|
tst.list_children.ksh \
|
||||||
tst.list_clones.ksh \
|
tst.list_clones.ksh \
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
#!/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 2020 Joyent, Inc.
|
||||||
|
#
|
||||||
|
|
||||||
|
. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
|
||||||
|
|
||||||
|
verify_runnable "global"
|
||||||
|
|
||||||
|
fs=$TESTPOOL/$TESTFS
|
||||||
|
testprop="com.joyent:testprop"
|
||||||
|
testval="testval"
|
||||||
|
|
||||||
|
log_must dataset_setprop $fs $testprop $testval
|
||||||
|
log_must_program_sync $TESTPOOL - $fs $testprop <<-EOF
|
||||||
|
arg = ...
|
||||||
|
fs = arg["argv"][1]
|
||||||
|
prop = arg["argv"][2]
|
||||||
|
err = zfs.sync.inherit(fs, prop)
|
||||||
|
msg = "resetting " .. prop .. " on " .. fs .. " err=" .. err
|
||||||
|
return msg
|
||||||
|
EOF
|
||||||
|
|
||||||
|
|
||||||
|
prop=$(get_prop $testprop $fs)
|
||||||
|
[[ "$prop" == "-" ]] || log_fail "Property still set after inheriting"
|
||||||
|
|
||||||
|
log_pass "Inherit/clear property with channel program works."
|
Loading…
Reference in New Issue