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

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