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