All of lore.kernel.org
 help / color / mirror / Atom feed
* [ndctl PATCH 0/7] ndctl: automatically initialize labels
@ 2017-08-29 20:01 Dan Williams
  2017-08-29 20:01 ` [ndctl PATCH 1/7] ndctl, init-labels: fix '--label-version' option Dan Williams
                   ` (6 more replies)
  0 siblings, 7 replies; 12+ messages in thread
From: Dan Williams @ 2017-08-29 20:01 UTC (permalink / raw)
  To: linux-nvdimm

The QEMU-KVM enabling for a virtual NVDIMM is an example of a
configuration where label-less namespaces are created by default. I.e.
the ACPI NFIT produced by SeaBIOS publishes un-aliased pmem regions. The
first operation an administrator is likely to perform is to reconfigure
the namespace into "memory" mode to enable full-featured DAX support.

The reconfiguration of the label-less namespace into "memory" mode is an
opportunity to also enable labels. This series effectively runs the
following sequence:

    ndctl disable-region all
    ndctl init-labels
    ndctl enabled-region all

...in 'create-namespace' whenever a label-less namespace is encountered.
The implementation is careful to try v1.2 labels and validate that the
kernel supports that scheme. Otherwise, it falls back to v1.1 labels.

For other utilities built on top of libndctl, the following new helpers
are provided to enable a similar flow:

    ndctl_dimm_read_labels()
    ndctl_dimm_validate_labels()
    ndctl_dimm_init_labels()

...where 'read_labels' enables the other apis, 'validate_labels' checks
whether the data retrieved from the read corresponds to a valid set of
namespace label index blocks, and 'init_labels' writes namespace index
blocks to the dimm. In order to check that the kernel supports a given
index block version / format the result from
ndctl_dimm_get_available_labels() can be compared to the result from
ndctl_dimm_init_labels() to make sure the kernel sees the same number of
available slots as userspace.

---

Dan Williams (7):
      ndctl, init-labels: fix '--label-version' option
      ndctl: drop the "libndctl-" prefix on library source files
      ndctl: move label manipulation routines to their own file
      ndctl: consolidate namespace definitions in namespace.h
      ndctl: refactor read_labels() helper into a library call
      ndctl: introduce ndctl_dimm_{validate_labels,init_labels}
      ndctl: auto initialize labels


 Documentation/ndctl/ndctl-create-namespace.txt |    7 
 Makefile.am                                    |    1 
 ndctl/check.c                                  |   52 ++
 ndctl/check.h                                  |  130 ------
 ndctl/dimm.c                                   |  547 +----------------------
 ndctl/lib/Makefile.am                          |   11 
 ndctl/lib/ars.c                                |    2 
 ndctl/lib/dimm.c                               |  565 ++++++++++++++++++++++++
 ndctl/lib/hpe1.c                               |    4 
 ndctl/lib/hpe1.h                               |    0 
 ndctl/lib/libndctl.c                           |  154 -------
 ndctl/lib/libndctl.sym                         |    4 
 ndctl/lib/msft.c                               |    4 
 ndctl/lib/msft.h                               |    0 
 ndctl/lib/private.h                            |  151 +++---
 ndctl/lib/smart.c                              |    2 
 ndctl/libndctl.h.in                            |    9 
 ndctl/namespace.c                              |  101 ++++
 ndctl/namespace.h                              |  163 +++++++
 util/fletcher.c                                |   35 -
 util/fletcher.h                                |   19 +
 21 files changed, 1021 insertions(+), 940 deletions(-)
 delete mode 100644 ndctl/check.h
 rename ndctl/lib/{libndctl-ars.c => ars.c} (99%)
 create mode 100644 ndctl/lib/dimm.c
 rename ndctl/lib/{libndctl-hpe1.c => hpe1.c} (99%)
 rename ndctl/lib/{ndctl-hpe1.h => hpe1.h} (100%)
 rename ndctl/lib/{libndctl-msft.c => msft.c} (98%)
 rename ndctl/lib/{ndctl-msft.h => msft.h} (100%)
 rename ndctl/lib/{libndctl-private.h => private.h} (69%)
 rename ndctl/lib/{libndctl-smart.c => smart.c} (99%)
 create mode 100644 ndctl/namespace.h
 delete mode 100644 util/fletcher.c
_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [ndctl PATCH 1/7] ndctl, init-labels: fix '--label-version' option
  2017-08-29 20:01 [ndctl PATCH 0/7] ndctl: automatically initialize labels Dan Williams
@ 2017-08-29 20:01 ` Dan Williams
  2017-08-29 20:01 ` [ndctl PATCH 2/7] ndctl: drop the "libndctl-" prefix on library source files Dan Williams
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 12+ messages in thread
From: Dan Williams @ 2017-08-29 20:01 UTC (permalink / raw)
  To: linux-nvdimm

Kill the unnecessary double-dash characters in the definition of the
long option.

