Blame SOURCES/0014-daxctl-fail-reconfigure-device-based-on-kernel-onlin.patch

2eb93d
From 99415dfc7c5167c49a5732f577836f68872645b2 Mon Sep 17 00:00:00 2001
2eb93d
From: Vishal Verma <vishal.l.verma@intel.com>
2eb93d
Date: Wed, 24 Mar 2021 12:09:29 -0700
2eb93d
Subject: [PATCH 014/217] daxctl: fail reconfigure-device based on kernel
2eb93d
 onlining policy
2eb93d
2eb93d
If the kernel has a policy set to auto-online any new memory blocks, we
2eb93d
know that an attempt to reconfigure a device either in ZONE_MOVABLE, or
2eb93d
with the --no-online is going to fail. While we detect this race after
2eb93d
the fact, and print a warning, that is often insufficient as the user
2eb93d
may be forced to reboot to get out of the situation, resulting in an
2eb93d
unpleasant experience.
2eb93d
2eb93d
Detect whether the kernel policy is set to auto-online. If so, fail
2eb93d
device reconfigure operations that we know can't be satisfied. Allow
2eb93d
for overriding this safety check via the -f (--force) option. Update the
2eb93d
man page to talk about this, and the unit test to test for an expected
2eb93d
failure by enabling auto-onlining.
2eb93d
2eb93d
Cc: Dave Hansen <dave.hansen@intel.com>
2eb93d
Reported-by: Chunye Xu <chunye.xu@intel.com>
2eb93d
Reported-by: Dan Williams <dan.j.williams@intel.com>
2eb93d
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
2eb93d
---
2eb93d
 .../daxctl/daxctl-reconfigure-device.txt      | 12 ++++++-
2eb93d
 daxctl/device.c                               | 10 ++++++
2eb93d
 daxctl/lib/libdaxctl-private.h                |  1 +
2eb93d
 daxctl/lib/libdaxctl.c                        | 21 +++++++++++
2eb93d
 daxctl/lib/libdaxctl.sym                      |  5 +++
2eb93d
 daxctl/libdaxctl.h                            |  1 +
2eb93d
 test/daxctl-devices.sh                        | 36 +++++++++++++++++++
2eb93d
 7 files changed, 85 insertions(+), 1 deletion(-)
2eb93d
2eb93d
diff --git a/Documentation/daxctl/daxctl-reconfigure-device.txt b/Documentation/daxctl/daxctl-reconfigure-device.txt
2eb93d
index ad33eda..f112b3c 100644
2eb93d
--- a/Documentation/daxctl/daxctl-reconfigure-device.txt
2eb93d
+++ b/Documentation/daxctl/daxctl-reconfigure-device.txt
2eb93d
@@ -119,6 +119,10 @@ recommended to use the --no-online option described below. This will abridge
2eb93d
 the device reconfiguration operation to just hotplugging the memory, and
2eb93d
 refrain from then onlining it.
2eb93d
 
2eb93d
+In case daxctl detects that there is a kernel policy to auto-online blocks
2eb93d
+(via /sys/devices/system/memory/auto_online_blocks), then reconfiguring to
2eb93d
+system-ram will result in a failure. This can be overridden with '--force'.
2eb93d
+
2eb93d
 OPTIONS
2eb93d
 -------
2eb93d
 include::region-option.txt[]
2eb93d
@@ -162,12 +166,18 @@ include::movable-options.txt[]
2eb93d
 
2eb93d
 -f::
2eb93d
 --force::
2eb93d
-	When converting from "system-ram" mode to "devdax", it is expected
2eb93d
+	- When converting from "system-ram" mode to "devdax", it is expected
2eb93d
 	that all the memory sections are first made offline. By default,
2eb93d
 	daxctl won't touch online memory. However with this option, attempt
2eb93d
 	to offline the memory on the NUMA node associated with the dax device
2eb93d
 	before converting it back to "devdax" mode.
2eb93d
 
2eb93d
+	- Additionally, if a kernel policy to auto-online blocks is detected,
2eb93d
+	reconfiguration to system-ram fails. With this option, the failure can
2eb93d
+	be overridden to allow reconfiguration regardless of kernel policy.
2eb93d
+	Doing this may result in a successful reconfiguration, but it may
2eb93d
+	not be possible to subsequently offline the memory without a reboot.
2eb93d
+
2eb93d
 
