new file mode 100644
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0
+
+cxl-wait-sanitize(1)
+====================
+
+NAME
+----
+cxl-wait-sanitize - wait for a sanitization operation to complete
+
+SYNOPSIS
+--------
+[verse]
+'cxl wait-sanitize' <mem0> [<mem1>..<memN>] [<options>]
+
+DESCRIPTION
+-----------
+The kernel provides a POLL(2) capable sysfs file ('security/state') to
+indicate the state of device sanitization. When sanitization is in progress,
+this command waits for a change in the state of this file across all
+specified memdevs.
+
+OPTIONS
+-------
+<memdev>::
+include::memdev-option.txt[]
+
+-b::
+--bus=::
+include::bus-option.txt[]
+
+-v::
+--verbose::
+ Emit debug messages.
+
+include::../copyright.txt[]
@@ -135,6 +135,7 @@ int cxl_memdev_write_label(struct cxl_memdev *memdev, void *buf, size_t length,
struct cxl_cmd *cxl_cmd_new_get_partition(struct cxl_memdev *memdev);
struct cxl_cmd *cxl_cmd_new_set_partition(struct cxl_memdev *memdev,
unsigned long long volatile_size);
+int cxl_memdev_wait_sanitize(struct cxl_memdev *memdev);
----
@@ -45,6 +45,7 @@ cxl_manpages = [
'cxl-disable-region.txt',
'cxl-enable-region.txt',
'cxl-destroy-region.txt',
+ 'cxl-wait-sanitize.txt',
'cxl-monitor.txt',
]
@@ -22,6 +22,7 @@ int cmd_create_region(int argc, const char **argv, struct cxl_ctx *ctx);
int cmd_enable_region(int argc, const char **argv, struct cxl_ctx *ctx);
int cmd_disable_region(int argc, const char **argv, struct cxl_ctx *ctx);
int cmd_destroy_region(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_wait_sanitize(int argc, const char **argv, struct cxl_ctx *ctx);
#ifdef ENABLE_LIBTRACEFS
int cmd_monitor(int argc, const char **argv, struct cxl_ctx *ctx);
#else
@@ -76,6 +76,7 @@ static struct cmd_struct commands[] = {
{ "enable-region", .c_fn = cmd_enable_region },
{ "disable-region", .c_fn = cmd_disable_region },
{ "destroy-region", .c_fn = cmd_destroy_region },
+ { "wait-sanitize", .c_fn = cmd_wait_sanitize },
{ "monitor", .c_fn = cmd_monitor },
};
@@ -7,6 +7,7 @@
#include <stdlib.h>
#include <dirent.h>
#include <unistd.h>
+#include <poll.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
@@ -3968,6 +3969,83 @@ CXL_EXPORT struct cxl_cmd *cxl_cmd_new_set_partition(struct cxl_memdev *memdev,
return cmd;
}
+CXL_EXPORT int cxl_memdev_wait_sanitize(struct cxl_memdev *memdev)
+{
+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev);
+ struct pollfd fds;
+ char buf[SYSFS_ATTR_SIZE];
+ int fd = 0, rc;
+ char *path = memdev->dev_buf;
+ int len = memdev->buf_len;
+
+ if (snprintf(path, len,
+ "%s/security/state", memdev->dev_path) >= len) {
+ err(ctx, "%s: buffer too small!\n",
+ cxl_memdev_get_devname(memdev));
+ return -ERANGE;
+ }
+
+ fd = open(path, O_RDONLY|O_CLOEXEC);
+ if (fd < 0) {
+ rc = -errno;
+ err(ctx, "open: %s\n", strerror(errno));
+ return rc;
+ }
+ memset(&fds, 0, sizeof(fds));
+ fds.fd = fd;
+
+ rc = sysfs_read_attr(ctx, path, buf);
+ if (rc < 0) {
+ rc = -EOPNOTSUPP;
+ goto out;
+ }
+ /* skipping if we aren't in sanitize state */
+ if (strncmp(buf, "sanitize", 8) != 0) {
+ rc = 0;
+ goto out;
+ }
+
+ for (;;) {
+ rc = sysfs_read_attr(ctx, path, buf);
+ if (rc < 0) {
+ rc = -EOPNOTSUPP;
+ break;
+ }
+
+ if (strncmp(buf, "sanitize", 8) == 0) {
+ rc = poll(&fds, 1, -1);
+ if (rc < 0) {
+ rc = -errno;
+ err(ctx, "poll error: %s\n", strerror(errno));
+ break;
+ }
+ dbg(ctx, "poll wake: revents: %d\n", fds.revents);
+ if (pread(fd, buf, 1, 0) == -1) {
+ rc = -errno;
+ break;
+ }
+ fds.revents = 0;
+ } else {
+ if (strncmp(buf, "disabled", 8) == 0)
+ rc = 1;
+ break;
+ }
+ }
+
+ if (rc == 1)
+ dbg(ctx, "%s: sanitize complete\n",
+ cxl_memdev_get_devname(memdev));
+ else if (rc == 0)
+ dbg(ctx, "%s: sanitize skipped\n",
+ cxl_memdev_get_devname(memdev));
+ else
+ dbg(ctx, "%s: sanitize error waiting for complete\n",
+ cxl_memdev_get_devname(memdev));
+ out:
+ close(fd);
+ return rc;
+}
+
CXL_EXPORT int cxl_cmd_submit(struct cxl_cmd *cmd)
{
struct cxl_memdev *memdev = cmd->memdev;
@@ -250,3 +250,8 @@ global:
cxl_region_get_daxctl_region;
cxl_port_get_parent_dport;
} LIBCXL_4;
+
+LIBCXL_6 {
+global:
+ cxl_memdev_wait_sanitize;
+} LIBCXL_5;
@@ -416,6 +416,7 @@ unsigned long long cxl_cmd_partition_get_next_volatile_size(struct cxl_cmd *cmd)
unsigned long long cxl_cmd_partition_get_next_persistent_size(struct cxl_cmd *cmd);
struct cxl_cmd *cxl_cmd_new_set_partition(struct cxl_memdev *memdev,
unsigned long long volatile_size);
+int cxl_memdev_wait_sanitize(struct cxl_memdev *memdev);
enum cxl_setpartition_mode {
CXL_SETPART_NEXTBOOT,
@@ -135,6 +135,11 @@ static const struct option free_dpa_options[] = {
OPT_END(),
};
+static const struct option wait_sanitize_options[] = {
+ BASE_OPTIONS(),
+ OPT_END(),
+};
+
enum reserve_dpa_mode {
DPA_ALLOC,
DPA_FREE,
@@ -653,6 +658,16 @@ out_err:
return rc;
}
+static int action_wait_sanitize(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ /*
+ * It's perfectly ok for the device to be active
+ * or enabled, so no need to check anything here.
+ */
+ return cxl_memdev_wait_sanitize(memdev);
+}
+
static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx,
int (*action)(struct cxl_memdev *memdev,
struct action_context *actx),
@@ -893,3 +908,14 @@ int cmd_free_dpa(int argc, const char **argv, struct cxl_ctx *ctx)
return count >= 0 ? 0 : EXIT_FAILURE;
}
+
+int cmd_wait_sanitize(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int count = memdev_action(argc, argv, ctx, action_wait_sanitize,
+ wait_sanitize_options,
+ "cxl wait-sanitize <mem0> [<mem1>..<memn>] [<options>]");
+ log_info(&ml, "sanitization completed on %d mem device%s\n",
+ count >= 0 ? count : 0, count > 1 ? "s" : "");
+
+ return count >= 0 ? 0 : EXIT_FAILURE;
+}
Add a new cxl_memdev_wait_sanitize() to libcxl to support waiting for sanitize operation to be done in the background, if any. This is analogous to 'ndctl wait-overwrite'. Signed-off-by: Davidlohr Bueso <dave@stgolabs.net> --- Documentation/cxl/cxl-wait-sanitize.txt | 35 +++++++++++ Documentation/cxl/lib/libcxl.txt | 1 + Documentation/cxl/meson.build | 1 + cxl/builtin.h | 1 + cxl/cxl.c | 1 + cxl/lib/libcxl.c | 78 +++++++++++++++++++++++++ cxl/lib/libcxl.sym | 5 ++ cxl/libcxl.h | 1 + cxl/memdev.c | 26 +++++++++ 9 files changed, 149 insertions(+) create mode 100644 Documentation/cxl/cxl-wait-sanitize.txt