anitazha / rpms / ndctl

Forked from rpms/ndctl 2 years ago
Clone

Blame 0042-cxl-add-commands-to-read-write-and-zero-labels.patch

Jeff Moyer 2c91dc
From c415cebe4b5ca50e06db78a4719f312e33106936 Mon Sep 17 00:00:00 2001
Jeff Moyer 2c91dc
From: Vishal Verma <vishal.l.verma@intel.com>
Jeff Moyer 2c91dc
Date: Thu, 7 Oct 2021 02:21:35 -0600
Jeff Moyer 2c91dc
Subject: [PATCH 042/217] cxl: add commands to read, write, and zero labels
Jeff Moyer 2c91dc
Jeff Moyer 2c91dc
Add the following cxl-cli commands: read-labels, write-labels,
Jeff Moyer 2c91dc
zero-labels. They operate on a CXL memdev, or a set of memdevs, and
Jeff Moyer 2c91dc
allow interacting with the label storage area (LSA) on the device.
Jeff Moyer 2c91dc
Jeff Moyer 2c91dc
Add man pages for the above cxl-cli commands.
Jeff Moyer 2c91dc
Jeff Moyer 2c91dc
Cc: Dan Williams <dan.j.williams@intel.com>
Jeff Moyer 2c91dc
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Jeff Moyer 2c91dc
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
Jeff Moyer 2c91dc
---
Jeff Moyer 2c91dc
 Documentation/cxl/Makefile.am            |   5 +-
Jeff Moyer 2c91dc
 Documentation/cxl/cxl-read-labels.txt    |  33 +++
Jeff Moyer 2c91dc
 Documentation/cxl/cxl-write-labels.txt   |  32 +++
Jeff Moyer 2c91dc
 Documentation/cxl/cxl-zero-labels.txt    |  29 ++
Jeff Moyer 2c91dc
 Documentation/cxl/labels-description.txt |   8 +
Jeff Moyer 2c91dc
 Documentation/cxl/labels-options.txt     |  17 ++
Jeff Moyer 2c91dc
 Documentation/cxl/memdev-option.txt      |   4 +
Jeff Moyer 2c91dc
 cxl/Makefile.am                          |   1 +
Jeff Moyer 2c91dc
 cxl/builtin.h                            |   5 +
Jeff Moyer 2c91dc
 cxl/cxl.c                                |   3 +
Jeff Moyer 2c91dc
 cxl/memdev.c                             | 324 +++++++++++++++++++++++
Jeff Moyer 2c91dc
 11 files changed, 460 insertions(+), 1 deletion(-)
Jeff Moyer 2c91dc
 create mode 100644 Documentation/cxl/cxl-read-labels.txt
Jeff Moyer 2c91dc
 create mode 100644 Documentation/cxl/cxl-write-labels.txt
Jeff Moyer 2c91dc
 create mode 100644 Documentation/cxl/cxl-zero-labels.txt
Jeff Moyer 2c91dc
 create mode 100644 Documentation/cxl/labels-description.txt
Jeff Moyer 2c91dc
 create mode 100644 Documentation/cxl/labels-options.txt
Jeff Moyer 2c91dc
 create mode 100644 Documentation/cxl/memdev-option.txt
Jeff Moyer 2c91dc
 create mode 100644 cxl/memdev.c
Jeff Moyer 2c91dc
Jeff Moyer 2c91dc
diff --git a/Documentation/cxl/Makefile.am b/Documentation/cxl/Makefile.am
Jeff Moyer 2c91dc
index db98dd7..efabaa3 100644
Jeff Moyer 2c91dc
--- a/Documentation/cxl/Makefile.am
Jeff Moyer 2c91dc
+++ b/Documentation/cxl/Makefile.am
Jeff Moyer 2c91dc
@@ -19,7 +19,10 @@ endif
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 man1_MANS = \
Jeff Moyer 2c91dc
 	cxl.1 \
