* [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", ¶m.infile, "input-file", \
#define INIT_OPTIONS() \
OPT_BOOLEAN('f', "force", ¶m.force, \
- "force initialization even if existing index-block present")
+ "force initialization even if existing index-block present"), \
+OPT_STRING('V', "--label-version", ¶m.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).