changeset 19429:2377ea847e10

12245 Support inheriting properties in zfs channel programs Reviewed by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com> Approved by: Dan McDonald <danmcd@joyent.com>
author Jason King <jason.king@joyent.com>
date Thu, 23 Jan 2020 17:12:56 -0600
parents cefa3fedc6e3
children 6e69910f8ded
files usr/src/man/man1m/zfs-program.1m usr/src/pkg/manifests/system-test-zfstest.mf usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.inherit.ksh usr/src/uts/common/fs/zfs/dsl_prop.c usr/src/uts/common/fs/zfs/sys/dsl_prop.h usr/src/uts/common/fs/zfs/zcp_synctask.c
diffstat 6 files changed, 164 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/man/man1m/zfs-program.1m	Fri Jan 31 14:25:13 2020 -0600
+++ b/usr/src/man/man1m/zfs-program.1m	Thu Jan 23 17:12:56 2020 -0600
@@ -10,8 +10,9 @@
 .\"
 .\" Copyright (c) 2016, 2017 by Delphix. All rights reserved.
 .\" Copyright (c) 2018 Datto Inc.
+.\" Copyright 2020 Joyent, Inc.
 .\"
-.Dd January 21, 2016
+.Dd January 15, 2020
 .Dt ZFS-PROGRAM 1M
 .Os
 .Sh NAME
@@ -366,6 +367,27 @@
 If set to true, and the snapshot has holds or clones, allows the snapshot to be
 marked for deferred deletion rather than failing.
 .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)
 Promote the given clone to a filesystem.
 Returns 0 on successful promotion, or a nonzero error code otherwise.
--- a/usr/src/pkg/manifests/system-test-zfstest.mf	Fri Jan 31 14:25:13 2020 -0600
+++ b/usr/src/pkg/manifests/system-test-zfstest.mf	Thu Jan 23 17:12:56 2020 -0600
@@ -13,7 +13,7 @@
 # Copyright (c) 2012, 2017 by Delphix. All rights reserved.
 # Copyright 2015, 2016 Nexenta Systems, Inc.  All rights reserved.
 # Copyright 2016, OmniTI Computer Consulting, Inc. All rights reserved.
-# Copyright 2019 Joyent, Inc.
+# Copyright 2020 Joyent, Inc.
 # Copyright (c) 2018 Datto Inc.
 #
 
@@ -600,6 +600,9 @@
     path=opt/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_written \
     mode=0555
 file \
+    path=opt/zfs-tests/tests/functional/channel_program/synctask_core/tst.inherit \
+    mode=0555
+file \
     path=opt/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_children \
     mode=0555
 file \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.inherit.ksh	Thu Jan 23 17:12:56 2020 -0600
@@ -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."
--- a/usr/src/uts/common/fs/zfs/dsl_prop.c	Fri Jan 31 14:25:13 2020 -0600
+++ b/usr/src/uts/common/fs/zfs/dsl_prop.c	Thu Jan 23 17:12:56 2020 -0600
@@ -22,7 +22,7 @@
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2012, 2015 by Delphix. All rights reserved.
  * Copyright (c) 2013 Martin Matuska. All rights reserved.
- * Copyright 2015, Joyent, Inc.
+ * Copyright 2019 Joyent, Inc.
  */
 
 #include <sys/zfs_context.h>
@@ -802,13 +802,7 @@
 	return (error);
 }
 
-typedef struct dsl_props_set_arg {
-	const char *dpsa_dsname;
-	zprop_source_t dpsa_source;
-	nvlist_t *dpsa_props;
-} dsl_props_set_arg_t;
-
-static int
+int
 dsl_props_set_check(void *arg, dmu_tx_t *tx)
 {
 	dsl_props_set_arg_t *dpsa = arg;
@@ -886,7 +880,7 @@
 	}
 }
 
-static void
+void
 dsl_props_set_sync(void *arg, dmu_tx_t *tx)
 {
 	dsl_props_set_arg_t *dpsa = arg;
--- a/usr/src/uts/common/fs/zfs/sys/dsl_prop.h	Fri Jan 31 14:25:13 2020 -0600
+++ b/usr/src/uts/common/fs/zfs/sys/dsl_prop.h	Thu Jan 23 17:12:56 2020 -0600
@@ -21,6 +21,7 @@
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright 2019 Joyent, Inc.
  */
 
 #ifndef	_SYS_DSL_PROP_H
@@ -61,6 +62,12 @@
 	zprop_source_t pa_source;
 } 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_fini(dsl_dir_t *dd);
 int dsl_prop_register(struct dsl_dataset *ds, const char *propname,
@@ -83,6 +90,8 @@
     int intsz, int numints, void *buf, char *setpoint,
     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,
     nvlist_t *props, dmu_tx_t *tx);
 void dsl_prop_set_sync_impl(struct dsl_dataset *ds, const char *propname,
--- a/usr/src/uts/common/fs/zfs/zcp_synctask.c	Fri Jan 31 14:25:13 2020 -0600
+++ b/usr/src/uts/common/fs/zfs/zcp_synctask.c	Thu Jan 23 17:12:56 2020 -0600
@@ -15,6 +15,7 @@
 
 /*
  * Copyright (c) 2016, 2017 by Delphix. All rights reserved.
+ * Copyright 2020 Joyent, Inc.
  */
 
 #include "lua.h"
@@ -35,6 +36,12 @@
 
 #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 struct zcp_synctask_info {
 	const char *name;
@@ -275,6 +282,84 @@
 	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
 zcp_synctask_wrapper(lua_State *state)
 {
@@ -342,6 +427,7 @@
 		&zcp_synctask_promote_info,
 		&zcp_synctask_rollback_info,
 		&zcp_synctask_snapshot_info,
+		&zcp_synctask_inherit_prop_info,
 		NULL
 	};