Jeff Moyer 2c91dc
-	cxl-list.1
Jeff Moyer 2c91dc
+	cxl-list.1 \
Jeff Moyer 2c91dc
+	cxl-read-labels.1 \
Jeff Moyer 2c91dc
+	cxl-write-labels.1 \
Jeff Moyer 2c91dc
+	cxl-zero-labels.1
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 EXTRA_DIST = $(man1_MANS)
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
diff --git a/Documentation/cxl/cxl-read-labels.txt b/Documentation/cxl/cxl-read-labels.txt
Jeff Moyer 2c91dc
new file mode 100644
Jeff Moyer 2c91dc
index 0000000..143f296
Jeff Moyer 2c91dc
--- /dev/null
Jeff Moyer 2c91dc
+++ b/Documentation/cxl/cxl-read-labels.txt
Jeff Moyer 2c91dc
@@ -0,0 +1,33 @@
Jeff Moyer 2c91dc
+// SPDX-License-Identifier: GPL-2.0
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+cxl-read-labels(1)
Jeff Moyer 2c91dc
+==================
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+NAME
Jeff Moyer 2c91dc
+----
Jeff Moyer 2c91dc
+cxl-read-labels - read out the label area on a CXL memdev
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+SYNOPSIS
Jeff Moyer 2c91dc
+--------
Jeff Moyer 2c91dc
+[verse]
Jeff Moyer 2c91dc
+'cxl read-labels' <mem0> [<mem1>..<memN>] [<options>]
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+include::labels-description.txt[]
Jeff Moyer 2c91dc
+This command dumps the raw binary data in a memdev's label area to stdout or a
Jeff Moyer 2c91dc
+file.  In the multi-memdev case the data is concatenated.
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+OPTIONS
Jeff Moyer 2c91dc
+-------
Jeff Moyer 2c91dc
+include::labels-options.txt[]
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+-o::
Jeff Moyer 2c91dc
+--output::
Jeff Moyer 2c91dc
+	output file
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+include::../copyright.txt[]
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+SEE ALSO
Jeff Moyer 2c91dc
+--------
Jeff Moyer 2c91dc
+linkcxl:cxl-write-labels[1],
Jeff Moyer 2c91dc
+linkcxl:cxl-zero-labels[1],
Jeff Moyer 2c91dc
+CXL-2.0 9.13.2
Jeff Moyer 2c91dc
diff --git a/Documentation/cxl/cxl-write-labels.txt b/Documentation/cxl/cxl-write-labels.txt
Jeff Moyer 2c91dc
new file mode 100644
Jeff Moyer 2c91dc
index 0000000..75f42a5
Jeff Moyer 2c91dc
--- /dev/null
Jeff Moyer 2c91dc
+++ b/Documentation/cxl/cxl-write-labels.txt
Jeff Moyer 2c91dc
@@ -0,0 +1,32 @@
Jeff Moyer 2c91dc
+// SPDX-License-Identifier: GPL-2.0
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+cxl-write-labels(1)
Jeff Moyer 2c91dc
+===================
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+NAME
Jeff Moyer 2c91dc
+----
Jeff Moyer 2c91dc
+cxl-write-labels - write data to the label area on a memdev
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+SYNOPSIS
Jeff Moyer 2c91dc
+--------
Jeff Moyer 2c91dc
+[verse]
Jeff Moyer 2c91dc
+'cxl write-labels <mem> [-i <filename>]'
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+include::labels-description.txt[]
Jeff Moyer 2c91dc
+Read data from the input filename, or stdin, and write it to the given
Jeff Moyer 2c91dc
+<mem> device. Note that the device must not be active in any region, or
Jeff Moyer 2c91dc
+actively registered with the nvdimm subsystem. If it is, the kernel will
Jeff Moyer 2c91dc
+not allow write access to the device's label data area.
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+OPTIONS
Jeff Moyer 2c91dc
+-------
Jeff Moyer 2c91dc
+include::labels-options.txt[]
Jeff Moyer 2c91dc
+-i::
Jeff Moyer 2c91dc
+--input::
Jeff Moyer 2c91dc
+	input file
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+SEE ALSO
Jeff Moyer 2c91dc
+--------
Jeff Moyer 2c91dc
+linkcxl:cxl-read-labels[1],
Jeff Moyer 2c91dc
+linkcxl:cxl-zero-labels[1],
Jeff Moyer 2c91dc
+CXL-2.0 9.13.2
Jeff Moyer 2c91dc
diff --git a/Documentation/cxl/cxl-zero-labels.txt b/Documentation/cxl/cxl-zero-labels.txt
Jeff Moyer 2c91dc
new file mode 100644
Jeff Moyer 2c91dc
index 0000000..bf95b24
Jeff Moyer 2c91dc
--- /dev/null
Jeff Moyer 2c91dc
+++ b/Documentation/cxl/cxl-zero-labels.txt
Jeff Moyer 2c91dc
@@ -0,0 +1,29 @@
Jeff Moyer 2c91dc
+// SPDX-License-Identifier: GPL-2.0
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+cxl-zero-labels(1)
Jeff Moyer 2c91dc
+==================
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+NAME
Jeff Moyer 2c91dc
+----
Jeff Moyer 2c91dc
+cxl-zero-labels - zero out the label area on a set of memdevs
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+SYNOPSIS
Jeff Moyer 2c91dc
+--------
Jeff Moyer 2c91dc
+[verse]
Jeff Moyer 2c91dc
+'cxl zero-labels' <mem0> [<mem1>..<memN>] [<options>]
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+include::labels-description.txt[]
Jeff Moyer 2c91dc
+This command resets the device to its default state by
Jeff Moyer 2c91dc
+deleting all labels.
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+OPTIONS
Jeff Moyer 2c91dc
+-------
Jeff Moyer 2c91dc
+include::labels-options.txt[]
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+include::../copyright.txt[]
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+SEE ALSO
Jeff Moyer 2c91dc
+--------
Jeff Moyer 2c91dc
+linkcxl:cxl-read-labels[1],
Jeff Moyer 2c91dc
+linkcxl:cxl-write-labels[1],
Jeff Moyer 2c91dc
+CXL-2.0 9.13.2
Jeff Moyer 2c91dc
diff --git a/Documentation/cxl/labels-description.txt b/Documentation/cxl/labels-description.txt
Jeff Moyer 2c91dc
new file mode 100644
Jeff Moyer 2c91dc
index 0000000..f60bd5d
Jeff Moyer 2c91dc
--- /dev/null
Jeff Moyer 2c91dc
+++ b/Documentation/cxl/labels-description.txt
Jeff Moyer 2c91dc
@@ -0,0 +1,8 @@
Jeff Moyer 2c91dc
+// SPDX-License-Identifier: GPL-2.0
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+DESCRIPTION
Jeff Moyer 2c91dc
+-----------
Jeff Moyer 2c91dc
+The region label area is a small persistent partition of capacity
Jeff Moyer 2c91dc
+available on some CXL memory devices. The label area is used to
Jeff Moyer 2c91dc
+and configure or determine the set of memory devices participating
Jeff Moyer 2c91dc
+in different interleave sets.
Jeff Moyer 2c91dc
diff --git a/Documentation/cxl/labels-options.txt b/Documentation/cxl/labels-options.txt
Jeff Moyer 2c91dc
new file mode 100644
Jeff Moyer 2c91dc
index 0000000..06fbac3
Jeff Moyer 2c91dc
--- /dev/null
Jeff Moyer 2c91dc
+++ b/Documentation/cxl/labels-options.txt
Jeff Moyer 2c91dc
@@ -0,0 +1,17 @@
Jeff Moyer 2c91dc
+// SPDX-License-Identifier: GPL-2.0
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+<memory device(s)>::
Jeff Moyer 2c91dc
+include::memdev-option.txt[]
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+-s::
Jeff Moyer 2c91dc
+--size=::
Jeff Moyer 2c91dc
+	Limit the operation to the given number of bytes. A size of 0
Jeff Moyer 2c91dc
+	indicates to operate over the entire label capacity.
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+-O::
Jeff Moyer 2c91dc
+--offset=::
Jeff Moyer 2c91dc
+	Begin the operation at the given offset into the label area.
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+-v::
Jeff Moyer 2c91dc
+	Turn on verbose debug messages in the library (if libcxl was built with
Jeff Moyer 2c91dc
+	logging and debug enabled).
Jeff Moyer 2c91dc
diff --git a/Documentation/cxl/memdev-option.txt b/Documentation/cxl/memdev-option.txt
Jeff Moyer 2c91dc
new file mode 100644
Jeff Moyer 2c91dc
index 0000000..e778582
Jeff Moyer 2c91dc
--- /dev/null
Jeff Moyer 2c91dc
+++ b/Documentation/cxl/memdev-option.txt
Jeff Moyer 2c91dc
@@ -0,0 +1,4 @@
Jeff Moyer 2c91dc
+// SPDX-License-Identifier: GPL-2.0
Jeff Moyer 2c91dc
+A 'memX' device name, or a memdev id number. Restrict the operation to
Jeff Moyer 2c91dc
+the specified memdev(s). The keyword 'all' can be specified to indicate
Jeff Moyer 2c91dc
+the lack of any restriction.
Jeff Moyer 2c91dc
diff --git a/cxl/Makefile.am b/cxl/Makefile.am
Jeff Moyer 2c91dc
index 98606b9..da9f91d 100644
Jeff Moyer 2c91dc
--- a/cxl/Makefile.am
Jeff Moyer 2c91dc
+++ b/cxl/Makefile.am
Jeff Moyer 2c91dc
@@ -10,6 +10,7 @@ config.h: $(srcdir)/Makefile.am
Jeff Moyer 2c91dc
 cxl_SOURCES =\
