nvdimm.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
* [ndctl PATCH 0/6] ndctl updates for v1.2 namespace labels
@ 2017-07-05 20:48 Dan Williams
  2017-07-05 20:48 ` [ndctl PATCH 1/6] ndctl, test: push btt-check test back to 4.14 Dan Williams
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Dan Williams @ 2017-07-05 20:48 UTC (permalink / raw)
  To: linux-nvdimm

Update test/libndctl, init-labels, and read-labels for the new format.

An update to ndctl.h for the new ACPI 6.2 command formats is also
included. A later patch series will implement library helpers for those
new commands.

---

Dan Williams (6):
      ndctl, test: push btt-check test back to 4.14
      ndctl, test: unit test new pmem sector_size support
      ndctl: update to latest ndctl.h
      ndctl, read-labels: updates for v1.2 of the namespace specification
      ndctl, init-labels: allow opt-in to new v1.2 label format
      ndctl, create-namespace: set pmem namespace sector size


 ndctl/dimm.c      |  243 ++++++++++++++++++++++++++++++++++++++++++++---------
 ndctl/namespace.c |   40 +++++----
 ndctl/ndctl.h     |   42 +++++++++
 test/btt-check.sh |    2 
 test/libndctl.c   |   59 ++++++++++---
 5 files changed, 314 insertions(+), 72 deletions(-)
_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

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

* [ndctl PATCH 1/6] ndctl, test: push btt-check test back to 4.14
  2017-07-05 20:48 [ndctl PATCH 0/6] ndctl updates for v1.2 namespace labels Dan Williams
@ 2017-07-05 20:48 ` Dan Williams
  2017-07-05 20:48 ` [ndctl PATCH 2/6] ndctl, test: unit test new pmem sector_size support Dan Williams
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Dan Williams @ 2017-07-05 20:48 UTC (permalink / raw)
  To: linux-nvdimm

Until the kernel is able to issue clear-error _DSM routines from outside
atomic context the btt error clearing assumptions in this test will
continue to be invalid.

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

diff --git a/test/btt-check.sh b/test/btt-check.sh
index 5ec224b1d582..06d0f35f6c5d 100755
--- a/test/btt-check.sh
+++ b/test/btt-check.sh
@@ -54,7 +54,7 @@ check_min_kver()
 	[[ "$ver" == "$(echo -e "$ver\n$KVER" | sort -V | head -1)" ]]
 }
 
-check_min_kver "4.13" || { echo "kernel $KVER may not support badblocks clearing on pmem via btt"; exit $rc; }
+check_min_kver "4.14" || { echo "kernel $KVER may not support badblocks clearing on pmem via btt"; exit $rc; }
 
 create()
 {

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

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

* [ndctl PATCH 2/6] ndctl, test: unit test new pmem sector_size support
  2017-07-05 20:48 [ndctl PATCH 0/6] ndctl updates for v1.2 namespace labels Dan Williams
  2017-07-05 20:48 ` [ndctl PATCH 1/6] ndctl, test: push btt-check test back to 4.14 Dan Williams
@ 2017-07-05 20:48 ` Dan Williams
  2017-07-05 20:48 ` [ndctl PATCH 3/6] ndctl: update to latest ndctl.h Dan Williams
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Dan Williams @ 2017-07-05 20:48 UTC (permalink / raw)
  To: linux-nvdimm

Expand test/libndctl to validate the new support in 4.13 for specifying
a sector_size for pmem namespaces.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 test/libndctl.c |   59 +++++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 44 insertions(+), 15 deletions(-)

diff --git a/test/libndctl.c b/test/libndctl.c
index 0f67d548ca48..e1c8ee9aabf8 100644
--- a/test/libndctl.c
+++ b/test/libndctl.c
@@ -247,21 +247,22 @@ struct namespace {
 	uuid_t uuid;
 	int do_configure;
 	int check_alt_name;
-	int num_sector_sizes;
 	int ro;
+	int num_sector_sizes;
 	unsigned long *sector_sizes;
 };
 
 static uuid_t null_uuid;
