@@ -42,3 +42,4 @@ include::../copyright.txt[]
SEE ALSO
--------
linkcxl:cxl-list[1],
+linkcxl:cxl-sanitize-memdev[1],
@@ -49,6 +49,7 @@ cxl_manpages = [
'cxl-monitor.txt',
'cxl-update-firmware.txt',
'cxl-set-alert-config.txt',
+ 'cxl-sanitize-memdev.txt',
'cxl-wait-sanitize.txt',
]
@@ -16,6 +16,7 @@ int cmd_reserve_dpa(int argc, const char **argv, struct cxl_ctx *ctx);
int cmd_free_dpa(int argc, const char **argv, struct cxl_ctx *ctx);
int cmd_update_fw(int argc, const char **argv, struct cxl_ctx *ctx);
int cmd_set_alert_config(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_sanitize_memdev(int argc, const char **argv, struct cxl_ctx *ctx);
int cmd_wait_sanitize(int argc, const char **argv, struct cxl_ctx *ctx);
int cmd_disable_port(int argc, const char **argv, struct cxl_ctx *ctx);
int cmd_enable_port(int argc, const char **argv, struct cxl_ctx *ctx);
@@ -80,6 +80,7 @@ static struct cmd_struct commands[] = {
{ "disable-region", .c_fn = cmd_disable_region },
{ "destroy-region", .c_fn = cmd_destroy_region },
{ "monitor", .c_fn = cmd_monitor },
+ { "sanitize-memdev", .c_fn = cmd_sanitize_memdev },
};
int main(int argc, const char **argv)
@@ -1414,6 +1414,21 @@ CXL_EXPORT int cxl_memdev_get_id(struct cxl_memdev *memdev)
return memdev->id;
}
+CXL_EXPORT int cxl_memdev_sanitize(struct cxl_memdev *memdev, char *op)
+{
+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev);
+ char *path = memdev->dev_buf;
+ int len = memdev->buf_len;
+
+ if (snprintf(path, len,
+ "%s/security/%s", memdev->dev_path, op) >= len) {
+ err(ctx, "%s: buffer too small!\n",
+ cxl_memdev_get_devname(memdev));
+ return -ERANGE;
+ }
+ return sysfs_write_attr(ctx, path, "1\n");
+}
+
CXL_EXPORT int cxl_memdev_wait_sanitize(struct cxl_memdev *memdev,
int timeout_ms)
{
@@ -287,4 +287,5 @@ LIBECXL_8 {
global:
cxl_memdev_trigger_poison_list;
cxl_region_trigger_poison_list;
+ cxl_memdev_sanitize;
} LIBCXL_7;
@@ -79,6 +79,7 @@ bool cxl_memdev_fw_update_in_progress(struct cxl_memdev *memdev);
size_t cxl_memdev_fw_update_get_remaining(struct cxl_memdev *memdev);
int cxl_memdev_update_fw(struct cxl_memdev *memdev, const char *fw_path);
int cxl_memdev_cancel_fw_update(struct cxl_memdev *memdev);
+int cxl_memdev_sanitize(struct cxl_memdev *memdev, char *op);
int cxl_memdev_wait_sanitize(struct cxl_memdev *memdev, int timeout_ms);
/* ABI spelling mistakes are forever */
@@ -35,6 +35,8 @@ static struct parameters {
bool align;
bool cancel;
bool wait;
+ bool sanitize;
+ bool secure_erase;
const char *type;
const char *size;
const char *decoder_filter;
@@ -160,6 +162,10 @@ OPT_STRING('\0', "pmem-err-alert", \
¶m.corrected_pmem_err_alert, "'on' or 'off'", \
"enable or disable corrected pmem error warning alert")
+#define SANITIZE_OPTIONS() \
+OPT_BOOLEAN('e', "secure-erase", ¶m.secure_erase, \
+ "Secure Erase a memdev")
+
#define WAIT_SANITIZE_OPTIONS() \
OPT_INTEGER('t', "timeout", ¶m.timeout, \
"time in milliseconds to wait for overwrite completion (default: infinite)")
@@ -226,6 +232,12 @@ static const struct option set_alert_options[] = {
OPT_END(),
};
+static const struct option sanitize_options[] = {
+ BASE_OPTIONS(),
+ SANITIZE_OPTIONS(),
+ OPT_END(),
+};
+
static const struct option wait_sanitize_options[] = {
BASE_OPTIONS(),
WAIT_SANITIZE_OPTIONS(),
@@ -772,6 +784,19 @@ out_err:
return rc;
}
+static int action_sanitize_memdev(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ int rc;
+
+ if (param.secure_erase)
+ rc = cxl_memdev_sanitize(memdev, "erase");
+ else
+ rc = cxl_memdev_sanitize(memdev, "sanitize");
+
+ return rc;
+}
+
static int action_wait_sanitize(struct cxl_memdev *memdev,
struct action_context *actx)
{
@@ -1228,6 +1253,19 @@ int cmd_set_alert_config(int argc, const char **argv, struct cxl_ctx *ctx)
return count >= 0 ? 0 : EXIT_FAILURE;
}
+int cmd_sanitize_memdev(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int count = memdev_action(
+ argc, argv, ctx, action_sanitize_memdev, sanitize_options,
+ "cxl sanitize-memdev <mem0> [<mem1>..<memn>] [<options>]");
+
+ log_info(&ml, "sanitize %s on %d mem device%s\n",
+ count >= 0 ? "completed/started" : "failed",
+ count >= 0 ? count : 0, count > 1 ? "s" : "");
+
+ return count >= 0 ? 0 : EXIT_FAILURE;
+}
+
int cmd_wait_sanitize(int argc, const char **argv, struct cxl_ctx *ctx)
{
int count = memdev_action(
@@ -45,7 +45,7 @@ count=${#active_mem[@]}
set_timeout ${active_mem[0]} 2000
# sanitize with an active memdev should fail
-echo 1 > /sys/bus/cxl/devices/${active_mem[0]}/security/sanitize && err $LINENO
+"$CXL" sanitize-memdev ${active_mem[0]} && err $LINENO
# find an inactive mem
inactive=""
@@ -67,7 +67,7 @@ done
# secounds
set_timeout $inactive 3000
start=$SECONDS
-echo 1 > /sys/bus/cxl/devices/${inactive}/security/sanitize &
+"$CXL" sanitize-memdev $inactive || err $LINENO
"$CXL" wait-sanitize $inactive || err $LINENO
((SECONDS > start + 2)) || err $LINENO
Add a new cxl_memdev_sanitize() to libcxl to support triggering memory device sanitation, in either Sanitize and/or Secure Erase, per the CXL 3.0 spec. This is analogous to 'ndctl sanitize-dimm'. Signed-off-by: Davidlohr Bueso <dave@stgolabs.net> --- Changes from v2: resend, corrupted patch file Changes from v1: - remove '-s' option and allow sanitize and secure erase to be exclusive. (Vishal) - update cxl-sanitize test cases (Alison) - update wait-sanitize manpage to include sanitize-memdev cmd Documentation/cxl/cxl-wait-sanitize.txt | 1 + Documentation/cxl/meson.build | 1 + cxl/builtin.h | 1 + cxl/cxl.c | 1 + cxl/lib/libcxl.c | 15 ++++++++++ cxl/lib/libcxl.sym | 1 + cxl/libcxl.h | 1 + cxl/memdev.c | 38 +++++++++++++++++++++++++ test/cxl-sanitize.sh | 4 +-- 9 files changed, 61 insertions(+), 2 deletions(-)