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