Jeff Moyer 2c91dc
 		cxl.c \
Jeff Moyer 2c91dc
 		list.c \
Jeff Moyer 2c91dc
+		memdev.c \
Jeff Moyer 2c91dc
 		../util/json.c \
Jeff Moyer 2c91dc
 		builtin.h
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
diff --git a/cxl/builtin.h b/cxl/builtin.h
Jeff Moyer 2c91dc
index 3797f98..78eca6e 100644
Jeff Moyer 2c91dc
--- a/cxl/builtin.h
Jeff Moyer 2c91dc
+++ b/cxl/builtin.h
Jeff Moyer 2c91dc
@@ -5,4 +5,9 @@
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 struct cxl_ctx;
Jeff Moyer 2c91dc
 int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx);
Jeff Moyer 2c91dc
+int cmd_write_labels(int argc, const char **argv, struct cxl_ctx *ctx);
Jeff Moyer 2c91dc
+int cmd_read_labels(int argc, const char **argv, struct cxl_ctx *ctx);
Jeff Moyer 2c91dc
+int cmd_zero_labels(int argc, const char **argv, struct cxl_ctx *ctx);
Jeff Moyer 2c91dc
+int cmd_init_labels(int argc, const char **argv, struct cxl_ctx *ctx);
Jeff Moyer 2c91dc
+int cmd_check_labels(int argc, const char **argv, struct cxl_ctx *ctx);
Jeff Moyer 2c91dc
 #endif /* _CXL_BUILTIN_H_ */