2eb93d
 include::human-option.txt[]
2eb93d
 
2eb93d
diff --git a/daxctl/device.c b/daxctl/device.c
2eb93d
index 0721a57..a427b7d 100644
2eb93d
--- a/daxctl/device.c
2eb93d
+++ b/daxctl/device.c
2eb93d
@@ -541,8 +541,18 @@ static int disable_devdax_device(struct daxctl_dev *dev)
2eb93d
 
2eb93d
 static int reconfig_mode_system_ram(struct daxctl_dev *dev)
2eb93d
 {
2eb93d
+	const char *devname = daxctl_dev_get_devname(dev);
2eb93d
 	int rc, skip_enable = 0;
2eb93d
 
2eb93d
+	if (param.no_online || !param.no_movable) {
2eb93d
+		if (!param.force && daxctl_dev_will_auto_online_memory(dev)) {
2eb93d
+			fprintf(stderr,
2eb93d
+				"%s: error: kernel policy will auto-online memory, aborting\n",
2eb93d
+				devname);
2eb93d
+			return -EBUSY;
2eb93d
+		}
2eb93d
+	}
2eb93d
+
2eb93d
 	if (daxctl_dev_is_enabled(dev)) {
2eb93d
 		rc = disable_devdax_device(dev);
2eb93d
 		if (rc < 0)
2eb93d
diff --git a/daxctl/lib/libdaxctl-private.h b/daxctl/lib/libdaxctl-private.h
2eb93d
index af257fd..ae45311 100644
2eb93d
--- a/daxctl/lib/libdaxctl-private.h
2eb93d
+++ b/daxctl/lib/libdaxctl-private.h
2eb93d
@@ -111,6 +111,7 @@ struct daxctl_memory {
2eb93d
 	char *node_path;
2eb93d
 	unsigned long block_size;
2eb93d
 	enum memory_zones zone;
2eb93d
+	bool auto_online;
2eb93d
 };
2eb93d
 
2eb93d
 
2eb93d
diff --git a/daxctl/lib/libdaxctl.c b/daxctl/lib/libdaxctl.c
2eb93d
index 479e8f6..879f7e6 100644
2eb93d
--- a/daxctl/lib/libdaxctl.c
2eb93d
+++ b/daxctl/lib/libdaxctl.c
2eb93d
@@ -1644,3 +1644,24 @@ DAXCTL_EXPORT int daxctl_memory_is_movable(struct daxctl_memory *mem)
2eb93d
 		return rc;
2eb93d
 	return (mem->zone == MEM_ZONE_MOVABLE) ? 1 : 0;
2eb93d
 }
2eb93d
+
2eb93d
+DAXCTL_EXPORT int daxctl_dev_will_auto_online_memory(struct daxctl_dev *dev)
2eb93d
+{
2eb93d
+	const char *auto_path = "/sys/devices/system/memory/auto_online_blocks";
2eb93d
+	const char *devname = daxctl_dev_get_devname(dev);
2eb93d
+	struct daxctl_ctx *ctx = daxctl_dev_get_ctx(dev);
2eb93d
+	char buf[SYSFS_ATTR_SIZE];
2eb93d
+
2eb93d
+	/*
2eb93d
+	 * If we can't read the policy for some reason, don't fail yet. Assume
2eb93d
+	 * the auto-onlining policy is absent, and carry on. If onlining blocks
2eb93d
+	 * does result in the memory being in an inconsistent state, we have a
2eb93d
+	 * check and warning for it after the fact
2eb93d
+	 */
2eb93d
+	if (sysfs_read_attr(ctx, auto_path, buf) != 0)
2eb93d
+		err(ctx, "%s: Unable to determine auto-online policy: %s\n",
2eb93d
+				devname, strerror(errno));
2eb93d
+
2eb93d
+	/* match both "online" and "online_movable" */
2eb93d
+	return !strncmp(buf, "online", 6);
2eb93d
+}
2eb93d
diff --git a/daxctl/lib/libdaxctl.sym b/daxctl/lib/libdaxctl.sym
2eb93d
index a4e1684..892e393 100644
2eb93d
--- a/daxctl/lib/libdaxctl.sym
2eb93d
+++ b/daxctl/lib/libdaxctl.sym
2eb93d
@@ -91,3 +91,8 @@ global:
2eb93d
 	daxctl_mapping_get_size;
2eb93d
 	daxctl_dev_set_mapping;
2eb93d
 } LIBDAXCTL_7;
