Similar to ndctl {enable|disable}-region it may be useful to disable and
re-enable a dimm.  This refreshes the kernel's cached copy of a namespace
label, provided that any regions that the dimm contributes to have also been
disabled.

Cc: Vishal Verma <[email protected]>
Signed-off-by: Dan Williams <[email protected]>
---
 Documentation/Makefile.am            |    4 +
 Documentation/dimm-description.txt   |   15 ++++
 Documentation/ndctl-disable-dimm.txt |   22 +++++++
 Documentation/ndctl-enable-dimm.txt  |   22 +++++++
 Documentation/xable-dimm-options.txt |    9 +++
 ndctl/Makefile.am                    |    1 
 ndctl/builtin-xable-dimm.c           |  115 ++++++++++++++++++++++++++++++++++
 ndctl/builtin.h                      |    2 +
 ndctl/ndctl.c                        |    2 +
 9 files changed, 192 insertions(+)
 create mode 100644 Documentation/dimm-description.txt
 create mode 100644 Documentation/ndctl-disable-dimm.txt
 create mode 100644 Documentation/ndctl-enable-dimm.txt
 create mode 100644 Documentation/xable-dimm-options.txt
 create mode 100644 ndctl/builtin-xable-dimm.c

diff --git a/Documentation/Makefile.am b/Documentation/Makefile.am
index f0593e4fc7eb..63ef1ce7f2d7 100644
--- a/Documentation/Makefile.am
+++ b/Documentation/Makefile.am
@@ -4,6 +4,8 @@ man1_MANS = \
        ndctl-read-labels.1 \
        ndctl-enable-region.1 \
        ndctl-disable-region.1 \
+       ndctl-enable-dimm.1 \
+       ndctl-disable-dimm.1 \
        ndctl-enable-namespace.1 \
        ndctl-disable-namespace.1 \
        ndctl-create-namespace.1 \
@@ -17,6 +19,8 @@ XML_DEPS = \
        Makefile \
        region-description.txt \
        xable-region-options.txt \
+       dimm-description.txt \
+       xable-dimm-options.txt \
        xable-namespace-options.txt \
        labels-description.txt \
        labels-options.txt
diff --git a/Documentation/dimm-description.txt 
b/Documentation/dimm-description.txt
new file mode 100644
index 000000000000..95d0891c0b13
--- /dev/null
+++ b/Documentation/dimm-description.txt
@@ -0,0 +1,15 @@
+DESCRIPTION
+-----------
+A generic DIMM device object, named /dev/nmemX, is registered for each
+memory device indicated in the ACPI NFIT table, or other platform NVDIMM
+resource discovery mechanism.  The LIBNVDIMM core provides a built-in
+driver for these DIMM devices.  The driver is responsible for
+determining if the DIMM implements a namespace label area, and
+initializing the kernel's in-memory copy of that label data.
+
+The kernel performs runtime modifications of that data when namespace
+provisioning actions are taken, and actively blocks userspace from
+initiating label data changes while the DIMM is active in any region.
+Disabling a DIMM, after all the regions it is a member of have been
+disabled, allows userspace to manually update the label data to be
+consumed when the DIMM is next enabled.
diff --git a/Documentation/ndctl-disable-dimm.txt 
b/Documentation/ndctl-disable-dimm.txt
new file mode 100644
index 000000000000..b87314ffd197
--- /dev/null
+++ b/Documentation/ndctl-disable-dimm.txt
@@ -0,0 +1,22 @@
+ndctl-disable-dimm(1)
+=======================
+
+NAME
+----
+ndctl-disable-dimm - disable one or more idle dimms
+
+SYNOPSIS
+--------
+[verse]
+'ndctl disable-dimm' <dimm> [<options>]
+
+include::dimm-description.txt[]
+
+OPTIONS
+-------
+<dimm>::
+include::xable-dimm-options.txt[]
+
+SEE ALSO
+--------
+linkndctl:ndctl-enable-dimm[1]
diff --git a/Documentation/ndctl-enable-dimm.txt 
b/Documentation/ndctl-enable-dimm.txt
new file mode 100644
index 000000000000..0b0c6e0c965e
--- /dev/null
+++ b/Documentation/ndctl-enable-dimm.txt
@@ -0,0 +1,22 @@
+ndctl-enable-dimm(1)
+====================
+
+NAME
+----
+ndctl-enable-dimm - enable one more dimms
+
+SYNOPSIS
+--------
+[verse]
+'ndctl enable-dimm' <dimm> [<options>]
+
+include::dimm-description.txt[]
+
+OPTIONS
+-------
+<dimm>::
+include::xable-dimm-options.txt[]
+
+SEE ALSO
+--------
+linkndctl:ndctl-disable-dimm[1]
diff --git a/Documentation/xable-dimm-options.txt 
b/Documentation/xable-dimm-options.txt
new file mode 100644
index 000000000000..ad79208a61eb
--- /dev/null
+++ b/Documentation/xable-dimm-options.txt
@@ -0,0 +1,9 @@
+       A 'nmemX' device name, or a dimm id number. The keyword 'all' can
+       be specified to carry out the operation on every dimm in the system,
+       optionally filtered by bus id (see --bus= option).
+
+-b::
+--bus=::
+       Enforce that the operation only be carried on devices that are
+       attached to the given bus. Where 'bus' can be a provider name or a bus
+       id number.
diff --git a/ndctl/Makefile.am b/ndctl/Makefile.am
index 04f3a63ff999..f7d0a96af4f9 100644
--- a/ndctl/Makefile.am
+++ b/ndctl/Makefile.am
@@ -39,6 +39,7 @@ ndctl_SOURCES = ndctl.c \
                builtin-create-nfit.c \
                builtin-xaction-namespace.c \
                builtin-xable-region.c \