Jeff Moyer 2c91dc
diff --git a/cxl/cxl.c b/cxl/cxl.c
Jeff Moyer 2c91dc
index a7725f8..4b1661d 100644
Jeff Moyer 2c91dc
--- a/cxl/cxl.c
Jeff Moyer 2c91dc
+++ b/cxl/cxl.c
Jeff Moyer 2c91dc
@@ -61,6 +61,9 @@ static struct cmd_struct commands[] = {
Jeff Moyer 2c91dc
 	{ "version", .c_fn = cmd_version },
Jeff Moyer 2c91dc
 	{ "list", .c_fn = cmd_list },
Jeff Moyer 2c91dc
 	{ "help", .c_fn = cmd_help },
Jeff Moyer 2c91dc
+	{ "zero-labels", .c_fn = cmd_zero_labels },
Jeff Moyer 2c91dc
+	{ "read-labels", .c_fn = cmd_read_labels },
Jeff Moyer 2c91dc
+	{ "write-labels", .c_fn = cmd_write_labels },
Jeff Moyer 2c91dc
 };
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 int main(int argc, const char **argv)
Jeff Moyer 2c91dc
diff --git a/cxl/memdev.c b/cxl/memdev.c
Jeff Moyer 2c91dc
new file mode 100644
Jeff Moyer 2c91dc
index 0000000..5ee38e5
Jeff Moyer 2c91dc
--- /dev/null
Jeff Moyer 2c91dc
+++ b/cxl/memdev.c
Jeff Moyer 2c91dc
@@ -0,0 +1,324 @@
Jeff Moyer 2c91dc
+// SPDX-License-Identifier: GPL-2.0
Jeff Moyer 2c91dc
+/* Copyright (C) 2020-2021 Intel Corporation. All rights reserved. */
Jeff Moyer 2c91dc
+#include <stdio.h>
Jeff Moyer 2c91dc
+#include <errno.h>
Jeff Moyer 2c91dc
+#include <stdlib.h>
Jeff Moyer 2c91dc
+#include <unistd.h>
Jeff Moyer 2c91dc
+#include <limits.h>
Jeff Moyer 2c91dc
+#include <util/log.h>
Jeff Moyer 2c91dc
+#include <util/filter.h>
Jeff Moyer 2c91dc
+#include <cxl/libcxl.h>
Jeff Moyer 2c91dc
+#include <util/parse-options.h>
Jeff Moyer 2c91dc
+#include <ccan/minmax/minmax.h>
Jeff Moyer 2c91dc
+#include <ccan/array_size/array_size.h>
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+struct action_context {
Jeff Moyer 2c91dc
+	FILE *f_out;
Jeff Moyer 2c91dc
+	FILE *f_in;
Jeff Moyer 2c91dc
+};
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+static struct parameters {
Jeff Moyer 2c91dc
+	const char *outfile;
Jeff Moyer 2c91dc
+	const char *infile;
Jeff Moyer 2c91dc
+	unsigned len;
Jeff Moyer 2c91dc
+	unsigned offset;
Jeff Moyer 2c91dc
+	bool verbose;
Jeff Moyer 2c91dc
+} param;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+#define fail(fmt, ...) \
Jeff Moyer 2c91dc
+do { \
Jeff Moyer 2c91dc
+	fprintf(stderr, "cxl-%s:%s:%d: " fmt, \
Jeff Moyer 2c91dc
+			VERSION, __func__, __LINE__, ##__VA_ARGS__); \
Jeff Moyer 2c91dc
+} while (0)
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+#define BASE_OPTIONS() \
Jeff Moyer 2c91dc
+OPT_BOOLEAN('v',"verbose", &param.verbose, "turn on debug")
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+#define READ_OPTIONS() \
Jeff Moyer 2c91dc
+OPT_STRING('o', "output", &param.outfile, "output-file", \
Jeff Moyer 2c91dc
+	"filename to write label area contents")
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+#define WRITE_OPTIONS() \
Jeff Moyer 2c91dc
+OPT_STRING('i', "input", &param.infile, "input-file", \
Jeff Moyer 2c91dc
+	"filename to read label area data")
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+#define LABEL_OPTIONS() \
Jeff Moyer 2c91dc
+OPT_UINTEGER('s', "size", &param.len, "number of label bytes to operate"), \
Jeff Moyer 2c91dc
+OPT_UINTEGER('O', "offset", &param.offset, \
Jeff Moyer 2c91dc
+	"offset into the label area to start operation")
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+static const struct option read_options[] = {
Jeff Moyer 2c91dc
+	BASE_OPTIONS(),
Jeff Moyer 2c91dc
+	LABEL_OPTIONS(),
Jeff Moyer 2c91dc
+	READ_OPTIONS(),
Jeff Moyer 2c91dc
+	OPT_END(),
Jeff Moyer 2c91dc
+};
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+static const struct option write_options[] = {
Jeff Moyer 2c91dc
+	BASE_OPTIONS(),
Jeff Moyer 2c91dc
+	LABEL_OPTIONS(),
Jeff Moyer 2c91dc
+	WRITE_OPTIONS(),
Jeff Moyer 2c91dc
+	OPT_END(),
Jeff Moyer 2c91dc
+};
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+static const struct option zero_options[] = {
Jeff Moyer 2c91dc
+	BASE_OPTIONS(),
Jeff Moyer 2c91dc
+	LABEL_OPTIONS(),
Jeff Moyer 2c91dc
+	OPT_END(),
Jeff Moyer 2c91dc
+};
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+static int action_zero(struct cxl_memdev *memdev, struct action_context *actx)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	size_t size;
Jeff Moyer 2c91dc
+	int rc;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (param.len)
Jeff Moyer 2c91dc
+		size = param.len;
Jeff Moyer 2c91dc
+	else
Jeff Moyer 2c91dc
+		size = cxl_memdev_get_label_size(memdev);
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (cxl_memdev_nvdimm_bridge_active(memdev)) {
Jeff Moyer 2c91dc
+		fprintf(stderr,
Jeff Moyer 2c91dc
+			"%s: has active nvdimm bridge, abort label write\n",
Jeff Moyer 2c91dc
+			cxl_memdev_get_devname(memdev));
Jeff Moyer 2c91dc
+		return -EBUSY;
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	rc = cxl_memdev_zero_label(memdev, size, param.offset);
Jeff Moyer 2c91dc
+	if (rc < 0)
Jeff Moyer 2c91dc
+		fprintf(stderr, "%s: label zeroing failed: %s\n",
Jeff Moyer 2c91dc
+			cxl_memdev_get_devname(memdev), strerror(-rc));
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	return rc;
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+static int action_write(struct cxl_memdev *memdev, struct action_context *actx)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	size_t size = param.len, read_len;
Jeff Moyer 2c91dc
+	unsigned char *buf;
Jeff Moyer 2c91dc
+	int rc;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (cxl_memdev_nvdimm_bridge_active(memdev)) {
Jeff Moyer 2c91dc
+		fprintf(stderr,
Jeff Moyer 2c91dc
+			"%s: has active nvdimm bridge, abort label write\n",
Jeff Moyer 2c91dc
+			cxl_memdev_get_devname(memdev));
Jeff Moyer 2c91dc
+		return -EBUSY;
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (!size) {
Jeff Moyer 2c91dc
+		size_t label_size = cxl_memdev_get_label_size(memdev);
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+		fseek(actx->f_in, 0L, SEEK_END);
Jeff Moyer 2c91dc
+		size = ftell(actx->f_in);
Jeff Moyer 2c91dc
+		fseek(actx->f_in, 0L, SEEK_SET);
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+		if (size > label_size) {
Jeff Moyer 2c91dc
+			fprintf(stderr,
Jeff Moyer 2c91dc
+				"File size (%zu) greater than label area size (%zu), aborting\n",
Jeff Moyer 2c91dc
+				size, label_size);
Jeff Moyer 2c91dc
+			return -EINVAL;
Jeff Moyer 2c91dc
+		}
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	buf = calloc(1, size);
Jeff Moyer 2c91dc
+	if (!buf)
Jeff Moyer 2c91dc
+		return -ENOMEM;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	read_len = fread(buf, 1, size, actx->f_in);
Jeff Moyer 2c91dc
+	if (read_len != size) {
Jeff Moyer 2c91dc
+		rc = -ENXIO;
Jeff Moyer 2c91dc
+		goto out;
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	rc = cxl_memdev_write_label(memdev, buf, size, param.offset);
Jeff Moyer 2c91dc
+	if (rc < 0)
Jeff Moyer 2c91dc
+		fprintf(stderr, "%s: label write failed: %s\n",
Jeff Moyer 2c91dc
+			cxl_memdev_get_devname(memdev), strerror(-rc));
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+out:
Jeff Moyer 2c91dc
+	free(buf);
Jeff Moyer 2c91dc
+	return rc;
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+static int action_read(struct cxl_memdev *memdev, struct action_context *actx)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	size_t size, write_len;
Jeff Moyer 2c91dc
+	char *buf;
Jeff Moyer 2c91dc
+	int rc;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (param.len)
Jeff Moyer 2c91dc
+		size = param.len;
Jeff Moyer 2c91dc
+	else
Jeff Moyer 2c91dc
+		size = cxl_memdev_get_label_size(memdev);
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	buf = calloc(1, size);
Jeff Moyer 2c91dc
+	if (!buf)
Jeff Moyer 2c91dc
+		return -ENOMEM;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	rc = cxl_memdev_read_label(memdev, buf, size, param.offset);
Jeff Moyer 2c91dc
+	if (rc < 0) {
Jeff Moyer 2c91dc
+		fprintf(stderr, "%s: label read failed: %s\n",
Jeff Moyer 2c91dc
+			cxl_memdev_get_devname(memdev), strerror(-rc));
Jeff Moyer 2c91dc
+		goto out;
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	write_len = fwrite(buf, 1, size, actx->f_out);
Jeff Moyer 2c91dc
+	if (write_len != size) {
Jeff Moyer 2c91dc
+		rc = -ENXIO;
Jeff Moyer 2c91dc
+		goto out;
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+	fflush(actx->f_out);
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+out:
Jeff Moyer 2c91dc
+	free(buf);
Jeff Moyer 2c91dc
+	return rc;
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx,
Jeff Moyer 2c91dc
+		int (*action)(struct cxl_memdev *memdev, struct action_context *actx),
Jeff Moyer 2c91dc
+		const struct option *options, const char *usage)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	struct cxl_memdev *memdev, *single = NULL;
Jeff Moyer 2c91dc
+	struct action_context actx = { 0 };
Jeff Moyer 2c91dc
+	int i, rc = 0, count = 0, err = 0;
Jeff Moyer 2c91dc
+	const char * const u[] = {
Jeff Moyer 2c91dc
+		usage,
Jeff Moyer 2c91dc
+		NULL
Jeff Moyer 2c91dc
+	};
Jeff Moyer 2c91dc
+	unsigned long id;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	argc = parse_options(argc, argv, options, u, 0);
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (argc == 0)
Jeff Moyer 2c91dc
+		usage_with_options(u, options);
Jeff Moyer 2c91dc
+	for (i = 0; i < argc; i++) {
Jeff Moyer 2c91dc
+		if (strcmp(argv[i], "all") == 0) {
Jeff Moyer 2c91dc
+			argv[0] = "all";
Jeff Moyer 2c91dc
+			argc = 1;
Jeff Moyer 2c91dc
+			break;
Jeff Moyer 2c91dc
+		}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+		if (sscanf(argv[i], "mem%lu", &id) != 1) {
Jeff Moyer 2c91dc
+			fprintf(stderr, "'%s' is not a valid memdev name\n",
Jeff Moyer 2c91dc
+					argv[i]);
Jeff Moyer 2c91dc
+			err++;
Jeff Moyer 2c91dc
+		}
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (err == argc) {
Jeff Moyer 2c91dc
+		usage_with_options(u, options);
Jeff Moyer 2c91dc
+		return -EINVAL;
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (!param.outfile)
Jeff Moyer 2c91dc
+		actx.f_out = stdout;
Jeff Moyer 2c91dc
+	else {
Jeff Moyer 2c91dc
+		actx.f_out = fopen(param.outfile, "w+");
Jeff Moyer 2c91dc
+		if (!actx.f_out) {
Jeff Moyer 2c91dc
+			fprintf(stderr, "failed to open: %s: (%s)\n",
Jeff Moyer 2c91dc
+					param.outfile, strerror(errno));
Jeff Moyer 2c91dc
+			rc = -errno;
Jeff Moyer 2c91dc
+			goto out;
Jeff Moyer 2c91dc
+		}
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (!param.infile) {
Jeff Moyer 2c91dc
+		actx.f_in = stdin;
Jeff Moyer 2c91dc
+	} else {
Jeff Moyer 2c91dc
+		actx.f_in = fopen(param.infile, "r");
Jeff Moyer 2c91dc
+		if (!actx.f_in) {
Jeff Moyer 2c91dc
+			fprintf(stderr, "failed to open: %s: (%s)\n",
Jeff Moyer 2c91dc
+					param.infile, strerror(errno));
Jeff Moyer 2c91dc
+			rc = -errno;
Jeff Moyer 2c91dc
+			goto out_close_fout;
Jeff Moyer 2c91dc
+		}
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (param.verbose)
Jeff Moyer 2c91dc
+		cxl_set_log_priority(ctx, LOG_DEBUG);
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	rc = 0;
Jeff Moyer 2c91dc
+	err = 0;
Jeff Moyer 2c91dc
+	count = 0;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	for (i = 0; i < argc; i++) {
Jeff Moyer 2c91dc
+		if (sscanf(argv[i], "mem%lu", &id) != 1
Jeff Moyer 2c91dc
+				&& strcmp(argv[i], "all") != 0)
Jeff Moyer 2c91dc
+			continue;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+		cxl_memdev_foreach (ctx, memdev) {
Jeff Moyer 2c91dc
+			if (!util_cxl_memdev_filter(memdev, argv[i]))
Jeff Moyer 2c91dc
+				continue;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+			if (action == action_write) {
Jeff Moyer 2c91dc
+				single = memdev;
Jeff Moyer 2c91dc
+				rc = 0;
Jeff Moyer 2c91dc
+			} else
Jeff Moyer 2c91dc
+				rc = action(memdev, &actx);
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+			if (rc == 0)
Jeff Moyer 2c91dc
+				count++;
Jeff Moyer 2c91dc
+			else if (rc && !err)
Jeff Moyer 2c91dc
+				err = rc;
Jeff Moyer 2c91dc
+		}
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+	rc = err;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (action == action_write) {
Jeff Moyer 2c91dc
+		if (count > 1) {
Jeff Moyer 2c91dc
+			error("write-labels only supports writing a single memdev\n");
Jeff Moyer 2c91dc
+			usage_with_options(u, options);
Jeff Moyer 2c91dc
+			return -EINVAL;
Jeff Moyer 2c91dc
+		} else if (single) {
Jeff Moyer 2c91dc
+			rc = action(single, &actx);
Jeff Moyer 2c91dc
+			if (rc)
Jeff Moyer 2c91dc
+				count = 0;
Jeff Moyer 2c91dc
+		}
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (actx.f_in != stdin)
Jeff Moyer 2c91dc
+		fclose(actx.f_in);
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+ out_close_fout:
Jeff Moyer 2c91dc
+	if (actx.f_out != stdout)
Jeff Moyer 2c91dc
+		fclose(actx.f_out);
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+ out:
Jeff Moyer 2c91dc
+	/*
Jeff Moyer 2c91dc
+	 * count if some actions succeeded, 0 if none were attempted,
Jeff Moyer 2c91dc
+	 * negative error code otherwise.
Jeff Moyer 2c91dc
+	 */
Jeff Moyer 2c91dc
+	if (count > 0)
Jeff Moyer 2c91dc
+		return count;
Jeff Moyer 2c91dc
+	return rc;
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+int cmd_write_labels(int argc, const char **argv, struct cxl_ctx *ctx)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	int count = memdev_action(argc, argv, ctx, action_write, write_options,
Jeff Moyer 2c91dc
+			"cxl write-labels <memdev> [-i <filename>]");
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	fprintf(stderr, "wrote %d mem%s\n", count >= 0 ? count : 0,
Jeff Moyer 2c91dc
+			count > 1 ? "s" : "");
Jeff Moyer 2c91dc
+	return count >= 0 ? 0 : EXIT_FAILURE;
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+int cmd_read_labels(int argc, const char **argv, struct cxl_ctx *ctx)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	int count = memdev_action(argc, argv, ctx, action_read, read_options,
Jeff Moyer 2c91dc
+			"cxl read-labels <mem0> [<mem1>..<memN>] [-o <filename>]");
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	fprintf(stderr, "read %d mem%s\n", count >= 0 ? count : 0,
Jeff Moyer 2c91dc
+			count > 1 ? "s" : "");
Jeff Moyer 2c91dc
+	return count >= 0 ? 0 : EXIT_FAILURE;
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+int cmd_zero_labels(int argc, const char **argv, struct cxl_ctx *ctx)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	int count = memdev_action(argc, argv, ctx, action_zero, zero_options,
Jeff Moyer 2c91dc
+			"cxl zero-labels <mem0> [<mem1>..<memN>] [<options>]");
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	fprintf(stderr, "zeroed %d mem%s\n", count >= 0 ? count : 0,
Jeff Moyer 2c91dc
+			count > 1 ? "s" : "");
Jeff Moyer 2c91dc
+	return count >= 0 ? 0 : EXIT_FAILURE;
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
-- 
Jeff Moyer 2c91dc
2.27.0
Jeff Moyer 2c91dc