2eb93d
+
2eb93d
+LIBDAXCTL_9 {
2eb93d
+global:
2eb93d
+	daxctl_dev_will_auto_online_memory;
2eb93d
+} LIBDAXCTL_8;
2eb93d
diff --git a/daxctl/libdaxctl.h b/daxctl/libdaxctl.h
2eb93d
index e82b274..30ab51a 100644
2eb93d
--- a/daxctl/libdaxctl.h
2eb93d
+++ b/daxctl/libdaxctl.h
2eb93d
@@ -71,6 +71,7 @@ int daxctl_dev_disable(struct daxctl_dev *dev);
2eb93d
 int daxctl_dev_enable_devdax(struct daxctl_dev *dev);
2eb93d
 int daxctl_dev_enable_ram(struct daxctl_dev *dev);
2eb93d
 int daxctl_dev_get_target_node(struct daxctl_dev *dev);
2eb93d
+int daxctl_dev_will_auto_online_memory(struct daxctl_dev *dev);
2eb93d
 
2eb93d
 struct daxctl_memory;
2eb93d
 struct daxctl_memory *daxctl_dev_get_memory(struct daxctl_dev *dev);
2eb93d
diff --git a/test/daxctl-devices.sh b/test/daxctl-devices.sh
2eb93d
index 496e4f2..eed5906 100755
2eb93d
--- a/test/daxctl-devices.sh
2eb93d
+++ b/test/daxctl-devices.sh
2eb93d
@@ -64,6 +64,26 @@ daxctl_get_mode()
2eb93d
 	"$DAXCTL" list -d "$1" | jq -er '.[].mode'
2eb93d
 }
2eb93d
 
2eb93d
+set_online_policy()
2eb93d
+{
2eb93d
+	echo "online" > /sys/devices/system/memory/auto_online_blocks
2eb93d
+}
2eb93d
+
2eb93d
+unset_online_policy()
2eb93d
+{
2eb93d
+	echo "offline" > /sys/devices/system/memory/auto_online_blocks
2eb93d
+}
2eb93d
+
2eb93d
+save_online_policy()
2eb93d
+{
2eb93d
+	saved_policy="$(cat /sys/devices/system/memory/auto_online_blocks)"
2eb93d
+}
2eb93d
+
2eb93d
+restore_online_policy()
2eb93d
+{
2eb93d
+	echo "$saved_policy" > /sys/devices/system/memory/auto_online_blocks
2eb93d
+}
2eb93d
+
2eb93d
 daxctl_test()
2eb93d
 {
2eb93d
 	local daxdev
2eb93d
@@ -71,6 +91,9 @@ daxctl_test()
2eb93d
 	daxdev=$(daxctl_get_dev "$testdev")
2eb93d
 	test -n "$daxdev"
2eb93d
 
2eb93d
+	# these tests need to run with kernel onlining policy turned off
2eb93d
+	save_online_policy
2eb93d
+	unset_online_policy
2eb93d
 	"$DAXCTL" reconfigure-device -N -m system-ram "$daxdev"
2eb93d
 	[[ $(daxctl_get_mode "$daxdev") == "system-ram" ]]
2eb93d
 	"$DAXCTL" online-memory "$daxdev"
2eb93d
@@ -81,6 +104,19 @@ daxctl_test()
2eb93d
 	[[ $(daxctl_get_mode "$daxdev") == "system-ram" ]]
2eb93d
 	"$DAXCTL" reconfigure-device -f -m devdax "$daxdev"
2eb93d
 	[[ $(daxctl_get_mode "$daxdev") == "devdax" ]]
2eb93d
+
2eb93d
+	# this tests for reconfiguration failure if an online-policy is set
2eb93d
+	set_online_policy
2eb93d
+	: "This command is expected to fail:"
2eb93d
+	if ! "$DAXCTL" reconfigure-device -N -m system-ram "$daxdev"; then
2eb93d
+		echo "reconfigure failed as expected"
2eb93d
+	else
2eb93d
+		echo "reconfigure succeded, expected failure"
2eb93d
+		restore_online_policy
2eb93d
+		return 1
2eb93d
+	fi
2eb93d
+
2eb93d
+	restore_online_policy
2eb93d
 }
2eb93d
 
2eb93d
 find_testdev
2eb93d
-- 
2eb93d
2.27.0
2eb93d