Cc: Vishal Verma <vishal.l.verma@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 ndctl/dimm.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ndctl/dimm.c b/ndctl/dimm.c
index 264917d05cc0..ee3b9979fa8c 100644
--- a/ndctl/dimm.c
+++ b/ndctl/dimm.c
@@ -952,7 +952,7 @@ OPT_STRING('i', "input", &param.infile, "input-file", \
 #define INIT_OPTIONS() \
 OPT_BOOLEAN('f', "force", &param.force, \
 		"force initialization even if existing index-block present"), \
-OPT_STRING('V', "--label-version", &param.labelversion, "version-number", \
+OPT_STRING('V', "label-version", &param.labelversion, "version-number", \
 	"namespace label specification version (default: 1.1)")
 
 static const struct option read_options[] = {

_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [ndctl PATCH 2/7] ndctl: drop the "libndctl-" prefix on library source files
  2017-08-29 20:01 [ndctl PATCH 0/7] ndctl: automatically initialize labels Dan Williams
  2017-08-29 20:01 ` [ndctl PATCH 1/7] ndctl, init-labels: fix '--label-version' option Dan Williams
@ 2017-08-29 20:01 ` Dan Williams
  2017-08-29 20:01 ` [ndctl PATCH 3/7] ndctl: move label manipulation routines to their own file Dan Williams
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 12+ messages in thread
From: Dan Williams @ 2017-08-29 20:01 UTC (permalink / raw)
  To: linux-nvdimm

The "libndctl-" prefix is redundant given the source files already live
in the ndctl/lib/ directory. There is a similar story for removing the
"ndctl-" prefix on the vendor-specific / internal-only headers.

Cc: Vishal Verma <vishal.l.verma@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 ndctl/lib/Makefile.am        |   10 +++++-----
 ndctl/lib/ars.c              |    2 +-
 ndctl/lib/hpe1.c             |    4 ++--
 ndctl/lib/hpe1.h             |    0 
 ndctl/lib/libndctl.c         |    2 +-
 ndctl/lib/msft.c             |    4 ++--
 ndctl/lib/msft.h             |    0 
 ndctl/lib/private.h          |    4 ++--
 ndctl/lib/smart.c            |    2 +-
 9 files changed, 14 insertions(+), 14 deletions(-)
 rename ndctl/lib/{libndctl-ars.c => ars.c} (99%)
 rename ndctl/lib/{libndctl-hpe1.c => hpe1.c} (99%)
 rename ndctl/lib/{ndctl-hpe1.h => hpe1.h} (100%)
 rename ndctl/lib/{libndctl-msft.c => msft.c} (98%)
 rename ndctl/lib/{ndctl-msft.h => msft.h} (100%)
 rename ndctl/lib/{libndctl-private.h => private.h} (99%)
 rename ndctl/lib/{libndctl-smart.c => smart.c} (99%)

diff --git a/ndctl/lib/Makefile.am b/ndctl/lib/Makefile.am
index 7a446be295bb..0f01b7d88007 100644
--- a/ndctl/lib/Makefile.am
+++ b/ndctl/lib/Makefile.am
@@ -12,7 +12,7 @@ lib_LTLIBRARIES = libndctl.la
 
 libndctl_la_SOURCES =\
 	libndctl.h \
-	libndctl-private.h \
+	private.h \
 	../../util/log.c \
 	../../util/log.h \
 	../../util/sysfs.c \
@@ -26,13 +26,13 @@ libndctl_la_LIBADD =\
 	$(KMOD_LIBS)
 
 if ENABLE_ARS
-libndctl_la_SOURCES += libndctl-ars.c
+libndctl_la_SOURCES += ars.c
 endif
 
 if ENABLE_SMART
-libndctl_la_SOURCES += libndctl-smart.c
-libndctl_la_SOURCES += libndctl-hpe1.c
-libndctl_la_SOURCES += libndctl-msft.c
+libndctl_la_SOURCES += smart.c
+libndctl_la_SOURCES += hpe1.c
+libndctl_la_SOURCES += msft.c
 endif
 
 EXTRA_DIST += libndctl.sym
diff --git a/ndctl/lib/libndctl-ars.c b/ndctl/lib/ars.c
similarity index 99%
rename from ndctl/lib/libndctl-ars.c
rename to ndctl/lib/ars.c
index 9b1a0cb6e1d6..735c1457a3ec 100644
--- a/ndctl/lib/libndctl-ars.c
+++ b/ndctl/lib/ars.c
@@ -12,7 +12,7 @@
  */
 #include <stdlib.h>
 #include <ndctl/libndctl.h>
-#include "libndctl-private.h"
+#include "private.h"
 
 NDCTL_EXPORT struct ndctl_cmd *ndctl_bus_cmd_new_ars_cap(struct ndctl_bus *bus,
 		unsigned long long address, unsigned long long len)
diff --git a/ndctl/lib/libndctl-hpe1.c b/ndctl/lib/hpe1.c
similarity index 99%
rename from ndctl/lib/libndctl-hpe1.c
rename to ndctl/lib/hpe1.c
index ec542527e509..45cb5cc6db73 100644
--- a/ndctl/lib/libndctl-hpe1.c
+++ b/ndctl/lib/hpe1.c
@@ -15,9 +15,9 @@
 #include <limits.h>
 #include <util/log.h>
 #include <ndctl/libndctl.h>
-#include "libndctl-private.h"
+#include "private.h"
 
-#include "ndctl-hpe1.h"
+#include "hpe1.h"
 
 #define CMD_HPE1(_c) ((_c)->hpe1)
 #define CMD_HPE1_SMART(_c) (CMD_HPE1(_c)->u.smart.data)
diff --git a/ndctl/lib/ndctl-hpe1.h b/ndctl/lib/hpe1.h
similarity index 100%
rename from ndctl/lib/ndctl-hpe1.h
rename to ndctl/lib/hpe1.h
diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
index c2e0efbd87b0..4c0f8a7afd57 100644
--- a/ndctl/lib/libndctl.c
+++ b/ndctl/lib/libndctl.c
@@ -37,7 +37,7 @@
 #include <util/sysfs.h>
 #include <ndctl/libndctl.h>
 #include <daxctl/libdaxctl.h>
-#include "libndctl-private.h"
+#include "private.h"
 
 static uuid_t null_uuid;
 
diff --git a/ndctl/lib/libndctl-msft.c b/ndctl/lib/msft.c
similarity index 98%
rename from ndctl/lib/libndctl-msft.c
rename to ndctl/lib/msft.c
index d46f79bb534d..8c226f5602f1 100644
--- a/ndctl/lib/libndctl-msft.c
+++ b/ndctl/lib/msft.c
@@ -16,8 +16,8 @@
 #include <limits.h>
 #include <util/log.h>
 #include <ndctl/libndctl.h>
-#include "libndctl-private.h"
-#include "ndctl-msft.h"
+#include "private.h"
+#include "msft.h"
 
 #define CMD_MSFT(_c) ((_c)->msft)
 #define CMD_MSFT_SMART(_c) (CMD_MSFT(_c)->u.smart.data)
diff --git a/ndctl/lib/ndctl-msft.h b/ndctl/lib/msft.h
similarity index 100%
rename from ndctl/lib/ndctl-msft.h
rename to ndctl/lib/msft.h
diff --git a/ndctl/lib/libndctl-private.h b/ndctl/lib/private.h
similarity index 99%
rename from ndctl/lib/libndctl-private.h
rename to ndctl/lib/private.h
index 8f10fbc76aca..8bc730d4b39a 100644
--- a/ndctl/lib/libndctl-private.h
+++ b/ndctl/lib/private.h
@@ -31,8 +31,8 @@
 #include <ndctl/libndctl.h>
 #include <ccan/endian/endian.h>
 #include <ccan/short_types/short_types.h>
-#include "ndctl-hpe1.h"
-#include "ndctl-msft.h"
+#include "hpe1.h"
+#include "msft.h"
 
 #define SZ_16M 0x01000000
 
diff --git a/ndctl/lib/libndctl-smart.c b/ndctl/lib/smart.c
similarity index 99%
rename from ndctl/lib/libndctl-smart.c
rename to ndctl/lib/smart.c
index 73a49efe5d58..41bbc6f93b80 100644
--- a/ndctl/lib/libndctl-smart.c
+++ b/ndctl/lib/smart.c
@@ -14,7 +14,7 @@
 #include <limits.h>
 #include <util/log.h>
 #include <ndctl/libndctl.h>
-#include "libndctl-private.h"
+#include "private.h"
 
 /*
  * Define the wrappers around the ndctl_smart_ops:

_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [ndctl PATCH 3/7] ndctl: move label manipulation routines to their own file
  2017-08-29 20:01 [ndctl PATCH 0/7] ndctl: automatically initialize labels Dan Williams
  2017-08-29 20:01 ` [ndctl PATCH 1/7] ndctl, init-labels: fix '--label-version' option Dan Williams
  2017-08-29 20:01 ` [ndctl PATCH 2/7] ndctl: drop the "libndctl-" prefix on library source files Dan Williams
@ 2017-08-29 20:01 ` Dan Williams
  2017-08-29 20:01 ` [ndctl PATCH 4/7] ndctl: consolidate namespace definitions in namespace.h Dan Williams
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 12+ messages in thread
From: Dan Williams @ 2017-08-29 20:01 UTC (permalink / raw)
  To: linux-nvdimm

In anticipation of pushing label functionality into the library move the
existing ndctl_dimm_zero_labels() into a new ndctl/lib/dimm.c source
file.

Cc: Vishal Verma <vishal.l.verma@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 ndctl/lib/Makefile.am |    1 
 ndctl/lib/dimm.c      |  106 ++++++++++++++++++++++++++++++++++++
 ndctl/lib/libndctl.c  |  145 -------------------------------------------------
 ndctl/lib/private.h   |   57 +++++++++++++++++++
 4 files changed, 164 insertions(+), 145 deletions(-)
 create mode 100644 ndctl/lib/dimm.c

diff --git a/ndctl/lib/Makefile.am b/ndctl/lib/Makefile.am
index 0f01b7d88007..d8df87d13df3 100644
--- a/ndctl/lib/Makefile.am
+++ b/ndctl/lib/Makefile.am
@@ -17,6 +17,7 @@ libndctl_la_SOURCES =\
 	../../util/log.h \
 	../../util/sysfs.c \
 	../../util/sysfs.h \
+	dimm.c \
 	libndctl.c
 
 libndctl_la_LIBADD =\
diff --git a/ndctl/lib/dimm.c b/ndctl/lib/dimm.c
new file mode 100644
index 000000000000..1c613a470099
--- /dev/null
+++ b/ndctl/lib/dimm.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2014-2017, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
+ * more details.
+ */
+#include <ndctl/libndctl.h>
+#include <util/sysfs.h>
+#include <stdlib.h>
+#include "private.h"
+
+NDCTL_EXPORT int ndctl_dimm_zero_labels(struct ndctl_dimm *dimm)
+{
+	struct ndctl_cmd *cmd_size, *cmd_read, *cmd_write;
+	struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
+	struct ndctl_bus *bus = ndctl_dimm_get_bus(dimm);
+	int rc;
+
+	rc = ndctl_bus_wait_probe(bus);
+	if (rc < 0)
+		return rc;
+
+	if (ndctl_dimm_is_active(dimm)) {
+		dbg(ctx, "%s: regions active, abort label write\n",
+			ndctl_dimm_get_devname(dimm));
+		return -EBUSY;
+	}
+
+	cmd_size = ndctl_dimm_cmd_new_cfg_size(dimm);
+	if (!cmd_size)
+		return -ENOTTY;
+	rc = ndctl_cmd_submit(cmd_size);
+	if (rc || ndctl_cmd_get_firmware_status(cmd_size))
+		goto out_size;
+
+	cmd_read = ndctl_dimm_cmd_new_cfg_read(cmd_size);
+	if (!cmd_read) {
+		rc = -ENOTTY;
+		goto out_size;
+	}
+	rc = ndctl_cmd_submit(cmd_read);
+	if (rc || ndctl_cmd_get_firmware_status(cmd_read))
+		goto out_read;
+
+	cmd_write = ndctl_dimm_cmd_new_cfg_write(cmd_read);
+	if (!cmd_write) {
+		rc = -ENOTTY;
+		goto out_read;
+	}
+	if (ndctl_cmd_cfg_write_zero_data(cmd_write) < 0) {
+		rc = -ENXIO;
+		goto out_write;
+	}
+	rc = ndctl_cmd_submit(cmd_write);
+	if (rc || ndctl_cmd_get_firmware_status(cmd_write))
+		goto out_write;
+
+	/*
+	 * If the dimm is already disabled the kernel is not holding a cached
+	 * copy of the label space.
+	 */
+	if (!ndctl_dimm_is_enabled(dimm))
+		goto out_write;
+
+	rc = ndctl_dimm_disable(dimm);
+	if (rc)
+		goto out_write;
+	rc = ndctl_dimm_enable(dimm);
+
+ out_write:
+	ndctl_cmd_unref(cmd_write);
+ out_read:
+	ndctl_cmd_unref(cmd_read);
+ out_size:
+	ndctl_cmd_unref(cmd_size);
+
+	return rc;
+}
+
+NDCTL_EXPORT unsigned long ndctl_dimm_get_available_labels(
+		struct ndctl_dimm *dimm)
+{
+	struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
+	char *path = dimm->dimm_buf;
+	int len = dimm->buf_len;
+	char buf[20];
+
+	if (snprintf(path, len, "%s/available_slots", dimm->dimm_path) >= len) {
+		err(ctx, "%s: buffer too small!\n",
+				ndctl_dimm_get_devname(dimm));
+		return ULONG_MAX;
+	}
+
+	if (sysfs_read_attr(ctx, path, buf) < 0)
+		return ULONG_MAX;
+
+	return strtoul(buf, NULL, 0);
+}
+
+
diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
index 4c0f8a7afd57..f93ba9b8de76 100644
--- a/ndctl/lib/libndctl.c
+++ b/ndctl/lib/libndctl.c
@@ -105,63 +105,6 @@ struct ndctl_bus {
 };
 
 /**
- * struct ndctl_dimm - memory device as identified by NFIT
- * @module: kernel module (libnvdimm)
- * @handle: NFIT-handle value
- * @major: /dev/nmemX major character device number
- * @minor: /dev/nmemX minor character device number
- * @phys_id: SMBIOS physical id
- * @vendor_id: hardware component vendor
- * @device_id: hardware device id
- * @revision_id: hardware revision id
- * @node: system node-id
- * @socket: socket-id in the node
- * @imc: memory-controller-id in the socket
- * @channel: channel-id in the memory-controller
- * @dimm: dimm-id in the channel
- * @formats: number of support interfaces
- * @format: array of format interface code numbers
- */
-struct ndctl_dimm {
-	struct kmod_module *module;
-	struct ndctl_bus *bus;
-	struct ndctl_smart_ops *smart_ops;
-	unsigned int handle, major, minor, serial;
-	unsigned short phys_id;
-	unsigned short vendor_id;
-	unsigned short device_id;
-	unsigned short revision_id;
-	unsigned short subsystem_vendor_id;
-	unsigned short subsystem_device_id;
-	unsigned short subsystem_revision_id;
-	unsigned short manufacturing_date;
-	unsigned char manufacturing_location;
-	unsigned long dsm_family;
-	unsigned long dsm_mask;
-	char *unique_id;
-	char *dimm_path;
-	char *dimm_buf;
-	int health_eventfd;
-	int buf_len;
-	int id;
-	union dimm_flags {
-		unsigned long flags;
-		struct {
-			unsigned int f_map:1;
-			unsigned int f_arm:1;
-			unsigned int f_save:1;
-			unsigned int f_flush:1;
-			unsigned int f_smart:1;
-			unsigned int f_restore:1;
-			unsigned int f_notify:1;
-		};
-	} flags;
-	struct list_node list;
-	int formats;
-	int format[0];
-};
-
-/**
  * struct ndctl_mapping - dimm extent relative to a region
  * @dimm: backing dimm for the mapping
  * @offset: dimm relative offset
@@ -2214,74 +2157,6 @@ NDCTL_EXPORT ssize_t ndctl_cmd_cfg_write_zero_data(struct ndctl_cmd *cfg_write)
 	return cfg_write->iter.total_xfer;
 }
 
-NDCTL_EXPORT int ndctl_dimm_zero_labels(struct ndctl_dimm *dimm)
-{
-	struct ndctl_cmd *cmd_size, *cmd_read, *cmd_write;
-	struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
-	struct ndctl_bus *bus = ndctl_dimm_get_bus(dimm);
-	int rc;
-
-	rc = ndctl_bus_wait_probe(bus);
-	if (rc < 0)
-		return rc;
-
-	if (ndctl_dimm_is_active(dimm)) {
-		dbg(ctx, "%s: regions active, abort label write\n",
-			ndctl_dimm_get_devname(dimm));
-		return -EBUSY;
-	}
-
-	cmd_size = ndctl_dimm_cmd_new_cfg_size(dimm);
-	if (!cmd_size)
-		return -ENOTTY;
-	rc = ndctl_cmd_submit(cmd_size);
-	if (rc || ndctl_cmd_get_firmware_status(cmd_size))
-		goto out_size;
-
-	cmd_read = ndctl_dimm_cmd_new_cfg_read(cmd_size);
-	if (!cmd_read) {
-		rc = -ENOTTY;
-		goto out_size;
-	}
-	rc = ndctl_cmd_submit(cmd_read);
-	if (rc || ndctl_cmd_get_firmware_status(cmd_read))
-		goto out_read;
-
-	cmd_write = ndctl_dimm_cmd_new_cfg_write(cmd_read);
-	if (!cmd_write) {
-		rc = -ENOTTY;
-		goto out_read;
-	}
-	if (ndctl_cmd_cfg_write_zero_data(cmd_write) < 0) {
-		rc = -ENXIO;
-		goto out_write;
-	}
-	rc = ndctl_cmd_submit(cmd_write);
-	if (rc || ndctl_cmd_get_firmware_status(cmd_write))
-		goto out_write;
-
-	/*
-	 * If the dimm is already disabled the kernel is not holding a cached
-	 * copy of the label space.
-	 */
-	if (!ndctl_dimm_is_enabled(dimm))
-		goto out_write;
-
-	rc = ndctl_dimm_disable(dimm);
-	if (rc)
-		goto out_write;
-	rc = ndctl_dimm_enable(dimm);
-
- out_write:
-	ndctl_cmd_unref(cmd_write);
- out_read:
-	ndctl_cmd_unref(cmd_read);
- out_size:
-	ndctl_cmd_unref(cmd_size);
-
-	return rc;
-}
-
 NDCTL_EXPORT void ndctl_cmd_unref(struct ndctl_cmd *cmd)
 {
 	if (!cmd)
@@ -2645,26 +2520,6 @@ NDCTL_EXPORT int ndctl_dimm_is_active(struct ndctl_dimm *dimm)
 	return 0;
 }
 
-NDCTL_EXPORT unsigned long ndctl_dimm_get_available_labels(
-		struct ndctl_dimm *dimm)
-{
-	struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
-	char *path = dimm->dimm_buf;
-	int len = dimm->buf_len;
-	char buf[20];
-
-	if (snprintf(path, len, "%s/available_slots", dimm->dimm_path) >= len) {
-		err(ctx, "%s: buffer too small!\n",
-				ndctl_dimm_get_devname(dimm));
-		return ULONG_MAX;
-	}
-
-	if (sysfs_read_attr(ctx, path, buf) < 0)
-		return ULONG_MAX;
-
-	return strtoul(buf, NULL, 0);
-}
-
 NDCTL_EXPORT int ndctl_interleave_set_is_active(
 		struct ndctl_interleave_set *iset)
 {
diff --git a/ndctl/lib/private.h b/ndctl/lib/private.h
index 8bc730d4b39a..12e3102150fd 100644
--- a/ndctl/lib/private.h
+++ b/ndctl/lib/private.h
@@ -34,6 +34,63 @@
 #include "hpe1.h"
 #include "msft.h"
 
+/**
+ * struct ndctl_dimm - memory device as identified by NFIT
+ * @module: kernel module (libnvdimm)
+ * @handle: NFIT-handle value
+ * @major: /dev/nmemX major character device number
+ * @minor: /dev/nmemX minor character device number
+ * @phys_id: SMBIOS physical id
+ * @vendor_id: hardware component vendor
+ * @device_id: hardware device id
+ * @revision_id: hardware revision id
+ * @node: system node-id
+ * @socket: socket-id in the node
+ * @imc: memory-controller-id in the socket
+ * @channel: channel-id in the memory-controller
+ * @dimm: dimm-id in the channel
+ * @formats: number of support interfaces
+ * @format: array of format interface code numbers
+ */
+struct ndctl_dimm {
+	struct kmod_module *module;
+	struct ndctl_bus *bus;
+	struct ndctl_smart_ops *smart_ops;
+	unsigned int handle, major, minor, serial;
+	unsigned short phys_id;
+	unsigned short vendor_id;
+	unsigned short device_id;
+	unsigned short revision_id;
+	unsigned short subsystem_vendor_id;
+	unsigned short subsystem_device_id;
+	unsigned short subsystem_revision_id;
+	unsigned short manufacturing_date;
+	unsigned char manufacturing_location;
+	unsigned long dsm_family;
+	unsigned long dsm_mask;
+	char *unique_id;
+	char *dimm_path;
+	char *dimm_buf;
+	int health_eventfd;
+	int buf_len;
+	int id;
+	union dimm_flags {
+		unsigned long flags;
+		struct {
+			unsigned int f_map:1;
+			unsigned int f_arm:1;
+			unsigned int f_save:1;
+			unsigned int f_flush:1;
+			unsigned int f_smart:1;
+			unsigned int f_restore:1;
+			unsigned int f_notify:1;
+		};
+	} flags;
+	struct list_node list;
+	int formats;
+	int format[0];
+};
+
 #define SZ_16M 0x01000000
 
 enum {

_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [ndctl PATCH 4/7] ndctl: consolidate namespace definitions in namespace.h
  2017-08-29 20:01 [ndctl PATCH 0/7] ndctl: automatically initialize labels Dan Williams
                   ` (2 preceding siblings ...)
  2017-08-29 20:01 ` [ndctl PATCH 3/7] ndctl: move label manipulation routines to their own file Dan Williams
@ 2017-08-29 20:01 ` Dan Williams
  2017-08-29 20:01 ` [ndctl PATCH 5/7] ndctl: refactor read_labels() helper into a library call Dan Williams
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 12+ messages in thread
From: Dan Williams @ 2017-08-29 20:01 UTC (permalink / raw)
  To: linux-nvdimm

The following files all have some namespace-label and btt information:

   ndctl/dimm.c
   ndctl/check.h
   ndctl/lib/private.h

Consolidate all of this in a shared ndctl/namespace.h header.

Cc: Vishal Verma <vishal.l.verma@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 ndctl/check.c        |   52 +++++++++++++++-
 ndctl/check.h        |  130 ----------------------------------------
 ndctl/dimm.c         |   50 ---------------
 ndctl/lib/libndctl.c |    6 +-
 ndctl/lib/private.h  |   90 ----------------------------
 ndctl/namespace.c    |   11 ++-
 ndctl/namespace.h    |  162 ++++++++++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 222 insertions(+), 279 deletions(-)
 delete mode 100644 ndctl/check.h
 create mode 100644 ndctl/namespace.h

diff --git a/ndctl/check.c b/ndctl/check.c
index e05d1b073653..915bb9da8f5f 100644
--- a/ndctl/check.c
+++ b/ndctl/check.c
@@ -30,11 +30,11 @@
 #include <util/bitmap.h>
 #include <util/fletcher.h>
 #include <ndctl/libndctl.h>
+#include <ndctl/namespace.h>
 #include <ccan/endian/endian.h>
 #include <ccan/minmax/minmax.h>
 #include <ccan/array_size/array_size.h>
 #include <ccan/short_types/short_types.h>
-#include "check.h"
 
 #ifdef HAVE_NDCTL_H
 #include <linux/ndctl.h>
@@ -42,6 +42,48 @@
 #include <ndctl.h>
 #endif
 
+struct check_opts {
+	bool verbose;
+	bool force;
+	bool repair;
+};
+
+struct btt_chk {
+	char *path;
+	int fd;
+	uuid_t parent_uuid;
+	unsigned long long rawsize;
+	unsigned long long nlba;
+	int start_off;
+	int num_arenas;
+	long sys_page_size;
+	struct arena_info *arena;
+	struct check_opts *opts;
+	struct log_ctx ctx;
+};
+
+struct arena_info {
+	struct arena_map map;
+	u64 size;	/* Total bytes for this arena */
+	u64 external_lba_start;
+	u32 internal_nlba;
+	u32 internal_lbasize;
+	u32 external_nlba;
+	u32 external_lbasize;
+	u32 nfree;
+	u16 version_major;
+	u16 version_minor;
+	u64 nextoff;
+	u64 infooff;
+	u64 dataoff;
+	u64 mapoff;
+	u64 logoff;
+	u64 info2off;
+	u32 flags;
+	int num;
+	struct btt_chk *bttc;
+};
+
 static sigjmp_buf sj_env;
 
 static void sigbus_hdl(int sig, siginfo_t *siginfo, void *ptr)
@@ -922,9 +964,15 @@ static int btt_recover_first_sb(struct btt_chk *bttc)
 	return rc;
 }
 
-int namespace_check(struct ndctl_namespace *ndns, struct check_opts *opts)
+int namespace_check(struct ndctl_namespace *ndns, bool verbose, bool force,
+		bool repair)
 {
 	const char *devname = ndctl_namespace_get_devname(ndns);
+	struct check_opts __opts = {
+		.verbose = verbose,
+		.force = force,
+		.repair = repair,
+	}, *opts = &__opts;
 	int raw_mode, rc, disabled_flag = 0, open_flags;
 	struct btt_sb *btt_sb;
 	struct btt_chk *bttc;
diff --git a/ndctl/check.h b/ndctl/check.h
deleted file mode 100644
index 00b11b244ba0..000000000000
--- a/ndctl/check.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (c) 2016, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- */
-
-#ifndef _CHECK_H
-#define _CHECK_H
-
-#include <util/log.h>
-#include <ccan/endian/endian.h>
-#include <ccan/short_types/short_types.h>
-
-#define BTT_SIG_LEN 16
-#define BTT_SIG "BTT_ARENA_INFO\0"
-#define MAP_TRIM_SHIFT 31
-#define MAP_ERR_SHIFT 30
-#define MAP_LBA_MASK (~((1 << MAP_TRIM_SHIFT) | (1 << MAP_ERR_SHIFT)))
-#define MAP_ENT_NORMAL 0xC0000000
-#define ARENA_MIN_SIZE (1UL << 24)	/* 16 MB */
-#define ARENA_MAX_SIZE (1ULL << 39)	/* 512 GB */
-#define BTT_INFO_SIZE 4096
-#define IB_FLAG_ERROR_MASK 0x00000001
-
-#define BTT_NUM_OFFSETS 2
-#define BTT1_START_OFFSET 4096
-#define BTT2_START_OFFSET 0
-
-struct log_entry {
-	le32 lba;
-	le32 old_map;
-	le32 new_map;
-	le32 seq;
-	le64 padding[2];
-};
-
-struct btt_sb {
-	u8 signature[BTT_SIG_LEN];
-	u8 uuid[16];
-	u8 parent_uuid[16];
-	le32 flags;
-	le16 version_major;
-	le16 version_minor;
-	le32 external_lbasize;
-	le32 external_nlba;
-	le32 internal_lbasize;
-	le32 internal_nlba;
-	le32 nfree;
-	le32 infosize;
-	le64 nextoff;
-	le64 dataoff;
-	le64 mapoff;
-	le64 logoff;
-	le64 info2off;
-	u8 padding[3968];
-	le64 checksum;
-};
-
-struct free_entry {
-	u32 block;
-	u8 sub;
-	u8 seq;
-};
-
-struct arena_map {
-	struct btt_sb *info;
-	size_t info_len;
-	void *data;
-	size_t data_len;
-	u32 *map;
-	size_t map_len;
-	struct log_entry *log;
-	size_t log_len;
-	struct btt_sb *info2;
-	size_t info2_len;
-};
-
-struct check_opts {
-	bool verbose;
-	bool force;
-	bool repair;
-};
-
-struct btt_chk {
-	char *path;
-	int fd;
-	uuid_t parent_uuid;
-	unsigned long long rawsize;
-	unsigned long long nlba;
-	int start_off;
-	int num_arenas;
-	long sys_page_size;
-	struct arena_info *arena;
-	struct check_opts *opts;
-	struct log_ctx ctx;
-};
-
-
-struct arena_info {
-	struct arena_map map;
-	u64 size;	/* Total bytes for this arena */
-	u64 external_lba_start;
-	u32 internal_nlba;
-	u32 internal_lbasize;
-	u32 external_nlba;
-	u32 external_lbasize;
-	u32 nfree;
-	u16 version_major;
-	u16 version_minor;
-	u64 nextoff;
-	u64 infooff;
-	u64 dataoff;
-	u64 mapoff;
-	u64 logoff;
-	u64 info2off;
-	u32 flags;
-	int num;
-	struct btt_chk *bttc;
-};
-
-int namespace_check(struct ndctl_namespace *ndns, struct check_opts *opts);
-
-#endif
diff --git a/ndctl/dimm.c b/ndctl/dimm.c
index ee3b9979fa8c..4a39189297a6 100644
--- a/ndctl/dimm.c
+++ b/ndctl/dimm.c
@@ -24,59 +24,11 @@
 #include <json-c/json.h>
 #include <util/fletcher.h>
 #include <ndctl/libndctl.h>
+#include <ndctl/namespace.h>
 #include <util/parse-options.h>
 #include <ccan/minmax/minmax.h>
-#include <ccan/short_types/short_types.h>
-#include <ccan/endian/endian.h>
 #include <ccan/array_size/array_size.h>
 
-enum {
-	NSINDEX_SIG_LEN = 16,
-	NSINDEX_ALIGN = 256,
-	NSINDEX_SEQ_MASK = 0x3,
-	NSLABEL_UUID_LEN = 16,
-	NSLABEL_NAME_LEN = 64,
-};
-
-struct namespace_index {
-	char sig[NSINDEX_SIG_LEN];
-	u8 flags[3];
-	u8 labelsize;
-	le32 seq;
-	le64 myoff;
-	le64 mysize;
-	le64 otheroff;
-	le64 labeloff;
-	le32 nslot;
-	le16 major;
-	le16 minor;
-	le64 checksum;
-	char free[0];
-};
-
-struct namespace_label {
-	char uuid[NSLABEL_UUID_LEN];
-	char name[NSLABEL_NAME_LEN];
-	le32 flags;
-	le16 nlabel;
-	le16 position;
-	le64 isetcookie;
-	le64 lbasize;
-	le64 dpa;
-	le64 rawsize;
-	le32 slot;
-	/*
-	 * Accessing fields past this point should be gated by a
-	 * namespace_label_has() check.
-	 */
-	u8 align;
-	u8 reserved[3];
-	char type_guid[NSLABEL_UUID_LEN];
-	char abstraction_guid[NSLABEL_UUID_LEN];
-	u8 reserved2[88];
-	le64 checksum;
-};
-
 struct nvdimm_data {
 	struct ndctl_dimm *dimm;
 	struct ndctl_cmd *cmd_read;
diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
index f93ba9b8de76..86abeb6cc577 100644
--- a/ndctl/lib/libndctl.c
+++ b/ndctl/lib/libndctl.c
@@ -36,6 +36,7 @@
 
 #include <util/sysfs.h>
 #include <ndctl/libndctl.h>
+#include <ndctl/namespace.h>
 #include <daxctl/libdaxctl.h>
 #include "private.h"
 
@@ -55,7 +56,7 @@ static uuid_t null_uuid;
  */
 NDCTL_EXPORT size_t ndctl_sizeof_namespace_index(void)
 {
-	return sizeof_namespace_index();
+	return ALIGN(sizeof(struct namespace_index), NSINDEX_ALIGN);
 }
 
 /**
@@ -71,7 +72,8 @@ NDCTL_EXPORT size_t ndctl_min_namespace_size(void)
  */
 NDCTL_EXPORT size_t ndctl_sizeof_namespace_label(void)
 {
-	return sizeof(struct namespace_label);
+	/* TODO: v1.2 label support */
+	return offsetof(struct namespace_label, type_guid);
 }
 
 struct ndctl_ctx;
diff --git a/ndctl/lib/private.h b/ndctl/lib/private.h
index 12e3102150fd..64906b8123d0 100644
--- a/ndctl/lib/private.h
+++ b/ndctl/lib/private.h
@@ -91,96 +91,6 @@ struct ndctl_dimm {
 	int format[0];
 };
 
-#define SZ_16M 0x01000000
-
-enum {
-	NSINDEX_SIG_LEN = 16,
-	NSINDEX_ALIGN = 256,
-	NSLABEL_UUID_LEN = 16,
-	NSLABEL_NAMESPACE_MIN_SIZE = SZ_16M,
-	NSLABEL_NAME_LEN = 64,
-	NSLABEL_FLAG_ROLABEL = 0x1,  /* read-only label */
-	NSLABEL_FLAG_LOCAL = 0x2,    /* DIMM-local namespace */
-	NSLABEL_FLAG_BTT = 0x4,      /* namespace contains a BTT */
-	NSLABEL_FLAG_UPDATING = 0x8, /* label being updated */
-	BTT_ALIGN = 4096,            /* all btt structures */
-	BTTINFO_SIG_LEN = 16,
-	BTTINFO_UUID_LEN = 16,
-	BTTINFO_FLAG_ERROR = 0x1,    /* error state (read-only) */
-	BTTINFO_MAJOR_VERSION = 1,
-};
-
-/**
- * struct namespace_index - label set superblock
- * @sig: NAMESPACE_INDEX\0
- * @flags: placeholder
- * @seq: sequence number for this index
- * @myoff: offset of this index in label area
- * @mysize: size of this index struct
- * @otheroff: offset of other index
- * @labeloff: offset of first label slot
- * @nslot: total number of label slots
- * @major: label area major version
- * @minor: label area minor version
- * @checksum: fletcher64 of all fields
- * @free[0]: bitmap, nlabel bits
- *
- * The size of free[] is rounded up so the total struct size is a
- * multiple of NSINDEX_ALIGN bytes.  Any bits this allocates beyond
- * nlabel bits must be zero.
- */
-struct namespace_index {
-        u8 sig[NSINDEX_SIG_LEN];
-        le32 flags;
-        le32 seq;
-        le64 myoff;
-        le64 mysize;
-        le64 otheroff;
-        le64 labeloff;
-        le32 nslot;
-        le16 major;
-        le16 minor;
-        le64 checksum;
-        u8 free[0];
-};
-
-static inline size_t sizeof_namespace_index(void)
-{
-	size_t size = sizeof(struct namespace_index);
-
-	size += NSINDEX_ALIGN;
-	size &= ~(NSINDEX_ALIGN - 1);
-	return size;
-}
-
-/**
- * struct namespace_label - namespace superblock
- * @uuid: UUID per RFC 4122
- * @name: optional name (NULL-terminated)
- * @flags: see NSLABEL_FLAG_*
- * @nlabel: num labels to describe this ns
- * @position: labels position in set
- * @isetcookie: interleave set cookie
- * @lbasize: LBA size in bytes or 0 for pmem
- * @dpa: DPA of NVM range on this DIMM
- * @rawsize: size of namespace
- * @slot: slot of this label in label area
- * @unused: must be zero
- */
-struct namespace_label {
-	u8 uuid[NSLABEL_UUID_LEN];
-	u8 name[NSLABEL_NAME_LEN];
-	le32 flags;
-	le16 nlabel;
-	le16 position;
-	le64 isetcookie;
-	le64 lbasize;
-	le64 dpa;
-	le64 rawsize;
-	le32 slot;
-	le32 unused;
-};
-
 /**
  * struct ndctl_ctx - library user context to find "nd" instances
  *
diff --git a/ndctl/namespace.c b/ndctl/namespace.c
index c4d70c39c6c4..6cfd873da248 100644
--- a/ndctl/namespace.c
+++ b/ndctl/namespace.c
@@ -28,7 +28,6 @@
 #include <util/parse-options.h>
 #include <ccan/minmax/minmax.h>
 #include <ccan/array_size/array_size.h>
-#include "check.h"
 
 #ifdef HAVE_NDCTL_H
 #include <linux/ndctl.h>
@@ -836,13 +835,15 @@ static int namespace_reconfig(struct ndctl_region *region,
 	return setup_namespace(region, ndns, &p);
 }
 
+int namespace_check(struct ndctl_namespace *ndns, bool verbose, bool force,
+		bool repair);
+
 static int do_xaction_namespace(const char *namespace,
 		enum namespace_action action, struct ndctl_ctx *ctx)
 {
 	struct ndctl_namespace *ndns, *_n;
 	int rc = -ENXIO, success = 0;
 	struct ndctl_region *region;
-	struct check_opts opts;
 	const char *ndns_name;
 	struct ndctl_bus *bus;
 
@@ -898,10 +899,8 @@ static int do_xaction_namespace(const char *namespace,
 					rc = namespace_destroy(region, ndns);
 					break;
 				case ACTION_CHECK:
-					opts.verbose = verbose;
-					opts.repair = repair;
-					opts.force = force;
-					rc = namespace_check(ndns, &opts);
+					rc = namespace_check(ndns, verbose,
+							force, repair);
 					if (rc < 0)
 						return rc;
 					break;
diff --git a/ndctl/namespace.h b/ndctl/namespace.h
new file mode 100644
index 000000000000..b466c2b96bd3
--- /dev/null
+++ b/ndctl/namespace.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2014-2017, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
+ * more details.
+ */
+#ifndef __NDCTL_NAMESPACE_H__
+#define __NDCTL_NAMESPACE_H__
+#include <util/size.h>
+#include <ccan/endian/endian.h>
+#include <ccan/short_types/short_types.h>
+
+enum {
+	NSINDEX_SIG_LEN = 16,
+	NSINDEX_ALIGN = 256,
+	NSINDEX_SEQ_MASK = 0x3,
+	NSLABEL_UUID_LEN = 16,
+	NSLABEL_NAMESPACE_MIN_SIZE = SZ_16M,
+	NSLABEL_NAME_LEN = 64,
+};
+
+/**
+ * struct namespace_index - label set superblock
+ * @sig: NAMESPACE_INDEX\0
+ * @flags: placeholder
+ * @seq: sequence number for this index
+ * @myoff: offset of this index in label area
+ * @mysize: size of this index struct
+ * @otheroff: offset of other index
+ * @labeloff: offset of first label slot
+ * @nslot: total number of label slots
+ * @major: label area major version
+ * @minor: label area minor version
+ * @checksum: fletcher64 of all fields
+ * @free[0]: bitmap, nlabel bits
+ *
+ * The size of free[] is rounded up so the total struct size is a
+ * multiple of NSINDEX_ALIGN bytes.  Any bits this allocates beyond
+ * nlabel bits must be zero.
+ */
+struct namespace_index {
+	char sig[NSINDEX_SIG_LEN];
+	u8 flags[3];
+	u8 labelsize;
+	le32 seq;
+	le64 myoff;
+	le64 mysize;
+	le64 otheroff;
+	le64 labeloff;
+	le32 nslot;
+	le16 major;
+	le16 minor;
+	le64 checksum;
+	char free[0];
+};
+
+/**
+ * struct namespace_label - namespace superblock
+ * @uuid: UUID per RFC 4122
+ * @name: optional name (NULL-terminated)
+ * @flags: see NSLABEL_FLAG_*
+ * @nlabel: num labels to describe this ns
+ * @position: labels position in set
+ * @isetcookie: interleave set cookie
+ * @lbasize: LBA size in bytes or 0 for pmem
+ * @dpa: DPA of NVM range on this DIMM
+ * @rawsize: size of namespace
+ * @slot: slot of this label in label area
+ */
+struct namespace_label {
+	char uuid[NSLABEL_UUID_LEN];
+	char name[NSLABEL_NAME_LEN];
+	le32 flags;
+	le16 nlabel;
+	le16 position;
+	le64 isetcookie;
+	le64 lbasize;
+	le64 dpa;
+	le64 rawsize;
+	le32 slot;
+	/*
+	 * Accessing fields past this point should be gated by a
+	 * namespace_label_has() check.
+	 */
+	u8 align;
+	u8 reserved[3];
+	char type_guid[NSLABEL_UUID_LEN];
+	char abstraction_guid[NSLABEL_UUID_LEN];
+	u8 reserved2[88];
+	le64 checksum;
+};
+
+#define BTT_SIG_LEN 16
+#define BTT_SIG "BTT_ARENA_INFO\0"
+#define MAP_TRIM_SHIFT 31
+#define MAP_ERR_SHIFT 30
+#define MAP_LBA_MASK (~((1 << MAP_TRIM_SHIFT) | (1 << MAP_ERR_SHIFT)))
+#define MAP_ENT_NORMAL 0xC0000000
+#define ARENA_MIN_SIZE (1UL << 24)	/* 16 MB */
+#define ARENA_MAX_SIZE (1ULL << 39)	/* 512 GB */
+#define BTT_INFO_SIZE 4096
+#define IB_FLAG_ERROR_MASK 0x00000001
+
+#define BTT_NUM_OFFSETS 2
+#define BTT1_START_OFFSET 4096
+#define BTT2_START_OFFSET 0
+
+struct log_entry {
+	le32 lba;
+	le32 old_map;
+	le32 new_map;
+	le32 seq;
+	le64 padding[2];
+};
+
+struct btt_sb {
+	u8 signature[BTT_SIG_LEN];
+	u8 uuid[16];
+	u8 parent_uuid[16];
+	le32 flags;
+	le16 version_major;
+	le16 version_minor;
+	le32 external_lbasize;
+	le32 external_nlba;
+	le32 internal_lbasize;
+	le32 internal_nlba;
+	le32 nfree;
+	le32 infosize;
+	le64 nextoff;
+	le64 dataoff;
+	le64 mapoff;
+	le64 logoff;
+	le64 info2off;
+	u8 padding[3968];
+	le64 checksum;
+};
+
+struct free_entry {
+	u32 block;
+	u8 sub;
+	u8 seq;
+};
+
+struct arena_map {
+	struct btt_sb *info;
+	size_t info_len;
+	void *data;
+	size_t data_len;
+	u32 *map;
+	size_t map_len;
+	struct log_entry *log;
+	size_t log_len;
+	struct btt_sb *info2;
+	size_t info2_len;
+};
+#endif /* __NDCTL_NAMESPACE_H__ */

_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [ndctl PATCH 5/7] ndctl: refactor read_labels() helper into a library call
  2017-08-29 20:01 [ndctl PATCH 0/7] ndctl: automatically initialize labels Dan Williams
                   ` (3 preceding siblings ...)
  2017-08-29 20:01 ` [ndctl PATCH 4/7] ndctl: consolidate namespace definitions in namespace.h Dan Williams
@ 2017-08-29 20:01 ` Dan Williams
  2017-08-29 20:02 ` [ndctl PATCH 6/7] ndctl: introduce ndctl_dimm_{validate_labels, init_labels} Dan Williams
  2017-08-29 20:02 ` [ndctl PATCH 7/7] ndctl: auto initialize labels Dan Williams
  6 siblings, 0 replies; 12+ messages in thread
From: Dan Williams @ 2017-08-29 20:01 UTC (permalink / raw)
  To: linux-nvdimm

As a pre-requisite to making an "init labels" library call, refactor
label reading into a generic helper call.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 ndctl/dimm.c           |   40 ++----------------------------
 ndctl/lib/dimm.c       |   64 ++++++++++++++++++++++++++++++------------------
 ndctl/lib/libndctl.sym |    1 +
 ndctl/libndctl.h.in    |    1 +
 4 files changed, 45 insertions(+), 61 deletions(-)

diff --git a/ndctl/dimm.c b/ndctl/dimm.c
index 4a39189297a6..ca7b833db182 100644
--- a/ndctl/dimm.c
+++ b/ndctl/dimm.c
@@ -358,40 +358,6 @@ static int rw_bin(FILE *f, struct ndctl_cmd *cmd, ssize_t size, int rw)
 	return 0;
 }
 
-static struct ndctl_cmd *read_labels(struct ndctl_dimm *dimm)
-{
-	struct ndctl_bus *bus = ndctl_dimm_get_bus(dimm);
-	struct ndctl_cmd *cmd_size, *cmd_read;
-	int rc;
-
-	rc = ndctl_bus_wait_probe(bus);
-	if (rc < 0)
-		return NULL;
-
-	cmd_size = ndctl_dimm_cmd_new_cfg_size(dimm);
-	if (!cmd_size)
-		return NULL;
-	rc = ndctl_cmd_submit(cmd_size);
-	if (rc || ndctl_cmd_get_firmware_status(cmd_size))
-		goto out_size;
-
-	cmd_read = ndctl_dimm_cmd_new_cfg_read(cmd_size);
-	if (!cmd_read)
-		goto out_size;
-	rc = ndctl_cmd_submit(cmd_read);
-	if (rc || ndctl_cmd_get_firmware_status(cmd_read))
-		goto out_read;
-
-	ndctl_cmd_unref(cmd_size);
-	return cmd_read;
-
- out_read:
-	ndctl_cmd_unref(cmd_read);
- out_size:
-	ndctl_cmd_unref(cmd_size);
-	return NULL;
-}
-
 static int action_write(struct ndctl_dimm *dimm, struct action_context *actx)
 {
 	struct ndctl_cmd *cmd_read, *cmd_write;
@@ -403,7 +369,7 @@ static int action_write(struct ndctl_dimm *dimm, struct action_context *actx)
 		return -EBUSY;
 	}
 
-	cmd_read = read_labels(dimm);
+	cmd_read = ndctl_dimm_read_labels(dimm);
 	if (!cmd_read)
 		return -ENXIO;
 
@@ -441,7 +407,7 @@ static int action_read(struct ndctl_dimm *dimm, struct action_context *actx)
 	ssize_t size;
 	int rc = 0;
 
-	cmd_read = read_labels(dimm);
+	cmd_read = ndctl_dimm_read_labels(dimm);
 	if (!cmd_read)
 		return -ENXIO;
 
@@ -794,7 +760,7 @@ static int __action_init(struct ndctl_dimm *dimm, int version, int chk_only)
 	int rc = 0, i;
 	ssize_t size;
 
-	cmd_read = read_labels(dimm);
+	cmd_read = ndctl_dimm_read_labels(dimm);
 	if (!cmd_read)
 		return -ENXIO;
 
diff --git a/ndctl/lib/dimm.c b/ndctl/lib/dimm.c
index 1c613a470099..f7696af04ba2 100644
--- a/ndctl/lib/dimm.c
+++ b/ndctl/lib/dimm.c
@@ -15,38 +15,56 @@
 #include <stdlib.h>
 #include "private.h"
 
+NDCTL_EXPORT struct ndctl_cmd *ndctl_dimm_read_labels(struct ndctl_dimm *dimm)
+{
+        struct ndctl_bus *bus = ndctl_dimm_get_bus(dimm);
+        struct ndctl_cmd *cmd_size, *cmd_read;
+        int rc;
+
+        rc = ndctl_bus_wait_probe(bus);
+        if (rc < 0)
+                return NULL;
+
+        cmd_size = ndctl_dimm_cmd_new_cfg_size(dimm);
+        if (!cmd_size)
+                return NULL;
+        rc = ndctl_cmd_submit(cmd_size);
+        if (rc || ndctl_cmd_get_firmware_status(cmd_size))
+                goto out_size;
+
+        cmd_read = ndctl_dimm_cmd_new_cfg_read(cmd_size);
+        if (!cmd_read)
+                goto out_size;
+        rc = ndctl_cmd_submit(cmd_read);
+        if (rc || ndctl_cmd_get_firmware_status(cmd_read))
+                goto out_read;
+
+        ndctl_cmd_unref(cmd_size);
+        return cmd_read;
+
+ out_read:
+        ndctl_cmd_unref(cmd_read);
+ out_size:
+        ndctl_cmd_unref(cmd_size);
+        return NULL;
+}
+
 NDCTL_EXPORT int ndctl_dimm_zero_labels(struct ndctl_dimm *dimm)
 {
-	struct ndctl_cmd *cmd_size, *cmd_read, *cmd_write;
 	struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
-	struct ndctl_bus *bus = ndctl_dimm_get_bus(dimm);
+	struct ndctl_cmd *cmd_read, *cmd_write;
 	int rc;
 
-	rc = ndctl_bus_wait_probe(bus);
-	if (rc < 0)
-		return rc;
+	cmd_read = ndctl_dimm_read_labels(dimm);
+	if (!cmd_read)
+		return -ENXIO;
 
 	if (ndctl_dimm_is_active(dimm)) {
 		dbg(ctx, "%s: regions active, abort label write\n",
 			ndctl_dimm_get_devname(dimm));
-		return -EBUSY;
-	}
-
-	cmd_size = ndctl_dimm_cmd_new_cfg_size(dimm);
-	if (!cmd_size)
-		return -ENOTTY;
-	rc = ndctl_cmd_submit(cmd_size);
-	if (rc || ndctl_cmd_get_firmware_status(cmd_size))
-		goto out_size;
-
-	cmd_read = ndctl_dimm_cmd_new_cfg_read(cmd_size);
-	if (!cmd_read) {
-		rc = -ENOTTY;
-		goto out_size;
-	}
-	rc = ndctl_cmd_submit(cmd_read);
-	if (rc || ndctl_cmd_get_firmware_status(cmd_read))
+		rc = -EBUSY;
 		goto out_read;
+	}
 
 	cmd_write = ndctl_dimm_cmd_new_cfg_write(cmd_read);
 	if (!cmd_write) {
@@ -77,8 +95,6 @@ NDCTL_EXPORT int ndctl_dimm_zero_labels(struct ndctl_dimm *dimm)
 	ndctl_cmd_unref(cmd_write);
  out_read:
 	ndctl_cmd_unref(cmd_read);
- out_size:
-	ndctl_cmd_unref(cmd_size);
 
 	return rc;
 }
diff --git a/ndctl/lib/libndctl.sym b/ndctl/lib/libndctl.sym
index b8ac65f2917f..95c6e400124d 100644
--- a/ndctl/lib/libndctl.sym
+++ b/ndctl/lib/libndctl.sym
@@ -113,6 +113,7 @@ global:
 	ndctl_cmd_smart_threshold_get_temperature;
 	ndctl_cmd_smart_threshold_get_spares;
 	ndctl_dimm_zero_labels;
+	ndctl_dimm_read_labels;
 	ndctl_dimm_get_available_labels;
 	ndctl_region_get_first;
 	ndctl_region_get_next;
diff --git a/ndctl/libndctl.h.in b/ndctl/libndctl.h.in
index 855d883c3380..9be380b8a735 100644
--- a/ndctl/libndctl.h.in
+++ b/ndctl/libndctl.h.in
@@ -358,6 +358,7 @@ struct ndctl_cmd *ndctl_dimm_cmd_new_cfg_size(struct ndctl_dimm *dimm);
 struct ndctl_cmd *ndctl_dimm_cmd_new_cfg_read(struct ndctl_cmd *cfg_size);
 struct ndctl_cmd *ndctl_dimm_cmd_new_cfg_write(struct ndctl_cmd *cfg_read);
 int ndctl_dimm_zero_labels(struct ndctl_dimm *dimm);
+struct ndctl_cmd *ndctl_dimm_read_labels(struct ndctl_dimm *dimm);
 unsigned long ndctl_dimm_get_available_labels(struct ndctl_dimm *dimm);
 unsigned int ndctl_cmd_cfg_size_get_size(struct ndctl_cmd *cfg_size);
 ssize_t ndctl_cmd_cfg_read_get_data(struct ndctl_cmd *cfg_read, void *buf,

_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [ndctl PATCH 6/7] ndctl: introduce ndctl_dimm_{validate_labels, init_labels}
  2017-08-29 20:01 [ndctl PATCH 0/7] ndctl: automatically initialize labels Dan Williams
                   ` (4 preceding siblings ...)
  2017-08-29 20:01 ` [ndctl PATCH 5/7] ndctl: refactor read_labels() helper into a library call Dan Williams
@ 2017-08-29 20:02 ` Dan Williams
  2017-08-29 20:02 ` [ndctl PATCH 7/7] ndctl: auto initialize labels Dan Williams
  6 siblings, 0 replies; 12+ messages in thread
From: Dan Williams @ 2017-08-29 20:02 UTC (permalink / raw)
  To: linux-nvdimm

Add an api that attempts to parse an opaque namespace label data blob
into namespace indices and labels. It requires the output from
ndctl_dimm_read_labels(), and it enables later interrogation of the dimm
via ndctl_dimm_sizeof_namespace_index() and
ndctl_dimm_sizeof_namespace_label() which require valid label data to be
present.

This mostly moves all the local label helpers from the ndctl utility
into the library.

Cc: Vishal Verma <vishal.l.verma@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 Makefile.am            |    1 
 ndctl/dimm.c           |  455 +++---------------------------------------------
 ndctl/lib/dimm.c       |  451 +++++++++++++++++++++++++++++++++++++++++++++++-
 ndctl/lib/libndctl.c   |    1 
 ndctl/lib/libndctl.sym |    3 
 ndctl/lib/private.h    |   10 +
 ndctl/libndctl.h.in    |    8 +
 ndctl/namespace.h      |    1 
 util/fletcher.c        |   35 ----
 util/fletcher.h        |   19 ++
 10 files changed, 513 insertions(+), 471 deletions(-)
 delete mode 100644 util/fletcher.c

diff --git a/Makefile.am b/Makefile.am
index ba81e8c3d5bb..b538b1fd57ba 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -69,7 +69,6 @@ libutil_a_SOURCES = \
 	util/strbuf.c \
 	util/wrapper.c \
 	util/filter.c \
-	util/fletcher.c\
 	util/bitmap.c
 
 nobase_include_HEADERS = daxctl/libdaxctl.h
diff --git a/ndctl/dimm.c b/ndctl/dimm.c
index ca7b833db182..7259506fc028 100644
--- a/ndctl/dimm.c
+++ b/ndctl/dimm.c
@@ -29,63 +29,9 @@
 #include <ccan/minmax/minmax.h>
 #include <ccan/array_size/array_size.h>
 
-struct nvdimm_data {
-	struct ndctl_dimm *dimm;
-	struct ndctl_cmd *cmd_read;
-	unsigned long config_size;
-	size_t nslabel_size;
-	struct log_ctx ctx;
-	void *data;
-	int nsindex_size;
-	int ns_current, ns_next;
-};
-
-static size_t sizeof_namespace_label(struct nvdimm_data *ndd)
-{
-	struct namespace_index nsindex;
-	int v1 = 0, v2 = 0;
-	ssize_t offset;
-
-	if (ndd->nslabel_size)
-		return ndd->nslabel_size;
-
-	for (offset = 0; offset < NSINDEX_ALIGN * 2; offset += NSINDEX_ALIGN) {
-		ssize_t len = (ssize_t) sizeof(nsindex);
-
-		len = ndctl_cmd_cfg_read_get_data(ndd->cmd_read, &nsindex,
-				len, offset);
-		if (len < 0)
-			break;
-
-		/*
-		 * Since we're doing a best effort parsing we don't
-		 * fully validate the index block. Instead just assume
-		 * v1.1 unless there's 2 index blocks that say v1.2.
-		 */
-		if (le16_to_cpu(nsindex.major) == 1) {
-			if (le16_to_cpu(nsindex.minor) == 1)
-				v1++;
-			else if (le16_to_cpu(nsindex.minor) == 2)
-				v2++;
-		}
-	}
-
-	if (v2 > v1)
-		ndd->nslabel_size = 256;
-	else
-		ndd->nslabel_size = 128;
-	return ndd->nslabel_size;
-}
-
-#define namespace_label_has(ndd, field) \
-	(offsetof(struct namespace_label, field) \
-	 < sizeof_namespace_label(ndd))
-
-static const char NSINDEX_SIGNATURE[] = "NAMESPACE_INDEX\0";
-
 struct action_context {
 	struct json_object *jdimms;
-	int labelversion;
+	enum ndctl_namespace_version labelversion;
 	FILE *f_out;
 	FILE *f_in;
 };
@@ -111,12 +57,9 @@ static int action_zero(struct ndctl_dimm *dimm, struct action_context *actx)
 	return ndctl_dimm_zero_labels(dimm);
 }
 
-static struct json_object *dump_label_json(struct ndctl_cmd *cmd_read, ssize_t size)
+static struct json_object *dump_label_json(struct ndctl_dimm *dimm,
+		struct ndctl_cmd *cmd_read, ssize_t size)
 {
-	struct nvdimm_data __ndd = {
-		.nslabel_size = 0,
-		.cmd_read = cmd_read
-	}, *ndd = &__ndd;
 	struct json_object *jarray = json_object_new_array();
 	struct json_object *jlabel = NULL;
 	struct namespace_label nslabel;
@@ -127,8 +70,9 @@ static struct json_object *dump_label_json(struct ndctl_cmd *cmd_read, ssize_t s
 		return NULL;
 
 	for (offset = NSINDEX_ALIGN * 2; offset < size;
-			offset += sizeof_namespace_label(ndd)) {
-		ssize_t len = min_t(ssize_t, sizeof_namespace_label(ndd),
+			offset += ndctl_dimm_sizeof_namespace_label(dimm)) {
+		ssize_t len = min_t(ssize_t,
+				ndctl_dimm_sizeof_namespace_label(dimm),
 				size - offset);
 		struct json_object *jobj;
 		char uuid[40];
@@ -138,7 +82,7 @@ static struct json_object *dump_label_json(struct ndctl_cmd *cmd_read, ssize_t s
 		if (!jlabel)
 			break;
 
-		if (len < (ssize_t) sizeof_namespace_label(ndd))
+		if (len < (ssize_t) ndctl_dimm_sizeof_namespace_label(dimm))
 			break;
 
 		len = ndctl_cmd_cfg_read_get_data(cmd_read, &nslabel, len, offset);
@@ -197,7 +141,7 @@ static struct json_object *dump_label_json(struct ndctl_cmd *cmd_read, ssize_t s
 
 		json_object_array_add(jarray, jlabel);
 
-		if (sizeof_namespace_label(ndd) < 256)
+		if (ndctl_dimm_sizeof_namespace_label(dimm) < 256)
 			continue;
 
 		uuid_unparse((void *) nslabel.type_guid, uuid);
@@ -303,7 +247,7 @@ static struct json_object *dump_json(struct ndctl_dimm *dimm,
 	jindex = dump_index_json(cmd_read, size);
 	if (!jindex)
 		goto err_jindex;
-	jlabel = dump_label_json(cmd_read, size);
+	jlabel = dump_label_json(dimm, cmd_read, size);
 	if (!jlabel)
 		goto err_jlabel;
 
@@ -427,320 +371,6 @@ static int action_read(struct ndctl_dimm *dimm, struct action_context *actx)
 	return rc;
 }
 
-/*
- * Note, best_seq(), inc_seq(), sizeof_namespace_index()
- * nvdimm_num_label_slots(), label_validate(), and label_write_index()
- * are copied from drivers/nvdimm/label.c in the Linux kernel with the
- * following modifications:
- * 1/ s,nd_,,gc
- * 2/ s,ndd->nsarea.config_size,ndd->config_size,gc
- * 3/ s,dev_dbg(dev,dbg(ndd,gc
- * 4/ s,__le,le,gc
- * 5/ s,__cpu_to,cpu_to,gc
- * 6/ remove flags argument to label_write_index
- * 7/ dropped clear_bit_le() usage in label_write_index
- * 8/ s,nvdimm_drvdata,nvdimm_data,gc
- */
-
-static unsigned inc_seq(unsigned seq)
-{
-	static const unsigned next[] = { 0, 2, 3, 1 };
-
-	return next[seq & 3];
-}
-
-static u32 best_seq(u32 a, u32 b)
-{
-	a &= NSINDEX_SEQ_MASK;
-	b &= NSINDEX_SEQ_MASK;
-
-	if (a == 0 || a == b)
-		return b;
-	else if (b == 0)
-		return a;
-	else if (inc_seq(a) == b)
-		return b;
-	else
-		return a;
-}
-
-size_t sizeof_namespace_index(struct nvdimm_data *ndd)
-{
-	u32 index_span;
-
-	if (ndd->nsindex_size)
-		return ndd->nsindex_size;
-
-	/*
-	 * The minimum index space is 512 bytes, with that amount of
-	 * index we can describe ~1400 labels which is less than a byte
-	 * of overhead per label.  Round up to a byte of overhead per
-	 * label and determine the size of the index region.  Yes, this
-	 * starts to waste space at larger config_sizes, but it's
-	 * unlikely we'll ever see anything but 128K.
-	 */
-	index_span = ndd->config_size / (sizeof_namespace_label(ndd) + 1);
-	index_span /= NSINDEX_ALIGN * 2;
-	ndd->nsindex_size = index_span * NSINDEX_ALIGN;
-
-	return ndd->nsindex_size;
-}
-
-int nvdimm_num_label_slots(struct nvdimm_data *ndd)
-{
-	return ndd->config_size / (sizeof_namespace_label(ndd) + 1);
-}
-
-static struct namespace_index *to_namespace_index(struct nvdimm_data *ndd,
-		int i)
-{
-	char *index;
-
-	if (i < 0)
-		return NULL;
-
-	index = (char *) ndd->data + sizeof_namespace_index(ndd) * i;
-	return (struct namespace_index *) index;
-}
-
-static int __label_validate(struct nvdimm_data *ndd)
-{
-	/*
-	 * On media label format consists of two index blocks followed
-	 * by an array of labels.  None of these structures are ever
-	 * updated in place.  A sequence number tracks the current
-	 * active index and the next one to write, while labels are
-	 * written to free slots.
-	 *
-	 *     +------------+
-	 *     |            |
-	 *     |  nsindex0  |
-	 *     |            |
-	 *     +------------+
-	 *     |            |
-	 *     |  nsindex1  |
-	 *     |            |
-	 *     +------------+
-	 *     |   label0   |
-	 *     +------------+
-	 *     |   label1   |
-	 *     +------------+
-	 *     |            |
-	 *      ....nslot...
-	 *     |            |
-	 *     +------------+
-	 *     |   labelN   |
-	 *     +------------+
-	 */
-	struct namespace_index *nsindex[] = {
-		to_namespace_index(ndd, 0),
-		to_namespace_index(ndd, 1),
-	};
-	const int num_index = ARRAY_SIZE(nsindex);
-	bool valid[2] = { 0 };
-	int i, num_valid = 0;
-	u32 seq;
-
-	for (i = 0; i < num_index; i++) {
-		u32 nslot;
-		u8 sig[NSINDEX_SIG_LEN];
-		u64 sum_save, sum, size;
-		unsigned int version, labelsize;
-
-		memcpy(sig, nsindex[i]->sig, NSINDEX_SIG_LEN);
-		if (memcmp(sig, NSINDEX_SIGNATURE, NSINDEX_SIG_LEN) != 0) {
-			dbg(ndd, "nsindex%d signature invalid\n", i);
-			continue;
-		}
-
-		/* label sizes larger than 128 arrived with v1.2 */
-		version = le16_to_cpu(nsindex[i]->major) * 100
-			+ le16_to_cpu(nsindex[i]->minor);
-		if (version >= 102)
-			labelsize = 1 << (7 + nsindex[i]->labelsize);
-		else
-			labelsize = 128;
-
-		if (labelsize != sizeof_namespace_label(ndd)) {
-			dbg(ndd, "nsindex%d labelsize %d invalid\n",
-					i, nsindex[i]->labelsize);
-			continue;
-		}
-
-		sum_save = le64_to_cpu(nsindex[i]->checksum);
-		nsindex[i]->checksum = cpu_to_le64(0);
-		sum = fletcher64(nsindex[i], sizeof_namespace_index(ndd), 1);
-		nsindex[i]->checksum = cpu_to_le64(sum_save);
-		if (sum != sum_save) {
-			dbg(ndd, "nsindex%d checksum invalid\n", i);
-			continue;
-		}
-
-		seq = le32_to_cpu(nsindex[i]->seq);
-		if ((seq & NSINDEX_SEQ_MASK) == 0) {
-			dbg(ndd, "nsindex%d sequence: %#x invalid\n", i, seq);
-			continue;
-		}
-
-		/* sanity check the index against expected values */
-		if (le64_to_cpu(nsindex[i]->myoff)
-				!= i * sizeof_namespace_index(ndd)) {
-			dbg(ndd, "nsindex%d myoff: %#llx invalid\n",
-					i, (unsigned long long)
-					le64_to_cpu(nsindex[i]->myoff));
-			continue;
-		}
-		if (le64_to_cpu(nsindex[i]->otheroff)
-				!= (!i) * sizeof_namespace_index(ndd)) {
-			dbg(ndd, "nsindex%d otheroff: %#llx invalid\n",
-					i, (unsigned long long)
-					le64_to_cpu(nsindex[i]->otheroff));
-			continue;
-		}
-
-		size = le64_to_cpu(nsindex[i]->mysize);
-		if (size > sizeof_namespace_index(ndd)
-				|| size < sizeof(struct namespace_index)) {
-			dbg(ndd, "nsindex%d mysize: %#zx invalid\n", i, size);
-			continue;
-		}
-
-		nslot = le32_to_cpu(nsindex[i]->nslot);
-		if (nslot * sizeof_namespace_label(ndd)
-				+ 2 * sizeof_namespace_index(ndd)
-				> ndd->config_size) {
-			dbg(ndd, "nsindex%d nslot: %u invalid, config_size: %#zx\n",
-					i, nslot, ndd->config_size);
-			continue;
-		}
-		valid[i] = true;
-		num_valid++;
-	}
-
-	switch (num_valid) {
-	case 0:
-		break;
-	case 1:
-		for (i = 0; i < num_index; i++)
-			if (valid[i])
-				return i;
-		/* can't have num_valid > 0 but valid[] = { false, false } */
-		err(ndd, "unexpected index-block parse error\n");
-		break;
-	default:
-		/* pick the best index... */
-		seq = best_seq(le32_to_cpu(nsindex[0]->seq),
-				le32_to_cpu(nsindex[1]->seq));
-		if (seq == (le32_to_cpu(nsindex[1]->seq) & NSINDEX_SEQ_MASK))
-			return 1;
-		else
-			return 0;
-		break;
-	}
-
-	return -1;
-}
-
-int label_validate(struct nvdimm_data *ndd)
-{
-	/*
-	 * In order to probe for and validate namespace index blocks we
-	 * need to know the size of the labels, and we can't trust the
-	 * size of the labels until we validate the index blocks.
-	 * Resolve this dependency loop by probing for known label
-	 * sizes, but default to v1.2 256-byte namespace labels if
-	 * discovery fails.
-	 */
-	int label_size[] = { 128, 256 };
-	int i, rc;
-
-	for (i = 0; (size_t) i < ARRAY_SIZE(label_size); i++) {
-		ndd->nslabel_size = label_size[i];
-		rc = __label_validate(ndd);
-		if (rc >= 0)
-			return rc;
-	}
-
-	return -1;
-}
-
-static int nvdimm_set_config_data(struct nvdimm_data *ndd, size_t offset,
-		void *buf, size_t len)
-{
-	struct ndctl_cmd *cmd_write;
-	int rc;
-
-	cmd_write = ndctl_dimm_cmd_new_cfg_write(ndd->cmd_read);
-	if (!cmd_write)
-		return -ENXIO;
-
-	rc = ndctl_cmd_cfg_write_set_data(cmd_write, buf, len, offset);
-	if (rc < 0)
-		goto out;
-
-	rc = ndctl_cmd_submit(cmd_write);
-	if (rc || ndctl_cmd_get_firmware_status(cmd_write))
-		rc = -ENXIO;
- out:
-	ndctl_cmd_unref(cmd_write);
-	return rc;
-}
-
-static int label_next_nsindex(int index)
-{
-	if (index < 0)
-		return -1;
-	return (index + 1) % 2;
-}
-
-static struct namespace_label *label_base(struct nvdimm_data *ndd)
-{
-	char *base = (char *) to_namespace_index(ndd, 0);
-
-	base += 2 * sizeof_namespace_index(ndd);
-	return (struct namespace_label *) base;
-}
-
-static int label_write_index(struct nvdimm_data *ndd, int index, u32 seq)
-{
-	struct namespace_index *nsindex;
-	unsigned long offset;
-	u64 checksum;
-	u32 nslot;
-
-	nsindex = to_namespace_index(ndd, index);
-	nslot = nvdimm_num_label_slots(ndd);
-
-	memcpy(nsindex->sig, NSINDEX_SIGNATURE, NSINDEX_SIG_LEN);
-	memset(nsindex->flags, 0, 3);
-	nsindex->labelsize = sizeof_namespace_label(ndd) >> 8;
-	nsindex->seq = cpu_to_le32(seq);
-	offset = (unsigned long) nsindex
-		- (unsigned long) to_namespace_index(ndd, 0);
-	nsindex->myoff = cpu_to_le64(offset);
-	nsindex->mysize = cpu_to_le64(sizeof_namespace_index(ndd));
-	offset = (unsigned long) to_namespace_index(ndd,
-			label_next_nsindex(index))
-		- (unsigned long) to_namespace_index(ndd, 0);
-	nsindex->otheroff = cpu_to_le64(offset);
-	offset = (unsigned long) label_base(ndd)
-		- (unsigned long) to_namespace_index(ndd, 0);
-	nsindex->labeloff = cpu_to_le64(offset);
-	nsindex->nslot = cpu_to_le32(nslot);
-	nsindex->major = cpu_to_le16(1);
-	if (sizeof_namespace_label(ndd) < 256)
-		nsindex->minor = cpu_to_le16(1);
-	else
-		nsindex->minor = cpu_to_le16(2);
-	nsindex->checksum = cpu_to_le64(0);
-	/* init label bitmap */
-	memset(nsindex->free, 0xff, ALIGN(nslot, BITS_PER_LONG) / 8);
-	checksum = fletcher64(nsindex, sizeof_namespace_index(ndd), 1);
-	nsindex->checksum = cpu_to_le64(checksum);
-	return nvdimm_set_config_data(ndd, le64_to_cpu(nsindex->myoff),
-			nsindex, sizeof_namespace_index(ndd));
-}
-
 static struct parameters {
 	const char *bus;
 	const char *outfile;
@@ -753,76 +383,42 @@ static struct parameters {
 	.labelversion = "1.1",
 };
 
-static int __action_init(struct ndctl_dimm *dimm, int version, int chk_only)
+static int __action_init(struct ndctl_dimm *dimm,
+		enum ndctl_namespace_version version, int chk_only)
 {
-	struct nvdimm_data __ndd = { 0 }, *ndd = &__ndd;
 	struct ndctl_cmd *cmd_read;
-	int rc = 0, i;
-	ssize_t size;
+	int rc;
 
 	cmd_read = ndctl_dimm_read_labels(dimm);
 	if (!cmd_read)
 		return -ENXIO;
 
-	size = ndctl_cmd_cfg_read_get_size(cmd_read);
-	if (size < 0)
-		return size;
-
-	ndd->data = malloc(size);
-	if (!ndd->data)
-		return -ENOMEM;
-	rc = ndctl_cmd_cfg_read_get_data(cmd_read, ndd->data, size, 0);
-	if (rc < 0)
-		goto out;
-
-	ndd->dimm = dimm;
-	ndd->cmd_read = cmd_read;
-	ndd->config_size = size;
-	ndd->nsindex_size = 0;
-	ndd->ns_current = -1;
-	ndd->ns_next = -1;
-	log_init(&ndd->ctx, ndctl_dimm_get_devname(dimm), "NDCTL_INIT_LABELS");
-	if (param.verbose)
-		ndd->ctx.log_priority = LOG_DEBUG;
-
 	/*
 	 * If the region goes active after this point, i.e. we're racing
 	 * another administrative action, the kernel will fail writes to
 	 * the label area.
 	 */
 	if (!chk_only && ndctl_dimm_is_active(dimm)) {
-		err(ndd, "regions active, abort label write\n");
+		fprintf(stderr, "%s: regions active, abort label write\n",
+				ndctl_dimm_get_devname(dimm));
 		rc = -EBUSY;
 		goto out;
 	}
 
-	rc = label_validate(ndd);
-	if (chk_only) {
-		rc = rc >= 0 ? 0 : -ENXIO;
+	rc = ndctl_dimm_validate_labels(dimm);
+	if (chk_only)
 		goto out;
-	}
 
 	if (rc >= 0 && !param.force) {
-		err(ndd, "error: labels already initialized\n");
+		fprintf(stderr, "%s: error: labels already initialized\n",
+				ndctl_dimm_get_devname(dimm));
 		rc = -EBUSY;
 		goto out;
 	}
 
-	/*
-	 * We may have initialized ndd to whatever labelsize is
-	 * currently on the dimm during label_validate(), so we reset it
-	 * to the desired version here.
-	 */
-	if (version > 1)
-		ndd->nslabel_size = 256;
-	else
-		ndd->nslabel_size = 128;
-
-	for (i = 0; i < 2; i++) {
-		rc = label_write_index(ndd, i, i*2);
-		if (rc)
-			goto out;
-	}
+	rc = ndctl_dimm_init_labels(dimm, version);
+	if (rc < 0)
+		goto out;
 
 	/*
 	 * If the dimm is already disabled the kernel is not holding a cached
@@ -838,7 +434,6 @@ static int __action_init(struct ndctl_dimm *dimm, int version, int chk_only)
 
  out:
 	ndctl_cmd_unref(cmd_read);
-	free(ndd->data);
 	return rc;
 }
 
@@ -966,13 +561,13 @@ static int dimm_action(int argc, const char **argv, void *ctx,
 		ndctl_set_log_priority(ctx, LOG_DEBUG);
 
 	if (strcmp(param.labelversion, "1.1") == 0)
-		actx.labelversion = 1;
+		actx.labelversion = NDCTL_NS_VERSION_1_1;
 	else if (strcmp(param.labelversion, "v1.1") == 0)
-		actx.labelversion = 1;
+		actx.labelversion = NDCTL_NS_VERSION_1_1;
 	else if (strcmp(param.labelversion, "1.2") == 0)
-		actx.labelversion = 2;
+		actx.labelversion = NDCTL_NS_VERSION_1_2;
 	else if (strcmp(param.labelversion, "v1.2") == 0)
-		actx.labelversion = 2;
+		actx.labelversion = NDCTL_NS_VERSION_1_2;
 	else {
 		fprintf(stderr, "'%s' is not a valid label version\n",
 				param.labelversion);
diff --git a/ndctl/lib/dimm.c b/ndctl/lib/dimm.c
index f7696af04ba2..212e9189c5b6 100644
--- a/ndctl/lib/dimm.c
+++ b/ndctl/lib/dimm.c
@@ -10,11 +10,454 @@
  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
  * more details.
  */
+#include <ndctl/namespace.h>
 #include <ndctl/libndctl.h>
+#include <util/fletcher.h>
 #include <util/sysfs.h>
 #include <stdlib.h>
 #include "private.h"
 
+static const char NSINDEX_SIGNATURE[] = "NAMESPACE_INDEX\0";
+
+/*
+ * Note, best_seq(), inc_seq(), sizeof_namespace_index()
+ * nvdimm_num_label_slots(), label_validate(), and label_write_index()
+ * are copied from drivers/nvdimm/label.c in the Linux kernel with the
+ * following modifications:
+ * 1/ s,nd_,,gc
+ * 2/ s,ndd->nsarea.config_size,ndd->config_size,gc
+ * 3/ s,dev_dbg(dev,dbg(ctx,gc
+ * 4/ s,__le,le,gc
+ * 5/ s,__cpu_to,cpu_to,gc
+ * 6/ remove flags argument to label_write_index
+ * 7/ dropped clear_bit_le() usage in label_write_index
+ * 8/ s,nvdimm_drvdata,nvdimm_data,gc
+ */
+static unsigned inc_seq(unsigned seq)
+{
+	static const unsigned next[] = { 0, 2, 3, 1 };
+
+	return next[seq & 3];
+}
+
+static u32 best_seq(u32 a, u32 b)
+{
+	a &= NSINDEX_SEQ_MASK;
+	b &= NSINDEX_SEQ_MASK;
+
+	if (a == 0 || a == b)
+		return b;
+	else if (b == 0)
+		return a;
+	else if (inc_seq(a) == b)
+		return b;
+	else
+		return a;
+}
+
+static struct ndctl_dimm *to_dimm(struct nvdimm_data *ndd)
+{
+	return container_of(ndd, struct ndctl_dimm, ndd);
+}
+
+static unsigned int sizeof_namespace_label(struct nvdimm_data *ndd)
+{
+	return ndctl_dimm_sizeof_namespace_label(to_dimm(ndd));
+}
+
+static unsigned int sizeof_namespace_index(struct nvdimm_data *ndd)
+{
+	u32 index_span;
+
+	if (ndd->nsindex_size)
+		return ndd->nsindex_size;
+
+	/*
+	 * The minimum index space is 512 bytes, with that amount of
+	 * index we can describe ~1400 labels which is less than a byte
+	 * of overhead per label.  Round up to a byte of overhead per
+	 * label and determine the size of the index region.  Yes, this
+	 * starts to waste space at larger config_sizes, but it's
+	 * unlikely we'll ever see anything but 128K.
+	 */
+	index_span = ndd->config_size / (sizeof_namespace_label(ndd) + 1);
+	index_span /= NSINDEX_ALIGN * 2;
+	ndd->nsindex_size = index_span * NSINDEX_ALIGN;
+
+	return ndd->nsindex_size;
+}
+
+static int nvdimm_num_label_slots(struct nvdimm_data *ndd)
+{
+	return ndd->config_size / (sizeof_namespace_label(ndd) + 1);
+}
+
+static struct namespace_index *to_namespace_index(struct nvdimm_data *ndd,
+		int i)
+{
+	char *index;
+
+	if (i < 0)
+		return NULL;
+
+	index = (char *) ndd->data + sizeof_namespace_index(ndd) * i;
+	return (struct namespace_index *) index;
+}
+
+static int __label_validate(struct nvdimm_data *ndd)
+{
+	struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(to_dimm(ndd));
+
+	/*
+	 * On media label format consists of two index blocks followed
+	 * by an array of labels.  None of these structures are ever
+	 * updated in place.  A sequence number tracks the current
+	 * active index and the next one to write, while labels are
+	 * written to free slots.
+	 *
+	 *     +------------+
+	 *     |            |
+	 *     |  nsindex0  |
+	 *     |            |
+	 *     +------------+
+	 *     |            |
+	 *     |  nsindex1  |
+	 *     |            |
+	 *     +------------+
+	 *     |   label0   |
+	 *     +------------+
+	 *     |   label1   |
+	 *     +------------+
+	 *     |            |
+	 *      ....nslot...
+	 *     |            |
+	 *     +------------+
+	 *     |   labelN   |
+	 *     +------------+
+	 */
+	struct namespace_index *nsindex[] = {
+		to_namespace_index(ndd, 0),
+		to_namespace_index(ndd, 1),
+	};
+	const int num_index = ARRAY_SIZE(nsindex);
+	bool valid[2] = { 0 };
+	int i, num_valid = 0;
+	u32 seq;
+
+	for (i = 0; i < num_index; i++) {
+		u32 nslot;
+		u8 sig[NSINDEX_SIG_LEN];
+		u64 sum_save, sum, size;
+		unsigned int version, labelsize;
+
+		memcpy(sig, nsindex[i]->sig, NSINDEX_SIG_LEN);
+		if (memcmp(sig, NSINDEX_SIGNATURE, NSINDEX_SIG_LEN) != 0) {
+			dbg(ctx, "nsindex%d signature invalid\n", i);
+			continue;
+		}
+
+		/* label sizes larger than 128 arrived with v1.2 */
+		version = le16_to_cpu(nsindex[i]->major) * 100
+			+ le16_to_cpu(nsindex[i]->minor);
+		if (version >= 102)
+			labelsize = 1 << (7 + nsindex[i]->labelsize);
+		else
+			labelsize = 128;
+
+		if (labelsize != sizeof_namespace_label(ndd)) {
+			dbg(ctx, "nsindex%d labelsize %d invalid\n",
+					i, nsindex[i]->labelsize);
+			continue;
+		}
+
+		sum_save = le64_to_cpu(nsindex[i]->checksum);
+		nsindex[i]->checksum = cpu_to_le64(0);
+		sum = fletcher64(nsindex[i], sizeof_namespace_index(ndd), 1);
+		nsindex[i]->checksum = cpu_to_le64(sum_save);
+		if (sum != sum_save) {
+			dbg(ctx, "nsindex%d checksum invalid\n", i);
+			continue;
+		}
+
+		seq = le32_to_cpu(nsindex[i]->seq);
+		if ((seq & NSINDEX_SEQ_MASK) == 0) {
+			dbg(ctx, "nsindex%d sequence: %#x invalid\n", i, seq);
+			continue;
+		}
+
+		/* sanity check the index against expected values */
+		if (le64_to_cpu(nsindex[i]->myoff)
+				!= i * sizeof_namespace_index(ndd)) {
+			dbg(ctx, "nsindex%d myoff: %#llx invalid\n",
+					i, (unsigned long long)
+					le64_to_cpu(nsindex[i]->myoff));
+			continue;
+		}
+		if (le64_to_cpu(nsindex[i]->otheroff)
+				!= (!i) * sizeof_namespace_index(ndd)) {
+			dbg(ctx, "nsindex%d otheroff: %#llx invalid\n",
+					i, (unsigned long long)
+					le64_to_cpu(nsindex[i]->otheroff));
+			continue;
+		}
+
+		size = le64_to_cpu(nsindex[i]->mysize);
+		if (size > sizeof_namespace_index(ndd)
+				|| size < sizeof(struct namespace_index)) {
+			dbg(ctx, "nsindex%d mysize: %#zx invalid\n", i, size);
+			continue;
+		}
+
+		nslot = le32_to_cpu(nsindex[i]->nslot);
+		if (nslot * sizeof_namespace_label(ndd)
+				+ 2 * sizeof_namespace_index(ndd)
+				> ndd->config_size) {
+			dbg(ctx, "nsindex%d nslot: %u invalid, config_size: %#zx\n",
+					i, nslot, ndd->config_size);
+			continue;
+		}
+		valid[i] = true;
+		num_valid++;
+	}
+
+	switch (num_valid) {
+	case 0:
+		break;
+	case 1:
+		for (i = 0; i < num_index; i++)
+			if (valid[i])
+				return i;
+		/* can't have num_valid > 0 but valid[] = { false, false } */
+		err(ctx, "unexpected index-block parse error\n");
+		break;
+	default:
+		/* pick the best index... */
+		seq = best_seq(le32_to_cpu(nsindex[0]->seq),
+				le32_to_cpu(nsindex[1]->seq));
+		if (seq == (le32_to_cpu(nsindex[1]->seq) & NSINDEX_SEQ_MASK))
+			return 1;
+		else
+			return 0;
+		break;
+	}
+
+	return -EINVAL;
+}
+
+/*
+ * If the dimm labels have not been previously validated this routine
+ * will make up a default size. Otherwise, it will pick the size based
+ * on what version is specified in the index block.
+ */
+NDCTL_EXPORT unsigned int ndctl_dimm_sizeof_namespace_label(struct ndctl_dimm *dimm)
+{
+	struct nvdimm_data *ndd = &dimm->ndd;
+	struct namespace_index nsindex;
+	ssize_t offset, size;
+	int v1 = 0, v2 = 0;
+
+	if (ndd && ndd->nslabel_size)
+		return ndd->nslabel_size;
+
+	for (offset = 0; offset < NSINDEX_ALIGN * 2; offset += NSINDEX_ALIGN) {
+		ssize_t len = (ssize_t) sizeof(nsindex);
+
+		len = ndctl_cmd_cfg_read_get_data(ndd->cmd_read, &nsindex,
+				len, offset);
+		if (len < 0)
+			break;
+
+		/*
+		 * Since we're doing a best effort parsing we don't
+		 * fully validate the index block. Instead just assume
+		 * v1.1 unless there's 2 index blocks that say v1.2.
+		 */
+		if (le16_to_cpu(nsindex.major) == 1) {
+			if (le16_to_cpu(nsindex.minor) == 1)
+				v1++;
+			else if (le16_to_cpu(nsindex.minor) == 2)
+				v2++;
+		}
+	}
+
+	if (v2 > v1)
+		size = 256;
+	else
+		size = 128;
+	if (ndd)
+		ndd->nslabel_size = size;
+	return size;
+}
+
+static int label_validate(struct nvdimm_data *ndd)
+{
+	/*
+	 * In order to probe for and validate namespace index blocks we
+	 * need to know the size of the labels, and we can't trust the
+	 * size of the labels until we validate the index blocks.
+	 * Resolve this dependency loop by probing for known label
+	 * sizes, but default to v1.2 256-byte namespace labels if
+	 * discovery fails.
+	 */
+	int label_size[] = { 128, 256 };
+	int i, rc;
+
+	for (i = 0; (size_t) i < ARRAY_SIZE(label_size); i++) {
+		ndd->nslabel_size = label_size[i];
+		rc = __label_validate(ndd);
+		if (rc >= 0)
+			return nvdimm_num_label_slots(ndd);
+	}
+
+	return -EINVAL;
+}
+
+static int nvdimm_set_config_data(struct nvdimm_data *ndd, size_t offset,
+		void *buf, size_t len)
+{
+	struct ndctl_cmd *cmd_write;
+	int rc;
+
+	cmd_write = ndctl_dimm_cmd_new_cfg_write(ndd->cmd_read);
+	if (!cmd_write)
+		return -ENXIO;
+
+	rc = ndctl_cmd_cfg_write_set_data(cmd_write, buf, len, offset);
+	if (rc < 0)
+		goto out;
+
+	rc = ndctl_cmd_submit(cmd_write);
+	if (rc || ndctl_cmd_get_firmware_status(cmd_write))
+		rc = -ENXIO;
+ out:
+	ndctl_cmd_unref(cmd_write);
+	return rc;
+}
+
+static int label_next_nsindex(int index)
+{
+	if (index < 0)
+		return -1;
+	return (index + 1) % 2;
+}
+
+static struct namespace_label *label_base(struct nvdimm_data *ndd)
+{
+	char *base = (char *) to_namespace_index(ndd, 0);
+
+	base += 2 * sizeof_namespace_index(ndd);
+	return (struct namespace_label *) base;
+}
+
+static void init_ndd(struct nvdimm_data *ndd, struct ndctl_cmd *cmd_read)
+{
+	ndctl_cmd_unref(ndd->cmd_read);
+	memset(ndd, 0, sizeof(*ndd));
+	ndd->cmd_read = cmd_read;
+	ndctl_cmd_ref(cmd_read);
+	ndd->data = cmd_read->iter.total_buf;
+	ndd->config_size = cmd_read->iter.total_xfer;
+	ndd->nsindex_size = 0;
+	ndd->ns_current = -1;
+	ndd->ns_next = -1;
+}
+
+static int write_label_index(struct ndctl_dimm *dimm,
+		enum ndctl_namespace_version ver, unsigned index, unsigned seq)
+{
+	struct nvdimm_data *ndd = &dimm->ndd;
+	struct namespace_index *nsindex;
+	unsigned long offset;
+	u64 checksum;
+	u32 nslot;
+
+	/*
+	 * We may have initialized ndd to whatever labelsize is
+	 * currently on the dimm during label_validate(), so we reset it
+	 * to the desired version here.
+	 */
+	switch (ver) {
+	case NDCTL_NS_VERSION_1_1:
+		ndd->nslabel_size = 128;
+		break;
+	case NDCTL_NS_VERSION_1_2:
+		ndd->nslabel_size = 256;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	nsindex = to_namespace_index(ndd, index);
+	nslot = nvdimm_num_label_slots(ndd);
+
+	memcpy(nsindex->sig, NSINDEX_SIGNATURE, NSINDEX_SIG_LEN);
+	memset(nsindex->flags, 0, 3);
+	nsindex->labelsize = sizeof_namespace_label(ndd) >> 8;
+	nsindex->seq = cpu_to_le32(seq);
+	offset = (unsigned long) nsindex
+		- (unsigned long) to_namespace_index(ndd, 0);
+	nsindex->myoff = cpu_to_le64(offset);
+	nsindex->mysize = cpu_to_le64(sizeof_namespace_index(ndd));
+	offset = (unsigned long) to_namespace_index(ndd,
+			label_next_nsindex(index))
+		- (unsigned long) to_namespace_index(ndd, 0);
+	nsindex->otheroff = cpu_to_le64(offset);
+	offset = (unsigned long) label_base(ndd)
+		- (unsigned long) to_namespace_index(ndd, 0);
+	nsindex->labeloff = cpu_to_le64(offset);
+	nsindex->nslot = cpu_to_le32(nslot);
+	nsindex->major = cpu_to_le16(1);
+	if (sizeof_namespace_label(ndd) < 256)
+		nsindex->minor = cpu_to_le16(1);
+	else
+		nsindex->minor = cpu_to_le16(2);
+	nsindex->checksum = cpu_to_le64(0);
+	/* init label bitmap */
+	memset(nsindex->free, 0xff, ALIGN(nslot, BITS_PER_LONG) / 8);
+	checksum = fletcher64(nsindex, sizeof_namespace_index(ndd), 1);
+	nsindex->checksum = cpu_to_le64(checksum);
+	return nvdimm_set_config_data(ndd, le64_to_cpu(nsindex->myoff),
+			nsindex, sizeof_namespace_index(ndd));
+}
+
+NDCTL_EXPORT int ndctl_dimm_init_labels(struct ndctl_dimm *dimm,
+		enum ndctl_namespace_version v)
+{
+	struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
+	struct nvdimm_data *ndd = &dimm->ndd;
+	int i;
+
+	if (!ndd->cmd_read) {
+		err(ctx, "%s: needs to be initialized by ndctl_dimm_read_labels\n",
+				ndctl_dimm_get_devname(dimm));
+		return -EINVAL;
+	}
+
+	for (i = 0; i < 2; i++) {
+		int rc;
+
+		rc = write_label_index(dimm, v, i, i*2);
+		if (rc < 0)
+			return rc;
+	}
+
+	return nvdimm_num_label_slots(ndd);
+}
+
+NDCTL_EXPORT int ndctl_dimm_validate_labels(struct ndctl_dimm *dimm)
+{
+	struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
+	struct nvdimm_data *ndd = &dimm->ndd;
+
+	if (!ndd->cmd_read) {
+		err(ctx, "%s: needs to be initialized by ndctl_dimm_read_labels\n",
+				ndctl_dimm_get_devname(dimm));
+		return -EINVAL;
+	}
+
+	return label_validate(&dimm->ndd);
+}
+
 NDCTL_EXPORT struct ndctl_cmd *ndctl_dimm_read_labels(struct ndctl_dimm *dimm)
 {
         struct ndctl_bus *bus = ndctl_dimm_get_bus(dimm);
@@ -38,9 +481,11 @@ NDCTL_EXPORT struct ndctl_cmd *ndctl_dimm_read_labels(struct ndctl_dimm *dimm)
         rc = ndctl_cmd_submit(cmd_read);
         if (rc || ndctl_cmd_get_firmware_status(cmd_read))
                 goto out_read;
+	ndctl_cmd_unref(cmd_size);
 
-        ndctl_cmd_unref(cmd_size);
-        return cmd_read;
+	init_ndd(&dimm->ndd, cmd_read);
+
+	return cmd_read;
 
  out_read:
         ndctl_cmd_unref(cmd_read);
@@ -118,5 +563,3 @@ NDCTL_EXPORT unsigned long ndctl_dimm_get_available_labels(
 
 	return strtoul(buf, NULL, 0);
 }
-
-
diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
index 86abeb6cc577..17fc8ee4ce00 100644
--- a/ndctl/lib/libndctl.c
+++ b/ndctl/lib/libndctl.c
@@ -560,6 +560,7 @@ static void free_dimm(struct ndctl_dimm *dimm)
 		kmod_module_unref(dimm->module);
 	if (dimm->health_eventfd > -1)
 		close(dimm->health_eventfd);
+	ndctl_cmd_unref(dimm->ndd.cmd_read);
 	free(dimm);
 }
 
diff --git a/ndctl/lib/libndctl.sym b/ndctl/lib/libndctl.sym
index 95c6e400124d..4c1773daa861 100644
--- a/ndctl/lib/libndctl.sym
+++ b/ndctl/lib/libndctl.sym
@@ -114,7 +114,10 @@ global:
 	ndctl_cmd_smart_threshold_get_spares;
 	ndctl_dimm_zero_labels;
 	ndctl_dimm_read_labels;
+	ndctl_dimm_validate_labels;
+	ndctl_dimm_init_labels;
 	ndctl_dimm_get_available_labels;
+	ndctl_dimm_sizeof_namespace_label;
 	ndctl_region_get_first;
 	ndctl_region_get_next;
 	ndctl_region_get_id;
diff --git a/ndctl/lib/private.h b/ndctl/lib/private.h
index 64906b8123d0..808e77da07ca 100644
--- a/ndctl/lib/private.h
+++ b/ndctl/lib/private.h
@@ -34,6 +34,15 @@
 #include "hpe1.h"
 #include "msft.h"
 
+struct nvdimm_data {
+	struct ndctl_cmd *cmd_read;
+	void *data;
+	unsigned long config_size;
+	size_t nslabel_size;
+	int nsindex_size;
+	int ns_current, ns_next;
+};
+
 /**
  * struct ndctl_dimm - memory device as identified by NFIT
  * @module: kernel module (libnvdimm)
@@ -56,6 +65,7 @@ struct ndctl_dimm {
 	struct kmod_module *module;
 	struct ndctl_bus *bus;
 	struct ndctl_smart_ops *smart_ops;
+	struct nvdimm_data ndd;
 	unsigned int handle, major, minor, serial;
 	unsigned short phys_id;
 	unsigned short vendor_id;
diff --git a/ndctl/libndctl.h.in b/ndctl/libndctl.h.in
index 9be380b8a735..2bbda046f130 100644
--- a/ndctl/libndctl.h.in
+++ b/ndctl/libndctl.h.in
@@ -359,7 +359,15 @@ struct ndctl_cmd *ndctl_dimm_cmd_new_cfg_read(struct ndctl_cmd *cfg_size);
 struct ndctl_cmd *ndctl_dimm_cmd_new_cfg_write(struct ndctl_cmd *cfg_read);
 int ndctl_dimm_zero_labels(struct ndctl_dimm *dimm);
 struct ndctl_cmd *ndctl_dimm_read_labels(struct ndctl_dimm *dimm);
+int ndctl_dimm_validate_labels(struct ndctl_dimm *dimm);
+enum ndctl_namespace_version {
+	NDCTL_NS_VERSION_1_1,
+	NDCTL_NS_VERSION_1_2,
+};
+int ndctl_dimm_init_labels(struct ndctl_dimm *dimm,
+		enum ndctl_namespace_version v);
 unsigned long ndctl_dimm_get_available_labels(struct ndctl_dimm *dimm);
+unsigned int ndctl_dimm_sizeof_namespace_label(struct ndctl_dimm *dimm);
 unsigned int ndctl_cmd_cfg_size_get_size(struct ndctl_cmd *cfg_size);
 ssize_t ndctl_cmd_cfg_read_get_data(struct ndctl_cmd *cfg_read, void *buf,
 		unsigned int len, unsigned int offset);
diff --git a/ndctl/namespace.h b/ndctl/namespace.h
index b466c2b96bd3..6d56468b8f89 100644
--- a/ndctl/namespace.h
+++ b/ndctl/namespace.h
@@ -12,6 +12,7 @@
  */
 #ifndef __NDCTL_NAMESPACE_H__
 #define __NDCTL_NAMESPACE_H__
+#include <sys/types.h>
 #include <util/size.h>
 #include <ccan/endian/endian.h>
 #include <ccan/short_types/short_types.h>
diff --git a/util/fletcher.c b/util/fletcher.c
deleted file mode 100644
index 29778db833f5..000000000000
--- a/util/fletcher.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright(c) 2015-2017 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-#include <stdlib.h>
-#include <stdbool.h>
-#include <util/fletcher.h>
-#include <ccan/endian/endian.h>
-#include <ccan/short_types/short_types.h>
-
-/*
- * Note, fletcher64() is copied from drivers/nvdimm/label.c in the Linux kernel
- */
-u64 fletcher64(void *addr, size_t len, bool le)
-{
-	u32 *buf = addr;
-	u32 lo32 = 0;
-	u64 hi32 = 0;
-	size_t i;
-
-	for (i = 0; i < len / sizeof(u32); i++) {
-		lo32 += le ? le32_to_cpu((le32) buf[i]) : buf[i];
-		hi32 += lo32;
-	}
-
-	return hi32 << 32 | lo32;
-}
diff --git a/util/fletcher.h b/util/fletcher.h
index e3bbce387702..54e2ecf5d6ed 100644
--- a/util/fletcher.h
+++ b/util/fletcher.h
@@ -1,8 +1,25 @@
 #ifndef _NDCTL_FLETCHER_H_
 #define _NDCTL_FLETCHER_H_
 
+#include <ccan/endian/endian.h>
 #include <ccan/short_types/short_types.h>
 
-u64 fletcher64(void *addr, size_t len, bool le);
+/*
+ * Note, fletcher64() is copied from drivers/nvdimm/label.c in the Linux kernel
+ */
+static inline u64 fletcher64(void *addr, size_t len, bool le)
+{
+	u32 *buf = addr;
+	u32 lo32 = 0;
+	u64 hi32 = 0;
+	size_t i;
+
+	for (i = 0; i < len / sizeof(u32); i++) {
+		lo32 += le ? le32_to_cpu((le32) buf[i]) : buf[i];
+		hi32 += lo32;
+	}
+
+	return hi32 << 32 | lo32;
+}
 
 #endif /* _NDCTL_FLETCHER_H_ */

_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [ndctl PATCH 7/7] ndctl: auto initialize labels
  2017-08-29 20:01 [ndctl PATCH 0/7] ndctl: automatically initialize labels Dan Williams
                   ` (5 preceding siblings ...)
  2017-08-29 20:02 ` [ndctl PATCH 6/7] ndctl: introduce ndctl_dimm_{validate_labels, init_labels} Dan Williams
@ 2017-08-29 20:02 ` Dan Williams
  2017-08-29 21:32   ` Verma, Vishal L
  6 siblings, 1 reply; 12+ messages in thread
From: Dan Williams @ 2017-08-29 20:02 UTC (permalink / raw)
  To: linux-nvdimm

If we are reconfiguring an ND_DEVICE_NAMESPACE_IO namespace take the
opportunity to potentially initialize labels. DIMM capacity that is not
aliased will surface as a label-less namespace by default. If every DIMM
in the interleave set supports labels we can switch a more dynamic
configuration, i.e. enable pmem sub-division.

The --no-autolabel option is added to disable this behavior if it is not
wanted.

Cc: Vishal Verma <vishal.l.verma@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 Documentation/ndctl/ndctl-create-namespace.txt |    7 ++
 ndctl/namespace.c                              |   90 +++++++++++++++++++++++-
 2 files changed, 95 insertions(+), 2 deletions(-)

diff --git a/Documentation/ndctl/ndctl-create-namespace.txt b/Documentation/ndctl/ndctl-create-namespace.txt
index 85d1f8db792f..3844ff74a9f1 100644
--- a/Documentation/ndctl/ndctl-create-namespace.txt
+++ b/Documentation/ndctl/ndctl-create-namespace.txt
@@ -138,6 +138,13 @@ OPTIONS
 	active.  Specifying --force causes the namespace to be disabled
 	before reconfiguring.
 
+-L::
+--autolabel::
+	When ndctl encounters a label-less namespace while
+	performing a reconfigure operation it will try to enable labels
+	for the region. This behavior can be suppressed with
+	"--no-autolabel".
+
 -v::
 --verbose::
 	Emit debug messages for the namespace creation process
diff --git a/ndctl/namespace.c b/ndctl/namespace.c
index 6cfd873da248..b6381c5822de 100644
--- a/ndctl/namespace.c
+++ b/ndctl/namespace.c
@@ -42,6 +42,7 @@ static struct parameters {
 	bool do_scan;
 	bool mode_default;
 	bool align_default;
+	bool autolabel;
 	const char *bus;
 	const char *map;
 	const char *type;
@@ -53,7 +54,9 @@ static struct parameters {
 	const char *reconfig;
 	const char *sector_size;
 	const char *align;
-} param;
+} param = {
+	.autolabel = true,
+};
 
 void builtin_xaction_namespace_reset(void)
 {
@@ -76,6 +79,7 @@ struct parsed_parameters {
 	unsigned long long size;
 	unsigned long sector_size;
 	unsigned long align;
+	bool autolabel;
 };
 
 #define debug(fmt, ...) \
@@ -111,7 +115,8 @@ OPT_STRING('t', "type", &param.type, "type", \
 	"specify the type of namespace to create 'pmem' or 'blk'"), \
 OPT_STRING('a', "align", &param.align, "align", \
 	"specify the namespace alignment in bytes (default: 2M)"), \
-OPT_BOOLEAN('f', "force", &force, "reconfigure namespace even if currently active")
+OPT_BOOLEAN('f', "force", &force, "reconfigure namespace even if currently active"), \
+OPT_BOOLEAN('L', "autolabel", &param.autolabel, "automatically initialize labels")
 
 #define CHECK_OPTIONS() \
 OPT_BOOLEAN('R', "repair", &repair, "perform metadata repairs"), \
@@ -675,6 +680,8 @@ static int validate_namespace_options(struct ndctl_region *region,
 		}
 	}
 
+	p->autolabel = param.autolabel;
+
 	return 0;
 }
 
@@ -810,6 +817,80 @@ static int namespace_destroy(struct ndctl_region *region,
 	return 0;
 }
 
+static void enable_labels(struct ndctl_region *region)
+{
+	int mappings = ndctl_region_get_mappings(region);
+	struct ndctl_cmd *cmd_read = NULL;
+	enum ndctl_namespace_version v;
+	struct ndctl_dimm *dimm;
+	int count;
+
+	/* no dimms => no labels */
+	if (!mappings)
+		return;
+
+	count = 0;
+	ndctl_dimm_foreach_in_region(region, dimm) {
+		if (!ndctl_dimm_is_cmd_supported(dimm, ND_CMD_GET_CONFIG_SIZE))
+			break;
+		if (!ndctl_dimm_is_cmd_supported(dimm, ND_CMD_GET_CONFIG_DATA))
+			break;
+		if (!ndctl_dimm_is_cmd_supported(dimm, ND_CMD_SET_CONFIG_DATA))
+			break;
+		count++;
+	}
+
+	/* all the dimms must support labelling */
+	if (count != mappings)
+		return;
+
+	ndctl_region_disable_invalidate(region);
+	count = 0;
+	ndctl_dimm_foreach_in_region(region, dimm)
+		if (ndctl_dimm_is_active(dimm)) {
+			count++;
+			break;
+		}
+
+	/* some of the dimms belong to multiple regions?? */
+	if (count)
+		goto out;
+
+	v = NDCTL_NS_VERSION_1_2;
+retry:
+	ndctl_dimm_foreach_in_region(region, dimm) {
+		int num_labels, avail;
+
+		ndctl_cmd_unref(cmd_read);
+		cmd_read = ndctl_dimm_read_labels(dimm);
+		if (!cmd_read)
+			continue;
+
+		num_labels = ndctl_dimm_init_labels(dimm, v);
+		if (num_labels < 0)
+			continue;
+
+		ndctl_dimm_disable(dimm);
+		ndctl_dimm_enable(dimm);
+
+		/*
+		 * If the kernel appears to not understand v1.2 labels,
+		 * try v1.1. Note, we increment avail by 1 to account
+		 * for the one free label that the kernel always
+		 * maintains for ongoing updates.
+		 */
+		avail = ndctl_dimm_get_available_labels(dimm) + 1;
+		if (num_labels != avail && v == NDCTL_NS_VERSION_1_2) {
+			v = NDCTL_NS_VERSION_1_1;
+			goto retry;
+		}
+
+	}
+	ndctl_cmd_unref(cmd_read);
+out:
+	ndctl_region_enable(region);
+}
+
 static int namespace_reconfig(struct ndctl_region *region,
 		struct ndctl_namespace *ndns)
 {
@@ -824,6 +905,11 @@ static int namespace_reconfig(struct ndctl_region *region,
 	if (rc)
 		return rc;
 
+	/* check if we can enable labels on this region */
+	if (ndctl_namespace_get_type(ndns) == ND_DEVICE_NAMESPACE_IO
+			&& p.autolabel)
+		enable_labels(region);
+
 	ndns = region_get_namespace(region);
 	if (!ndns || is_namespace_active(ndns)) {
 		debug("%s: no %s namespace seed\n",

_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [ndctl PATCH 7/7] ndctl: auto initialize labels
  2017-08-29 20:02 ` [ndctl PATCH 7/7] ndctl: auto initialize labels Dan Williams
@ 2017-08-29 21:32   ` Verma, Vishal L
  2017-08-29 21:48     ` Dan Williams
  0 siblings, 1 reply; 12+ messages in thread
From: Verma, Vishal L @ 2017-08-29 21:32 UTC (permalink / raw)
  To: Williams, Dan J, linux-nvdimm

On Tue, 2017-08-29 at 13:02 -0700, Dan Williams wrote:
> If we are reconfiguring an ND_DEVICE_NAMESPACE_IO namespace take the
> opportunity to potentially initialize labels. DIMM capacity that is
> not
> aliased will surface as a label-less namespace by default. If every
> DIMM
> in the interleave set supports labels we can switch a more dynamic
> configuration, i.e. enable pmem sub-division.
> 
> The --no-autolabel option is added to disable this behavior if it is
> not
> wanted.
> 
> Cc: Vishal Verma <vishal.l.verma@intel.com>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> ---
>  Documentation/ndctl/ndctl-create-namespace.txt |    7 ++
>  ndctl/namespace.c                              |   90
> +++++++++++++++++++++++-
>  2 files changed, 95 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/ndctl/ndctl-create-namespace.txt
> b/Documentation/ndctl/ndctl-create-namespace.txt
> index 85d1f8db792f..3844ff74a9f1 100644
> --- a/Documentation/ndctl/ndctl-create-namespace.txt
> +++ b/Documentation/ndctl/ndctl-create-namespace.txt
> @@ -138,6 +138,13 @@ OPTIONS
>  	active.  Specifying --force causes the namespace to be
> disabled
>  	before reconfiguring.
>  
> +-L::
> +--autolabel::

Shouldn't this be --no-autolabel

> +	When ndctl encounters a label-less namespace while
> +	performing a reconfigure operation it will try to enable
> labels
> +	for the region. This behavior can be suppressed with
> +	"--no-autolabel".

And the text description matched to describe only the --no-autolabel
option instead of describing both a positive and negative

> +
>  -v::
>  --verbose::
>  	Emit debug messages for the namespace creation process
> 

[...]

> +
> +	/* all the dimms must support labelling */

s/labelling/labeling/

> +	if (count != mappings)
> +		return;
> +
> +	ndctl_region_disable_invalidate(region);
> +	count = 0;
> +	ndctl_dimm_foreach_in_region(region, dimm)
> +		if (ndctl_dimm_is_active(dimm)) {
> +			count++;
> +			break;
> +		}
> +
> +	/* some of the dimms belong to multiple regions?? */
> +	if (count)
> +		goto out;
> +
> +	v = NDCTL_NS_VERSION_1_2;
> +retry:
> +	ndctl_dimm_foreach_in_region(region, dimm) {
> +		int num_labels, avail;
> +
> +		ndctl_cmd_unref(cmd_read);
> +		cmd_read = ndctl_dimm_read_labels(dimm);
> +		if (!cmd_read)
> +			continue;
> +
> +		num_labels = ndctl_dimm_init_labels(dimm, v);
> +		if (num_labels < 0)
> +			continue;
> +
> +		ndctl_dimm_disable(dimm);
> +		ndctl_dimm_enable(dimm);
> +
> +		/*
> +		 * If the kernel appears to not understand v1.2
> labels,
> +		 * try v1.1. Note, we increment avail by 1 to account
> +		 * for the one free label that the kernel always
> +		 * maintains for ongoing updates.
> +		 */
> +		avail = ndctl_dimm_get_available_labels(dimm) + 1;
> +		if (num_labels != avail && v == NDCTL_NS_VERSION_1_2)
> {
> +			v = NDCTL_NS_VERSION_1_1;
> +			goto retry;
> +		}
> +
> +	}
> +	ndctl_cmd_unref(cmd_read);
> +out:
> +	ndctl_region_enable(region);
> +}
> +
>  static int namespace_reconfig(struct ndctl_region *region,
>  		struct ndctl_namespace *ndns)
>  {
> @@ -824,6 +905,11 @@ static int namespace_reconfig(struct ndctl_region
> *region,
>  	if (rc)
>  		return rc;
>  
> +	/* check if we can enable labels on this region */
> +	if (ndctl_namespace_get_type(ndns) == ND_DEVICE_NAMESPACE_IO
> +			&& p.autolabel)
> +		enable_labels(region);
> +
>  	ndns = region_get_namespace(region);
>  	if (!ndns || is_namespace_active(ndns)) {
>  		debug("%s: no %s namespace seed\n",
> 
_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [ndctl PATCH 7/7] ndctl: auto initialize labels
  2017-08-29 21:32   ` Verma, Vishal L
@ 2017-08-29 21:48     ` Dan Williams
  2017-08-29 21:52       ` Verma, Vishal L
  0 siblings, 1 reply; 12+ messages in thread
From: Dan Williams @ 2017-08-29 21:48 UTC (permalink / raw)
  To: Verma, Vishal L; +Cc: linux-nvdimm

On Tue, Aug 29, 2017 at 2:32 PM, Verma, Vishal L
<vishal.l.verma@intel.com> wrote:
> On Tue, 2017-08-29 at 13:02 -0700, Dan Williams wrote:
>> If we are reconfiguring an ND_DEVICE_NAMESPACE_IO namespace take the
>> opportunity to potentially initialize labels. DIMM capacity that is
>> not
>> aliased will surface as a label-less namespace by default. If every
>> DIMM
>> in the interleave set supports labels we can switch a more dynamic
>> configuration, i.e. enable pmem sub-division.
>>
>> The --no-autolabel option is added to disable this behavior if it is
>> not
>> wanted.
>>
>> Cc: Vishal Verma <vishal.l.verma@intel.com>
>> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
>> ---
>>  Documentation/ndctl/ndctl-create-namespace.txt |    7 ++
>>  ndctl/namespace.c                              |   90
>> +++++++++++++++++++++++-
>>  2 files changed, 95 insertions(+), 2 deletions(-)
>>
>> diff --git a/Documentation/ndctl/ndctl-create-namespace.txt
>> b/Documentation/ndctl/ndctl-create-namespace.txt
>> index 85d1f8db792f..3844ff74a9f1 100644
>> --- a/Documentation/ndctl/ndctl-create-namespace.txt
>> +++ b/Documentation/ndctl/ndctl-create-namespace.txt
>> @@ -138,6 +138,13 @@ OPTIONS
>>       active.  Specifying --force causes the namespace to be
>> disabled
>>       before reconfiguring.
>>
>> +-L::
>> +--autolabel::
>
> Shouldn't this be --no-autolabel
>
>> +     When ndctl encounters a label-less namespace while
>> +     performing a reconfigure operation it will try to enable
>> labels
>> +     for the region. This behavior can be suppressed with
>> +     "--no-autolabel".
>
> And the text description matched to describe only the --no-autolabel
> option instead of describing both a positive and negative

I'm using a side effect of the way ndctl (and git) implement
OPT_BOOLEAN() options. They all automatically get a --no-<option>. So
"--autolabel" is the default.

>
>> +
>>  -v::
>>  --verbose::
>>       Emit debug messages for the namespace creation process
>>
>
> [...]
>
>> +
>> +     /* all the dimms must support labelling */
>
> s/labelling/labeling/

Yup, thanks.
_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [ndctl PATCH 7/7] ndctl: auto initialize labels
  2017-08-29 21:48     ` Dan Williams
@ 2017-08-29 21:52       ` Verma, Vishal L
  2017-08-29 22:43         ` Vishal Verma
  0 siblings, 1 reply; 12+ messages in thread
From: Verma, Vishal L @ 2017-08-29 21:52 UTC (permalink / raw)
  To: Williams, Dan J; +Cc: linux-nvdimm

On Tue, 2017-08-29 at 14:48 -0700, Dan Williams wrote:
> On Tue, Aug 29, 2017 at 2:32 PM, Verma, Vishal L
> <vishal.l.verma@intel.com> wrote:
> > On Tue, 2017-08-29 at 13:02 -0700, Dan Williams wrote:
> > > If we are reconfiguring an ND_DEVICE_NAMESPACE_IO namespace take
> > > the
> > > opportunity to potentially initialize labels. DIMM capacity that
> > > is
> > > not
> > > aliased will surface as a label-less namespace by default. If
> > > every
> > > DIMM
> > > in the interleave set supports labels we can switch a more dynamic
> > > configuration, i.e. enable pmem sub-division.
> > > 
> > > The --no-autolabel option is added to disable this behavior if it
> > > is
> > > not
> > > wanted.
> > > 
> > > Cc: Vishal Verma <vishal.l.verma@intel.com>
> > > Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> > > ---
> > >  Documentation/ndctl/ndctl-create-namespace.txt |    7 ++
> > >  ndctl/namespace.c                              |   90
> > > +++++++++++++++++++++++-
> > >  2 files changed, 95 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/Documentation/ndctl/ndctl-create-namespace.txt
> > > b/Documentation/ndctl/ndctl-create-namespace.txt
> > > index 85d1f8db792f..3844ff74a9f1 100644
> > > --- a/Documentation/ndctl/ndctl-create-namespace.txt
> > > +++ b/Documentation/ndctl/ndctl-create-namespace.txt
> > > @@ -138,6 +138,13 @@ OPTIONS
> > >       active.  Specifying --force causes the namespace to be
> > > disabled
> > >       before reconfiguring.
> > > 
> > > +-L::
> > > +--autolabel::
> > 
> > Shouldn't this be --no-autolabel
> > 
> > > +     When ndctl encounters a label-less namespace while
> > > +     performing a reconfigure operation it will try to enable
> > > labels
> > > +     for the region. This behavior can be suppressed with
> > > +     "--no-autolabel".
> > 
> > And the text description matched to describe only the --no-autolabel
> > option instead of describing both a positive and negative
> 
> I'm using a side effect of the way ndctl (and git) implement
> OPT_BOOLEAN() options. They all automatically get a --no-<option>. So
> "--autolabel" is the default.
> 
Ah cool, I didn't know OPT_BOOLEAN does that for you.
Does the 'no' option then lack a short option? We'll end up providing a
short option for the default case, but nothing for the override..

I'm also wondering if there will be any bash completion implications.
I'll test whether the --no- option shows up automatically in --list-opts
_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [ndctl PATCH 7/7] ndctl: auto initialize labels
  2017-08-29 21:52       ` Verma, Vishal L
@ 2017-08-29 22:43         ` Vishal Verma
  0 siblings, 0 replies; 12+ messages in thread
From: Vishal Verma @ 2017-08-29 22:43 UTC (permalink / raw)
  To: Williams, Dan J; +Cc: linux-nvdimm

On 08/29, Verma, Vishal L wrote:
> On Tue, 2017-08-29 at 14:48 -0700, Dan Williams wrote:
> > On Tue, Aug 29, 2017 at 2:32 PM, Verma, Vishal L
> > <vishal.l.verma@intel.com> wrote:
> > > On Tue, 2017-08-29 at 13:02 -0700, Dan Williams wrote:
> > > > If we are reconfiguring an ND_DEVICE_NAMESPACE_IO namespace take
> > > > the
> > > > opportunity to potentially initialize labels. DIMM capacity that
> > > > is
> > > > not
> > > > aliased will surface as a label-less namespace by default. If
> > > > every
> > > > DIMM
> > > > in the interleave set supports labels we can switch a more dynamic
> > > > configuration, i.e. enable pmem sub-division.
> > > > 
> > > > The --no-autolabel option is added to disable this behavior if it
> > > > is
> > > > not
> > > > wanted.
> > > > 
> > > > Cc: Vishal Verma <vishal.l.verma@intel.com>
> > > > Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> > > > ---
> > > >  Documentation/ndctl/ndctl-create-namespace.txt |    7 ++
> > > >  ndctl/namespace.c                              |   90
> > > > +++++++++++++++++++++++-
> > > >  2 files changed, 95 insertions(+), 2 deletions(-)
> > > > 
> > > > diff --git a/Documentation/ndctl/ndctl-create-namespace.txt
> > > > b/Documentation/ndctl/ndctl-create-namespace.txt
> > > > index 85d1f8db792f..3844ff74a9f1 100644
> > > > --- a/Documentation/ndctl/ndctl-create-namespace.txt
> > > > +++ b/Documentation/ndctl/ndctl-create-namespace.txt
> > > > @@ -138,6 +138,13 @@ OPTIONS
> > > >       active.  Specifying --force causes the namespace to be
> > > > disabled
> > > >       before reconfiguring.
> > > > 
> > > > +-L::
> > > > +--autolabel::
> > > 
> > > Shouldn't this be --no-autolabel
> > > 
> > > > +     When ndctl encounters a label-less namespace while
> > > > +     performing a reconfigure operation it will try to enable
> > > > labels
> > > > +     for the region. This behavior can be suppressed with
> > > > +     "--no-autolabel".
> > > 
> > > And the text description matched to describe only the --no-autolabel
> > > option instead of describing both a positive and negative
> > 
> > I'm using a side effect of the way ndctl (and git) implement
> > OPT_BOOLEAN() options. They all automatically get a --no-<option>. So
> > "--autolabel" is the default.
> > 
> Ah cool, I didn't know OPT_BOOLEAN does that for you.
> Does the 'no' option then lack a short option? We'll end up providing a
> short option for the default case, but nothing for the override..
> 
> I'm also wondering if there will be any bash completion implications.
> I'll test whether the --no- option shows up automatically in --list-opts

Patch to special case --no-autolabel for completion:

8<----

>From f18c54d3260c3310d14aaa9aa589de4abc304bf1 Mon Sep 17 00:00:00 2001
From: Vishal Verma <vishal.l.verma@intel.com>
Date: Tue, 29 Aug 2017 16:38:36 -0600
Subject: [PATCH] ndctl, bash-completion: special case --no-autolabel for
 create-namespace

OPT_BOOLEAN provides a --no-* option automatically for all boolean
options, but the negative versions aren't listed in --list-opts.

Special case --no-autolabel since that is the only one where the
negative makes sense.

Cc: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
---
 contrib/ndctl | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/contrib/ndctl b/contrib/ndctl
index 9410572..c7e3e7d 100755
--- a/contrib/ndctl
+++ b/contrib/ndctl
@@ -261,6 +261,17 @@ __ndctl_comp_non_option_args()
 	__ndctlcomp "$opts" "$cur"
 }
 
+__ndctl_add_special_opts()
+{
+	local subcmd=$1
+
+	case $subcmd in
+	create-namespace)
+		opts="$opts --no-autolabel"
+		;;
+	esac
+}
+
 __ndctl_prev_skip_opts ()
 {
 	local i cmd_ cmds_
@@ -354,6 +365,7 @@ __ndctl_main()
 		# List long option names
 		if [[ $cur == --* ]];  then
 			opts=$($cmd $subcmd --list-opts)
+			__ndctl_add_special_opts "$subcmd"
 			__ndctlcomp "$opts" "$cur"
 			__ndctl_comp_options "$cur"
 		else
-- 
2.9.5



> _______________________________________________
> Linux-nvdimm mailing list
> Linux-nvdimm@lists.01.org
> https://lists.01.org/mailman/listinfo/linux-nvdimm
_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

^ permalink raw reply related	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2017-08-29 22:42 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-08-29 20:01 [ndctl PATCH 0/7] ndctl: automatically initialize labels Dan Williams
2017-08-29 20:01 ` [ndctl PATCH 1/7] ndctl, init-labels: fix '--label-version' option Dan Williams
2017-08-29 20:01 ` [ndctl PATCH 2/7] ndctl: drop the "libndctl-" prefix on library source files Dan Williams
2017-08-29 20:01 ` [ndctl PATCH 3/7] ndctl: move label manipulation routines to their own file Dan Williams
2017-08-29 20:01 ` [ndctl PATCH 4/7] ndctl: consolidate namespace definitions in namespace.h Dan Williams
2017-08-29 20:01 ` [ndctl PATCH 5/7] ndctl: refactor read_labels() helper into a library call Dan Williams
2017-08-29 20:02 ` [ndctl PATCH 6/7] ndctl: introduce ndctl_dimm_{validate_labels, init_labels} Dan Williams
2017-08-29 20:02 ` [ndctl PATCH 7/7] ndctl: auto initialize labels Dan Williams
2017-08-29 21:32   ` Verma, Vishal L
2017-08-29 21:48     ` Dan Williams
2017-08-29 21:52       ` Verma, Vishal L
2017-08-29 22:43         ` Vishal Verma

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.