+               builtin-xable-dimm.c \
                builtin-list.c \
                builtin-test.c \
                builtin-help.c \
diff --git a/ndctl/builtin-xable-dimm.c b/ndctl/builtin-xable-dimm.c
new file mode 100644
index 000000000000..4bdbc7f8eea3
--- /dev/null
+++ b/ndctl/builtin-xable-dimm.c
@@ -0,0 +1,115 @@
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <util/filter.h>
+#include <util/parse-options.h>
+#include <ndctl/libndctl.h>
+
+static const char *dimm_bus;
+
+static const struct option dimm_options[] = {
+       OPT_STRING('b', "bus", &dimm_bus, "bus-id",
+                       "<dimm> must be on a bus with an id/provider of 
<bus-id>"),
+       OPT_END(),
+};
+
+static const char *parse_dimm_options(int argc, const char **argv,
+               char *xable_usage)
+{
+       const char * const u[] = {
+               xable_usage,
+               NULL
+       };
+       int i;
+
+        argc = parse_options(argc, argv, dimm_options, u, 0);
+
+       if (argc == 0)
+               error("specify a dimm to disable, or \"all\"\n");
+       for (i = 1; i < argc; i++)
+               error("unknown extra parameter \"%s\"\n", argv[i]);
+       if (argc == 0 || argc > 1) {
+               usage_with_options(u, dimm_options);
+               return NULL; /* we won't return from usage_with_options() */
+       }
+       return argv[0];
+}
+
+static int do_xable_dimm(const char *dimm_arg,
+               int (*xable_fn)(struct ndctl_dimm *), struct ndctl_ctx *ctx)
+{
+       int rc = -ENXIO, skip = 0, success = 0;
+       struct ndctl_dimm *dimm;
+       struct ndctl_bus *bus;
+
+       if (!dimm_arg)
+               goto out;
+
+        ndctl_bus_foreach(ctx, bus) {
+               if (!util_bus_filter(bus, dimm_bus))
+                       continue;
+
+               ndctl_dimm_foreach(bus, dimm) {
+                       if (!util_dimm_filter(dimm, dimm_arg))
+                               continue;
+                       if (xable_fn == ndctl_dimm_disable
+                                       && ndctl_dimm_is_active(dimm)) {
+                               fprintf(stderr, "%s is active, skipping...\n",
+                                               ndctl_dimm_get_devname(dimm));
+                               skip++;
+                               continue;
+                       }
+                       if (xable_fn(dimm) == 0)
+                               success++;
+               }
+       }
+
+       rc = success;
+       if (!success && skip)
+               rc = EBUSY;
+ out:
+       dimm_bus = NULL;
+       return rc;
+}
+
+int cmd_disable_dimm(int argc, const char **argv, struct ndctl_ctx *ctx)
+{
+       char *xable_usage = "ndctl disable-dimm <dimm> [<options>]";
+       const char *dimm = parse_dimm_options(argc, argv, xable_usage);
+       int disabled = do_xable_dimm(dimm, ndctl_dimm_disable,
+                       ctx);
+
+       if (disabled < 0) {
+               fprintf(stderr, "error disabling dimms: %s\n",
+                               strerror(-disabled));
+               return disabled;
+       } else if (disabled == 0) {
+               fprintf(stderr, "disabled 0 dimms\n");
+               return 0;
+       } else {
+               fprintf(stderr, "disabled %d dimm%s\n", disabled,
+                               disabled > 1 ? "s" : "");
+               return 0;
+       }
+}
+
+int cmd_enable_dimm(int argc, const char **argv, struct ndctl_ctx *ctx)
+{
+       char *xable_usage = "ndctl enable-dimm <dimm> [<options>]";
+       const char *dimm = parse_dimm_options(argc, argv, xable_usage);
+       int enabled = do_xable_dimm(dimm, ndctl_dimm_enable, ctx);
+
+       if (enabled < 0) {
+               fprintf(stderr, "error enabling dimms: %s\n",
+                               strerror(-enabled));
+               return enabled;
+       } else if (enabled == 0) {
+               fprintf(stderr, "enabled 0 dimms\n");
+               return 0;
+       } else {
+               fprintf(stderr, "enabled %d dimm%s\n", enabled,
+                               enabled > 1 ? "s" : "");
+               return 0;
+       }
+}
diff --git a/ndctl/builtin.h b/ndctl/builtin.h
index 46cd5d2d439c..ec55865ecea8 100644
--- a/ndctl/builtin.h
+++ b/ndctl/builtin.h
@@ -16,6 +16,8 @@ int cmd_destroy_namespace(int argc, const char **argv, struct 
ndctl_ctx *ctx);
 int cmd_disable_namespace(int argc, const char **argv, struct ndctl_ctx *ctx);
 int cmd_enable_region(int argc, const char **argv, struct ndctl_ctx *ctx);
 int cmd_disable_region(int argc, const char **argv, struct ndctl_ctx *ctx);
+int cmd_enable_dimm(int argc, const char **argv, struct ndctl_ctx *ctx);
+int cmd_disable_dimm(int argc, const char **argv, struct ndctl_ctx *ctx);
 int cmd_zero_labels(int argc, const char **argv, struct ndctl_ctx *ctx);
 int cmd_read_labels(int argc, const char **argv, struct ndctl_ctx *ctx);
 int cmd_list(int argc, const char **argv, struct ndctl_ctx *ctx);
diff --git a/ndctl/ndctl.c b/ndctl/ndctl.c
index 77f90d6087ba..aaeb3f7c2bec 100644
--- a/ndctl/ndctl.c
+++ b/ndctl/ndctl.c
@@ -32,6 +32,8 @@ static struct cmd_struct commands[] = {
        { "destroy-namespace", cmd_destroy_namespace },
        { "enable-region", cmd_enable_region },
        { "disable-region", cmd_disable_region },
+       { "enable-dimm", cmd_enable_dimm },
+       { "disable-dimm", cmd_disable_dimm },
        { "zero-labels", cmd_zero_labels },
        { "read-labels", cmd_read_labels },
        { "list", cmd_list },

_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm

Reply via email to