-static unsigned long blk_sector_sizes[7] = { 512, 520, 528, 4096, 4104, 4160, 4224, };
-static unsigned long pmem_sector_sizes[1] = { 0 };
+static unsigned long blk_sector_sizes[] = { 512, 520, 528, 4096, 4104, 4160, 4224, };
+static unsigned long pmem_sector_sizes[] = { 512, 4096 };
 
 static struct namespace namespace0_pmem0 = {
 	0, "namespace_pmem", &btt_settings, &pfn_settings, &dax_settings, SZ_18M,
 	{ 1, 1, 1, 1,
 	  1, 1, 1, 1,
 	  1, 1, 1, 1,
-	  1, 1, 1, 1, }, 1, 1, 1, 0, pmem_sector_sizes,
+	  1, 1, 1, 1, }, 1, 1, 0,
+	ARRAY_SIZE(pmem_sector_sizes), pmem_sector_sizes,
 };
 
 static struct namespace namespace1_pmem0 = {
@@ -269,7 +270,8 @@ static struct namespace namespace1_pmem0 = {
 	{ 2, 2, 2, 2,
 	  2, 2, 2, 2,
 	  2, 2, 2, 2,
-	  2, 2, 2, 2, }, 1, 1, 1, 0, pmem_sector_sizes,
+	  2, 2, 2, 2, }, 1, 1, 0,
+	ARRAY_SIZE(pmem_sector_sizes), pmem_sector_sizes,
 };
 
 static struct namespace namespace2_blk0 = {
@@ -277,7 +279,8 @@ static struct namespace namespace2_blk0 = {
 	{ 3, 3, 3, 3,
 	  3, 3, 3, 3,
 	  3, 3, 3, 3,
-	  3, 3, 3, 3, }, 1, 1, 7, 0, blk_sector_sizes,
+	  3, 3, 3, 3, }, 1, 1, 0,
+	ARRAY_SIZE(blk_sector_sizes), blk_sector_sizes,
 };
 
 static struct namespace namespace2_blk1 = {
@@ -285,7 +288,8 @@ static struct namespace namespace2_blk1 = {
 	{ 4, 4, 4, 4,
 	  4, 4, 4, 4,
 	  4, 4, 4, 4,
-	  4, 4, 4, 4, }, 1, 1, 7, 0, blk_sector_sizes,
+	  4, 4, 4, 4, }, 1, 1, 0,
+	ARRAY_SIZE(blk_sector_sizes), blk_sector_sizes,
 };
 
 static struct namespace namespace3_blk0 = {
@@ -293,7 +297,8 @@ static struct namespace namespace3_blk0 = {
 	{ 5, 5, 5, 5,
 	  5, 5, 5, 5,
 	  5, 5, 5, 5,
-	  5, 5, 5, 5, }, 1, 1, 7, 0, blk_sector_sizes,
+	  5, 5, 5, 5, }, 1, 1, 0,
+	ARRAY_SIZE(blk_sector_sizes), blk_sector_sizes,
 };
 
 static struct namespace namespace3_blk1 = {
@@ -301,7 +306,8 @@ static struct namespace namespace3_blk1 = {
 	{ 6, 6, 6, 6,
 	  6, 6, 6, 6,
 	  6, 6, 6, 6,
-	  6, 6, 6, 6, }, 1, 1, 7, 0, blk_sector_sizes,
+	  6, 6, 6, 6, }, 1, 1, 0,
+	ARRAY_SIZE(blk_sector_sizes), blk_sector_sizes,
 };
 
 static struct namespace namespace4_blk0 = {
@@ -309,7 +315,8 @@ static struct namespace namespace4_blk0 = {
 	{ 7, 7, 7, 7,
 	  7, 7, 7, 7,
 	  7, 7, 7, 7,
-	  7, 7, 7, 7, }, 1, 1, 7, 0, blk_sector_sizes,
+	  7, 7, 7, 7, }, 1, 1, 0,
+	ARRAY_SIZE(blk_sector_sizes), blk_sector_sizes,
 };
 
 static struct namespace namespace5_blk0 = {
@@ -317,7 +324,8 @@ static struct namespace namespace5_blk0 = {
 	{ 8, 8, 8, 8,
 	  8, 8, 8, 8,
 	  8, 8, 8, 8,
-	  8, 8, 8, 8, }, 1, 1, 7, 0, blk_sector_sizes,
+	  8, 8, 8, 8, }, 1, 1, 0,
+	ARRAY_SIZE(blk_sector_sizes), blk_sector_sizes,
 };
 
 static struct region regions0[] = {
@@ -1619,6 +1627,8 @@ static int validate_bdev(const char *devname, struct ndctl_btt *btt,
 static int check_namespaces(struct ndctl_region *region,
 		struct namespace **namespaces, enum ns_mode mode)
 {
+	struct ndctl_ctx *ctx = ndctl_region_get_ctx(region);
+	struct ndctl_test *test = ndctl_get_private_data(ctx);
 	struct ndctl_bus *bus = ndctl_region_get_bus(region);
 	struct ndctl_namespace **ndns_save;
 	struct namespace *namespace;
@@ -1636,8 +1646,10 @@ static int check_namespaces(struct ndctl_region *region,
  retry:
 	ndns_save = NULL;
 	for (i = 0; (namespace = namespaces[i]); i++) {
-		struct ndctl_namespace *ndns;
 		uuid_t uu;
+		struct ndctl_namespace *ndns;
+		unsigned long _sizes[] = { 0 }, *sector_sizes = _sizes;
+		int num_sector_sizes = (int) ARRAY_SIZE(_sizes);
 
 		snprintf(devname, sizeof(devname), "namespace%d.%d",
 				ndctl_region_get_id(region), namespace->id);
@@ -1648,7 +1660,15 @@ static int check_namespaces(struct ndctl_region *region,
 			break;
 		}
 
-		for (j = 0; j < namespace->num_sector_sizes; j++) {
+		if (ndctl_region_get_type(region) == ND_DEVICE_REGION_PMEM
+				&& !ndctl_test_attempt(test, KERNEL_VERSION(4, 13, 0)))
+			/* pass, no sector_size support for pmem prior to 4.13 */;
+		else {
+			num_sector_sizes = namespace->num_sector_sizes;
+			sector_sizes = namespace->sector_sizes;
+		}
+
+		for (j = 0; j < num_sector_sizes; j++) {
 			struct btt *btt_s = NULL;
 			struct pfn *pfn_s = NULL;
 			struct dax *dax_s = NULL;
@@ -1657,7 +1677,7 @@ static int check_namespaces(struct ndctl_region *region,
 			struct ndctl_dax *dax = NULL;
 
 			rc = configure_namespace(region, ndns, namespace,
-					namespace->sector_sizes[j], mode);
+					sector_sizes[j], mode);
 			if (rc < 0) {
 				fprintf(stderr, "%s: failed to configure namespace\n",
 						devname);
@@ -1735,6 +1755,15 @@ static int check_namespaces(struct ndctl_region *region,
 				break;
 			}
 
+			if (sector_sizes[j] && sector_sizes[j]
+					!= ndctl_namespace_get_sector_size(ndns)) {
+				fprintf(stderr, "%s: expected lbasize: %#lx got: %#x\n",
+						devname, sector_sizes[j],
+						ndctl_namespace_get_sector_size(ndns));
+				rc = -ENXIO;
+				break;
+			}
+
 			ndctl_namespace_get_uuid(ndns, uu);
 			if (uuid_compare(uu, namespace->uuid) != 0) {
 				char expect[40], actual[40];
@@ -1812,7 +1841,7 @@ static int check_namespaces(struct ndctl_region *region,
 			 * If this is the last sector size being tested, don't disable
 			 * the namespace
 			 */
-			if (j == namespace->num_sector_sizes - 1)
+			if (j == num_sector_sizes - 1)
 				break;
 
 			/*

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

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

* [ndctl PATCH 3/6] ndctl: update to latest ndctl.h
  2017-07-05 20:48 [ndctl PATCH 0/6] ndctl updates for v1.2 namespace labels Dan Williams
  2017-07-05 20:48 ` [ndctl PATCH 1/6] ndctl, test: push btt-check test back to 4.14 Dan Williams
  2017-07-05 20:48 ` [ndctl PATCH 2/6] ndctl, test: unit test new pmem sector_size support Dan Williams
@ 2017-07-05 20:48 ` Dan Williams
  2017-07-05 20:48 ` [ndctl PATCH 4/6] ndctl, read-labels: updates for v1.2 of the namespace specification Dan Williams
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Dan Williams @ 2017-07-05 20:48 UTC (permalink / raw)
  To: linux-nvdimm

Add the definitions for the new root-device (hid: ACPI0012) _DSMs
defined in the ACPI 6.2 specification.

Cc: Jerry Hoemann <jerry.hoemann@hpe.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 ndctl/ndctl.h |   42 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 41 insertions(+), 1 deletion(-)

diff --git a/ndctl/ndctl.h b/ndctl/ndctl.h
index 3b1d703e4af1..d70b97da3924 100644
--- a/ndctl/ndctl.h
+++ b/ndctl/ndctl.h
@@ -105,7 +105,8 @@ struct nd_cmd_ars_cap {
 	__u32 status;
 	__u32 max_ars_out;
 	__u32 clear_err_unit;
-	__u32 reserved;
+	__u16 flags;
+	__u16 reserved;
 } __attribute__((packed));
 
 struct nd_cmd_ars_start {
@@ -144,6 +145,43 @@ struct nd_cmd_clear_error {
 	__u64 cleared;
 } __attribute__((packed));
 
+struct nd_cmd_trans_spa {
+	__u64 spa;
+	__u32 status;
+	__u8  flags;
+	__u8  _reserved[3];
+	__u64 trans_length;
+	__u32 num_nvdimms;
+	struct nd_nvdimm_device {
+		__u32 nfit_device_handle;
+		__u32 _reserved;
+		__u64 dpa;
+	} __attribute__((packed)) devices[0];
+
+} __attribute__((packed));
+
+struct nd_cmd_ars_err_inj {
+	__u64 err_inj_spa_range_base;
+	__u64 err_inj_spa_range_length;
+	__u8  err_inj_options;
+	__u32 status;
+} __attribute__((packed));
+
+struct nd_cmd_ars_err_inj_clr {
+	__u64 err_inj_clr_spa_range_base;
+	__u64 err_inj_clr_spa_range_length;
+	__u32 status;
+} __attribute__((packed));
+
+struct nd_cmd_ars_err_inj_stat {
+	__u32 status;
+	__u32 inj_err_rec_count;
+	struct nd_error_stat_query_record {
+		__u64 err_inj_stat_spa_range_base;
+		__u64 err_inj_stat_spa_range_length;
+	} __attribute__((packed)) record[0];
+} __attribute__((packed));
+
 enum {
 	ND_CMD_IMPLEMENTED = 0,
 
@@ -169,6 +207,7 @@ enum {
 enum {
 	ND_ARS_VOLATILE = 1,
 	ND_ARS_PERSISTENT = 2,
+	ND_CONFIG_LOCKED = 1,
 };
 
 static __inline__ const char *nvdimm_bus_cmd_name(unsigned cmd)
@@ -178,6 +217,7 @@ static __inline__ const char *nvdimm_bus_cmd_name(unsigned cmd)
 		[ND_CMD_ARS_START] = "ars_start",
 		[ND_CMD_ARS_STATUS] = "ars_status",
 		[ND_CMD_CLEAR_ERROR] = "clear_error",
+		[ND_CMD_CALL] = "cmd_call",
 	};
 
 	if (cmd < ARRAY_SIZE(names) && names[cmd])

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

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

* [ndctl PATCH 4/6] ndctl, read-labels: updates for v1.2 of the namespace specification
  2017-07-05 20:48 [ndctl PATCH 0/6] ndctl updates for v1.2 namespace labels Dan Williams
                   ` (2 preceding siblings ...)
  2017-07-05 20:48 ` [ndctl PATCH 3/6] ndctl: update to latest ndctl.h Dan Williams
@ 2017-07-05 20:48 ` Dan Williams
  2017-07-05 20:49 ` [ndctl PATCH 5/6] ndctl, init-labels: allow opt-in to new v1.2 label format Dan Williams
  2017-07-05 20:49 ` [ndctl PATCH 6/6] ndctl, create-namespace: set pmem namespace sector size Dan Williams
  5 siblings, 0 replies; 7+ messages in thread
From: Dan Williams @ 2017-07-05 20:48 UTC (permalink / raw)
  To: linux-nvdimm

Add basic support for just dumping the new v1.2 namespace label fields
in the output of "ndctl read-labels --json".

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 ndctl/dimm.c |  106 ++++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 91 insertions(+), 15 deletions(-)

diff --git a/ndctl/dimm.c b/ndctl/dimm.c
index d0de4d47a041..5645b6d9be0e 100644
--- a/ndctl/dimm.c
+++ b/ndctl/dimm.c
@@ -39,18 +39,19 @@ enum {
 };
 
 struct namespace_index {
-        char sig[NSINDEX_SIG_LEN];
-        le32 flags;
-        le32 seq;
-        le64 myoff;
-        le64 mysize;
-        le64 otheroff;
-        le64 labeloff;
-        le32 nslot;
-        le16 major;
-        le16 minor;
-        le64 checksum;
-        char free[0];
+	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 {
@@ -64,9 +65,53 @@ struct namespace_label {
 	le64 dpa;
 	le64 rawsize;
 	le32 slot;
-	le32 unused;
+	/*
+	 * 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;
 };
 
+size_t sizeof_namespace_label(struct ndctl_cmd *cmd_read)
+{
+	struct namespace_index nsindex;
+	int v1 = 0, v2 = 0;
+	ssize_t offset;
+
+	for (offset = 0; offset < NSINDEX_ALIGN * 2; offset += NSINDEX_ALIGN) {
+		ssize_t len = (ssize_t) sizeof(nsindex);
+
+		len = ndctl_cmd_cfg_read_get_data(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)
+		return sizeof(struct namespace_label);
+	return 128;
+}
+
+#define namespace_label_has(cmd_read, field) \
+	(offsetof(struct namespace_label, field) \
+	 < sizeof_namespace_label(cmd_read))
+
 static const char NSINDEX_SIGNATURE[] = "NAMESPACE_INDEX\0";
 
 struct action_context {
@@ -98,6 +143,7 @@ static int action_zero(struct ndctl_dimm *dimm, struct action_context *actx)
 
 static struct json_object *dump_label_json(struct ndctl_cmd *cmd_read, ssize_t size)
 {
+	size_t namespace_label_size = sizeof_namespace_label(cmd_read);
 	struct json_object *jarray = json_object_new_array();
 	struct json_object *jlabel = NULL;
 	struct namespace_label nslabel;
@@ -108,7 +154,7 @@ 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(nslabel)) {
-		ssize_t len = min_t(ssize_t, sizeof(nslabel), size - offset);
+		ssize_t len = min_t(ssize_t, namespace_label_size, size - offset);
 		struct json_object *jobj;
 		char uuid[40];
 
@@ -175,6 +221,21 @@ static struct json_object *dump_label_json(struct ndctl_cmd *cmd_read, ssize_t s
 		json_object_object_add(jlabel, "rawsize", jobj);
 
 		json_object_array_add(jarray, jlabel);
+
+		if (namespace_label_size < 256)
+			continue;
+
+		uuid_unparse((void *) nslabel.type_guid, uuid);
+		jobj = json_object_new_string(uuid);
+		if (!jobj)
+			break;
+		json_object_object_add(jlabel, "type_guid", jobj);
+
+		uuid_unparse((void *) nslabel.abstraction_guid, uuid);
+		jobj = json_object_new_string(uuid);
+		if (!jobj)
+			break;
+		json_object_object_add(jlabel, "abstraction_guid", jobj);
 	}
 
 	if (json_object_array_length(jarray) < 1) {
@@ -218,6 +279,21 @@ static struct json_object *dump_index_json(struct ndctl_cmd *cmd_read, ssize_t s
 			break;
 		json_object_object_add(jindex, "signature", jobj);
 
+		jobj = json_object_new_int(le16_to_cpu(nsindex.major));
+		if (!jobj)
+			break;
+		json_object_object_add(jindex, "major", jobj);
+
+		jobj = json_object_new_int(le16_to_cpu(nsindex.minor));
+		if (!jobj)
+			break;
+		json_object_object_add(jindex, "minor", jobj);
+
+		jobj = json_object_new_int(1 << (7 + nsindex.labelsize));
+		if (!jobj)
+			break;
+		json_object_object_add(jindex, "labelsize", jobj);
+
 		jobj = json_object_new_int(le32_to_cpu(nsindex.seq));
 		if (!jobj)
 			break;
@@ -665,7 +741,7 @@ static int label_write_index(struct nvdimm_data *ndd, int index, u32 seq)
 	nslot = nvdimm_num_label_slots(ndd);
 
 	memcpy(nsindex->sig, NSINDEX_SIGNATURE, NSINDEX_SIG_LEN);
-	nsindex->flags = cpu_to_le32(0);
+	memset(nsindex->flags, 0, 3);
 	nsindex->seq = cpu_to_le32(seq);
 	offset = (unsigned long) nsindex
 		- (unsigned long) to_namespace_index(ndd, 0);

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

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

* [ndctl PATCH 5/6] ndctl, init-labels: allow opt-in to new v1.2 label format
  2017-07-05 20:48 [ndctl PATCH 0/6] ndctl updates for v1.2 namespace labels Dan Williams
                   ` (3 preceding siblings ...)
  2017-07-05 20:48 ` [ndctl PATCH 4/6] ndctl, read-labels: updates for v1.2 of the namespace specification Dan Williams
@ 2017-07-05 20:49 ` Dan Williams
  2017-07-05 20:49 ` [ndctl PATCH 6/6] ndctl, create-namespace: set pmem namespace sector size Dan Williams
  5 siblings, 0 replies; 7+ messages in thread
From: Dan Williams @ 2017-07-05 20:49 UTC (permalink / raw)
  To: linux-nvdimm

With the kernel change in 4.13 to start using v1.2 labels by default,
some environments may choose to keep deploying v1.1. The --label-version
option explicitly initializes the index block to the desired version. It
defaults to "1.1" since that has the widest compatibility.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 ndctl/dimm.c |  155 +++++++++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 121 insertions(+), 34 deletions(-)

diff --git a/ndctl/dimm.c b/ndctl/dimm.c
index 5645b6d9be0e..264917d05cc0 100644
--- a/ndctl/dimm.c
+++ b/ndctl/dimm.c
@@ -77,16 +77,31 @@ struct namespace_label {
 	le64 checksum;
 };
 
-size_t sizeof_namespace_label(struct ndctl_cmd *cmd_read)
+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(cmd_read, &nsindex, len, offset);
+		len = ndctl_cmd_cfg_read_get_data(ndd->cmd_read, &nsindex,
+				len, offset);
 		if (len < 0)
 			break;
 
@@ -104,18 +119,21 @@ size_t sizeof_namespace_label(struct ndctl_cmd *cmd_read)
 	}
 
 	if (v2 > v1)
-		return sizeof(struct namespace_label);
-	return 128;
+		ndd->nslabel_size = 256;
+	else
+		ndd->nslabel_size = 128;
+	return ndd->nslabel_size;
 }
 
-#define namespace_label_has(cmd_read, field) \
+#define namespace_label_has(ndd, field) \
 	(offsetof(struct namespace_label, field) \
-	 < sizeof_namespace_label(cmd_read))
+	 < sizeof_namespace_label(ndd))
 
 static const char NSINDEX_SIGNATURE[] = "NAMESPACE_INDEX\0";
 
 struct action_context {
 	struct json_object *jdimms;
+	int labelversion;
 	FILE *f_out;
 	FILE *f_in;
 };
@@ -143,7 +161,10 @@ static int action_zero(struct ndctl_dimm *dimm, struct action_context *actx)
 
 static struct json_object *dump_label_json(struct ndctl_cmd *cmd_read, ssize_t size)
 {
-	size_t namespace_label_size = sizeof_namespace_label(cmd_read);
+	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;
@@ -153,8 +174,10 @@ static struct json_object *dump_label_json(struct ndctl_cmd *cmd_read, ssize_t s
 	if (!jarray)
 		return NULL;
 
-	for (offset = NSINDEX_ALIGN * 2; offset < size; offset += sizeof(nslabel)) {
-		ssize_t len = min_t(ssize_t, namespace_label_size, size - offset);
+	for (offset = NSINDEX_ALIGN * 2; offset < size;
+			offset += sizeof_namespace_label(ndd)) {
+		ssize_t len = min_t(ssize_t, sizeof_namespace_label(ndd),
+				size - offset);
 		struct json_object *jobj;
 		char uuid[40];
 
@@ -163,7 +186,7 @@ static struct json_object *dump_label_json(struct ndctl_cmd *cmd_read, ssize_t s
 		if (!jlabel)
 			break;
 
-		if (len < (ssize_t) sizeof(nslabel))
+		if (len < (ssize_t) sizeof_namespace_label(ndd))
 			break;
 
 		len = ndctl_cmd_cfg_read_get_data(cmd_read, &nslabel, len, offset);
@@ -222,7 +245,7 @@ static struct json_object *dump_label_json(struct ndctl_cmd *cmd_read, ssize_t s
 
 		json_object_array_add(jarray, jlabel);
 
-		if (namespace_label_size < 256)
+		if (sizeof_namespace_label(ndd) < 256)
 			continue;
 
 		uuid_unparse((void *) nslabel.type_guid, uuid);
@@ -486,16 +509,6 @@ static int action_read(struct ndctl_dimm *dimm, struct action_context *actx)
 	return rc;
 }
 
-struct nvdimm_data {
-	struct ndctl_dimm *dimm;
-	struct ndctl_cmd *cmd_read;
-	unsigned long config_size;
-	struct log_ctx ctx;
-	void *data;
-	int nsindex_size;
-	int ns_current, ns_next;
-};
-
 /*
  * Note, best_seq(), inc_seq(), sizeof_namespace_index()
  * nvdimm_num_label_slots(), label_validate(), and label_write_index()
@@ -508,6 +521,7 @@ struct nvdimm_data {
  * 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)
@@ -532,7 +546,7 @@ static u32 best_seq(u32 a, u32 b)
 		return a;
 }
 
-static size_t sizeof_namespace_index(struct nvdimm_data *ndd)
+size_t sizeof_namespace_index(struct nvdimm_data *ndd)
 {
 	u32 index_span;
 
@@ -547,16 +561,16 @@ static size_t sizeof_namespace_index(struct nvdimm_data *ndd)
 	 * starts to waste space at larger config_sizes, but it's
 	 * unlikely we'll ever see anything but 128K.
 	 */
-	index_span = ndd->config_size / 129;
+	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)
+int nvdimm_num_label_slots(struct nvdimm_data *ndd)
 {
-	return ndd->config_size / 129;
+	return ndd->config_size / (sizeof_namespace_label(ndd) + 1);
 }
 
 static struct namespace_index *to_namespace_index(struct nvdimm_data *ndd,
@@ -571,7 +585,7 @@ static struct namespace_index *to_namespace_index(struct nvdimm_data *ndd,
 	return (struct namespace_index *) index;
 }
 
-static int label_validate(struct nvdimm_data *ndd)
+static int __label_validate(struct nvdimm_data *ndd)
 {
 	/*
 	 * On media label format consists of two index blocks followed
@@ -613,12 +627,28 @@ static int label_validate(struct nvdimm_data *ndd)
 		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);
@@ -658,7 +688,7 @@ static int label_validate(struct nvdimm_data *ndd)
 		}
 
 		nslot = le32_to_cpu(nsindex[i]->nslot);
-		if (nslot * sizeof(struct namespace_label)
+		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",
@@ -693,6 +723,29 @@ static int label_validate(struct nvdimm_data *ndd)
 	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)
 {
@@ -742,6 +795,7 @@ static int label_write_index(struct nvdimm_data *ndd, int index, u32 seq)
 
 	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);
@@ -756,7 +810,10 @@ static int label_write_index(struct nvdimm_data *ndd, int index, u32 seq)
 	nsindex->labeloff = cpu_to_le64(offset);
 	nsindex->nslot = cpu_to_le32(nslot);
 	nsindex->major = cpu_to_le16(1);
-	nsindex->minor = 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);
@@ -770,14 +827,17 @@ static struct parameters {
 	const char *bus;
 	const char *outfile;
 	const char *infile;
+	const char *labelversion;
 	bool force;
 	bool json;
 	bool verbose;
-} param;
+} param = {
+	.labelversion = "1.1",
+};
 
-static int __action_init(struct ndctl_dimm *dimm, int chk_only)
+static int __action_init(struct ndctl_dimm *dimm, int version, int chk_only)
 {
-	struct nvdimm_data __ndd, *ndd = &__ndd;
+	struct nvdimm_data __ndd = { 0 }, *ndd = &__ndd;
 	struct ndctl_cmd *cmd_read;
 	int rc = 0, i;
 	ssize_t size;
@@ -830,6 +890,16 @@ static int __action_init(struct ndctl_dimm *dimm, int chk_only)
 		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)
@@ -856,12 +926,12 @@ static int __action_init(struct ndctl_dimm *dimm, int chk_only)
 
 static int action_init(struct ndctl_dimm *dimm, struct action_context *actx)
 {
-	return __action_init(dimm, 0);
+	return __action_init(dimm, actx->labelversion, 0);
 }
 
 static int action_check(struct ndctl_dimm *dimm, struct action_context *actx)
 {
-	return __action_init(dimm, 1);
+	return __action_init(dimm, 0, 1);
 }
 
 
@@ -881,7 +951,9 @@ 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")
+		"force initialization even if existing index-block present"), \
+OPT_STRING('V', "--label-version", &param.labelversion, "version-number", \
+	"namespace label specification version (default: 1.1)")
 
 static const struct option read_options[] = {
 	BASE_OPTIONS(),
@@ -975,6 +1047,21 @@ static int dimm_action(int argc, const char **argv, void *ctx,
 	if (param.verbose)
 		ndctl_set_log_priority(ctx, LOG_DEBUG);
 
+	if (strcmp(param.labelversion, "1.1") == 0)
+		actx.labelversion = 1;
+	else if (strcmp(param.labelversion, "v1.1") == 0)
+		actx.labelversion = 1;
+	else if (strcmp(param.labelversion, "1.2") == 0)
+		actx.labelversion = 2;
+	else if (strcmp(param.labelversion, "v1.2") == 0)
+		actx.labelversion = 2;
+	else {
+		fprintf(stderr, "'%s' is not a valid label version\n",
+				param.labelversion);
+		rc = -EINVAL;
+		goto out;
+	}
+
 	rc = 0;
 	err = 0;
 	count = 0;

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

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

* [ndctl PATCH 6/6] ndctl, create-namespace: set pmem namespace sector size
  2017-07-05 20:48 [ndctl PATCH 0/6] ndctl updates for v1.2 namespace labels Dan Williams
                   ` (4 preceding siblings ...)
  2017-07-05 20:49 ` [ndctl PATCH 5/6] ndctl, init-labels: allow opt-in to new v1.2 label format Dan Williams
@ 2017-07-05 20:49 ` Dan Williams
  5 siblings, 0 replies; 7+ messages in thread
From: Dan Williams @ 2017-07-05 20:49 UTC (permalink / raw)
  To: linux-nvdimm

Starting with v1.2 namespace labels, the "lbasize" field is expected to
be non-zero for all namespace types.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 ndctl/namespace.c |   40 +++++++++++++++++++++++++---------------
 1 file changed, 25 insertions(+), 15 deletions(-)

diff --git a/ndctl/namespace.c b/ndctl/namespace.c
index c28d00193a62..778a65d02c2a 100644
--- a/ndctl/namespace.c
+++ b/ndctl/namespace.c
@@ -244,18 +244,14 @@ static int set_defaults(enum namespace_action mode)
 			error("invalid sector size: %s\n", param.sector_size);
 			rc = -EINVAL;
 		}
-
-		if (param.type && param.mode && strcmp(param.type, "pmem") == 0
-				&& strcmp(param.mode, "safe") != 0) {
-			error("'pmem' namespaces do not support setting 'sector size'\n");
-			rc = -EINVAL;
-		}
-	} else if (!param.reconfig
-			&& ((param.type && strcmp(param.type, "blk") == 0)
+	} else if (!param.reconfig) {
+		if ((param.type && strcmp(param.type, "blk") == 0)
 				|| (param.mode
-					&& strcmp(param.mode, "safe") == 0))) {
+					&& strcmp(param.mode, "safe") == 0))
 			/* default sector size for blk-type or safe-mode */
 			param.sector_size = "4096";
+		else
+			param.sector_size = "512";
 	}
 
 	return rc;
@@ -356,7 +352,7 @@ static int setup_namespace(struct ndctl_region *region,
 		try(ndctl_namespace, set_size, ndns, p->size);
 	}
 
-	if (ndctl_namespace_get_type(ndns) == ND_DEVICE_NAMESPACE_BLK)
+	if (p->sector_size)
 		try(ndctl_namespace, set_sector_size, ndns, p->sector_size);
 
 	uuid_generate(uuid);
@@ -608,22 +604,36 @@ static int validate_namespace_options(struct ndctl_region *region,
 				if (ndctl_namespace_get_supported_sector_size(seed, i)
 						== p->sector_size)
 					break;
-			if (i >= num) {
+			if (i >= num)
 				debug("%s: does not support namespace sector_size %lu\n",
 						region_name, p->sector_size);
+
+			/*
+			 * Pre-4.13 kernels did not support sector sizes
+			 * for pmem namespaces. Revert to the zero
+			 * default in that case.
+			 */
+			if (i >= num && ndctl_region_get_type(region)
+					!= ND_DEVICE_REGION_BLK
+					&& (p->sector_size == 512
+						|| p->sector_size == 4096)) {
+				debug("%s: revert to default sector size\n",
+						region_name);
+				p->sector_size = 0;
+			} else if (i >= num)
 				return -EINVAL;
-			}
 		}
 	} else if (ndns) {
 		struct ndctl_btt *btt = ndctl_namespace_get_btt(ndns);
 
 		if (btt)
 			p->sector_size = ndctl_btt_get_sector_size(btt);
-		else if (ndctl_namespace_get_type(ndns)
-				== ND_DEVICE_NAMESPACE_BLK)
-			p->sector_size = ndctl_namespace_get_sector_size(ndns);
 		else if (p->mode == NDCTL_NS_MODE_SAFE)
 				p->sector_size = 4096;
+		else
+			p->sector_size = ndctl_namespace_get_sector_size(ndns);
+		if (p->sector_size == UINT_MAX)
+			p->sector_size = 0;
 	}
 
 	if (param.map) {

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

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

end of thread, other threads:[~2017-07-05 20:53 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-07-05 20:48 [ndctl PATCH 0/6] ndctl updates for v1.2 namespace labels Dan Williams
2017-07-05 20:48 ` [ndctl PATCH 1/6] ndctl, test: push btt-check test back to 4.14 Dan Williams
2017-07-05 20:48 ` [ndctl PATCH 2/6] ndctl, test: unit test new pmem sector_size support Dan Williams
2017-07-05 20:48 ` [ndctl PATCH 3/6] ndctl: update to latest ndctl.h Dan Williams
2017-07-05 20:48 ` [ndctl PATCH 4/6] ndctl, read-labels: updates for v1.2 of the namespace specification Dan Williams
2017-07-05 20:49 ` [ndctl PATCH 5/6] ndctl, init-labels: allow opt-in to new v1.2 label format Dan Williams
2017-07-05 20:49 ` [ndctl PATCH 6/6] ndctl, create-namespace: set pmem namespace sector size Dan Williams

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).