* [ndctl PATCH 0/8] Improve support + testing for labels + info-blocks
@ 2019-02-12 21:28 Dan Williams
2019-02-12 21:28 ` [ndctl PATCH 1/8] ndctl/dimm: Add 'flags' field to read-labels output Dan Williams
` (7 more replies)
0 siblings, 8 replies; 12+ messages in thread
From: Dan Williams @ 2019-02-12 21:28 UTC (permalink / raw)
To: linux-nvdimm
As noted in the kernel patches for this issue:
Lately Linux has encountered platforms that collide Persistent
Memory regions between each other, specifically cases where
->start_pad needed to be non-zero. This lead to commit ae86cbfef381
"libnvdimm, pfn: Pad pfn namespaces relative to other regions". That
commit allowed namespaces to be mapped with devm_memremap_pages().
However dax operations on those configurations currently fail if
attempted within the ->start_pad range because
pmem_device->data_offset was still relative to raw resource base not
relative to the section aligned resource range mapped by
devm_memremap_pages().
Luckily __bdev_dax_supported() caught these failures and simply
disabled dax. However, to fix this situation a non-backwards
compatible change needs to be made to the interpretation of the
nd_pfn info-block. ->start_pad needs to be accounted in
->map.map_offset (formerly ->data_offset), and ->map.map_base
(formerly ->phys_addr) needs to be adjusted to the section aligned
resource base used to establish ->map.map formerly (formerly
->virt_addr).
Towards preventing similar bugs in this area introduce a regression
test "test/collide.sh" to validate support for pre- and post-fixed
kernels. In the course of developing this test a few missing
capabilities and fixes also surfaced.
---
Dan Williams (8):
ndctl/dimm: Add 'flags' field to read-labels output
ndctl/dimm: Add --human support to read-labels
ndctl/build: Drop -Wpointer-arith
ndctl/namespace: Add read-info-block command
ndctl/test: Update dax-dev to handle multiple e820 ranges
ndctl/test: Make dax.sh more robust vs small namespaces
ndctl/namespace: Always zero info-blocks
ndctl/test: Test inter-region collision handling
configure.ac | 1
ndctl/action.h | 1
ndctl/builtin.h | 1
ndctl/check.c | 20 --
ndctl/dimm.c | 21 ++-
ndctl/namespace.c | 416 +++++++++++++++++++++++++++++++++++++++++++++++++-
ndctl/namespace.h | 51 ++++++
ndctl/ndctl.c | 1
test/Makefile.am | 1
test/collide.sh | 226 +++++++++++++++++++++++++++
test/dax-dev.c | 17 ++
test/dax.sh | 4
test/fsdax-info0.xxd | 11 +
test/fsdax-info1.xxd | 11 +
test/fsdax-info2.xxd | 11 +
test/fsdax-info3.xxd | 11 +
util/fletcher.h | 1
util/size.h | 1
18 files changed, 763 insertions(+), 43 deletions(-)
create mode 100755 test/collide.sh
create mode 100644 test/fsdax-info0.xxd
create mode 100644 test/fsdax-info1.xxd
create mode 100644 test/fsdax-info2.xxd
create mode 100644 test/fsdax-info3.xxd
_______________________________________________
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/8] ndctl/dimm: Add 'flags' field to read-labels output
2019-02-12 21:28 [ndctl PATCH 0/8] Improve support + testing for labels + info-blocks Dan Williams
@ 2019-02-12 21:28 ` Dan Williams
2019-02-12 21:28 ` [ndctl PATCH 2/8] ndctl/dimm: Add --human support to read-labels Dan Williams
` (6 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Dan Williams @ 2019-02-12 21:28 UTC (permalink / raw)
To: linux-nvdimm
Recent discussions on some platform implementations setting the LOCAL
bit in namespace labels makes it apparent that this field should be
decoded in the json representation.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
ndctl/dimm.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/ndctl/dimm.c b/ndctl/dimm.c
index cc0bec04c3b2..292beebf9734 100644
--- a/ndctl/dimm.c
+++ b/ndctl/dimm.c
@@ -140,6 +140,11 @@ static struct json_object *dump_label_json(struct ndctl_dimm *dimm,
break;
json_object_object_add(jlabel, "nlabel", jobj);
+ jobj = json_object_new_int64(le64_to_cpu(nslabel.flags));
+ if (!jobj)
+ break;
+ json_object_object_add(jlabel, "flags", jobj);
+
jobj = json_object_new_int64(le64_to_cpu(nslabel.isetcookie));
if (!jobj)
break;
_______________________________________________
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/8] ndctl/dimm: Add --human support to read-labels
2019-02-12 21:28 [ndctl PATCH 0/8] Improve support + testing for labels + info-blocks Dan Williams
2019-02-12 21:28 ` [ndctl PATCH 1/8] ndctl/dimm: Add 'flags' field to read-labels output Dan Williams
@ 2019-02-12 21:28 ` Dan Williams
2019-03-19 22:39 ` Verma, Vishal L
2019-02-12 21:29 ` [ndctl PATCH 3/8] ndctl/build: Drop -Wpointer-arith Dan Williams
` (5 subsequent siblings)
7 siblings, 1 reply; 12+ messages in thread
From: Dan Williams @ 2019-02-12 21:28 UTC (permalink / raw)
To: linux-nvdimm
Allow for easier comparisons between 'read-labels' output and list.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
ndctl/dimm.c | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/ndctl/dimm.c b/ndctl/dimm.c
index 292beebf9734..5ff730f42a45 100644
--- a/ndctl/dimm.c
+++ b/ndctl/dimm.c
@@ -50,6 +50,7 @@ static struct parameters {
bool crypto_erase;
bool overwrite;
bool master_pass;
+ bool human;
bool force;
bool json;
bool verbose;
@@ -79,7 +80,7 @@ static int action_zero(struct ndctl_dimm *dimm, struct action_context *actx)
}
static struct json_object *dump_label_json(struct ndctl_dimm *dimm,
- struct ndctl_cmd *cmd_read, ssize_t size)
+ struct ndctl_cmd *cmd_read, ssize_t size, unsigned long flags)
{
struct json_object *jarray = json_object_new_array();
struct json_object *jlabel = NULL;
@@ -140,12 +141,13 @@ static struct json_object *dump_label_json(struct ndctl_dimm *dimm,
break;
json_object_object_add(jlabel, "nlabel", jobj);
- jobj = json_object_new_int64(le64_to_cpu(nslabel.flags));
+ jobj = util_json_object_hex(le32_to_cpu(nslabel.flags), flags);
if (!jobj)
break;
json_object_object_add(jlabel, "flags", jobj);
- jobj = json_object_new_int64(le64_to_cpu(nslabel.isetcookie));
+ jobj = util_json_object_hex(le64_to_cpu(nslabel.isetcookie),
+ flags);
if (!jobj)
break;
json_object_object_add(jlabel, "isetcookie", jobj);
@@ -155,12 +157,12 @@ static struct json_object *dump_label_json(struct ndctl_dimm *dimm,
break;
json_object_object_add(jlabel, "lbasize", jobj);
- jobj = json_object_new_int64(le64_to_cpu(nslabel.dpa));
+ jobj = util_json_object_hex(le64_to_cpu(nslabel.dpa), flags);
if (!jobj)
break;
json_object_object_add(jlabel, "dpa", jobj);
- jobj = json_object_new_int64(le64_to_cpu(nslabel.rawsize));
+ jobj = util_json_object_size(le64_to_cpu(nslabel.rawsize), flags);
if (!jobj)
break;
json_object_object_add(jlabel, "rawsize", jobj);
@@ -265,6 +267,7 @@ static struct json_object *dump_index_json(struct ndctl_cmd *cmd_read, ssize_t s
static struct json_object *dump_json(struct ndctl_dimm *dimm,
struct ndctl_cmd *cmd_read, ssize_t size)
{
+ unsigned long flags = param.human ? UTIL_JSON_HUMAN : 0;
struct json_object *jdimm = json_object_new_object();
struct json_object *jlabel, *jobj, *jindex;
@@ -273,7 +276,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(dimm, cmd_read, size);
+ jlabel = dump_label_json(dimm, cmd_read, size, flags);
if (!jlabel)
goto err_jlabel;
@@ -1038,7 +1041,8 @@ OPT_BOOLEAN('v',"verbose", ¶m.verbose, "turn on debug")
#define READ_OPTIONS() \
OPT_STRING('o', "output", ¶m.outfile, "output-file", \
"filename to write label area contents"), \
-OPT_BOOLEAN('j', "json", ¶m.json, "parse label data into json")
+OPT_BOOLEAN('j', "json", ¶m.json, "parse label data into json"), \
+OPT_BOOLEAN('u', "human", ¶m.human, "use human friendly number formats ")
#define WRITE_OPTIONS() \
OPT_STRING('i', "input", ¶m.infile, "input-file", \
_______________________________________________
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/8] ndctl/build: Drop -Wpointer-arith
2019-02-12 21:28 [ndctl PATCH 0/8] Improve support + testing for labels + info-blocks Dan Williams
2019-02-12 21:28 ` [ndctl PATCH 1/8] ndctl/dimm: Add 'flags' field to read-labels output Dan Williams
2019-02-12 21:28 ` [ndctl PATCH 2/8] ndctl/dimm: Add --human support to read-labels Dan Williams
@ 2019-02-12 21:29 ` Dan Williams
2019-02-12 21:29 ` [ndctl PATCH 4/8] ndctl/namespace: Add read-info-block command Dan Williams
` (4 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Dan Williams @ 2019-02-12 21:29 UTC (permalink / raw)
To: linux-nvdimm
It is common kernel practice to do pointer arithmetic on (void *). Drop
this warning for ndctl.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
configure.ac | 1 -
1 file changed, 1 deletion(-)
diff --git a/configure.ac b/configure.ac
index d27a2b1cf5a2..25b785f9d04f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -190,7 +190,6 @@ my_CFLAGS="\
-Wmissing-declarations \
-Wmissing-prototypes \
-Wnested-externs \
--Wpointer-arith \
-Wshadow \
-Wsign-compare \
-Wstrict-prototypes \
_______________________________________________
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/8] ndctl/namespace: Add read-info-block command
2019-02-12 21:28 [ndctl PATCH 0/8] Improve support + testing for labels + info-blocks Dan Williams
` (2 preceding siblings ...)
2019-02-12 21:29 ` [ndctl PATCH 3/8] ndctl/build: Drop -Wpointer-arith Dan Williams
@ 2019-02-12 21:29 ` Dan Williams
2019-03-19 23:11 ` Verma, Vishal L
2019-02-12 21:29 ` [ndctl PATCH 5/8] ndctl/test: Update dax-dev to handle multiple e820 ranges Dan Williams
` (3 subsequent siblings)
7 siblings, 1 reply; 12+ messages in thread
From: Dan Williams @ 2019-02-12 21:29 UTC (permalink / raw)
To: linux-nvdimm
Namespaces may contain an info-block that correlates with the possible
modes of a namespace: 'sector', 'fsdax', or 'devdax'. Provide a command
that can temporarily convert the namespace into 'raw' mode to read the
info-block.
Also, similar to 'read-labels' provide a facility to decode the
info-block into json.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
ndctl/action.h | 1
ndctl/builtin.h | 1
ndctl/check.c | 20 ---
ndctl/namespace.c | 401 +++++++++++++++++++++++++++++++++++++++++++++++++++++
ndctl/namespace.h | 51 +++++++
ndctl/ndctl.c | 1
util/fletcher.h | 1
util/size.h | 1
8 files changed, 456 insertions(+), 21 deletions(-)
diff --git a/ndctl/action.h b/ndctl/action.h
index 1ecad49530d5..01cfce511250 100644
--- a/ndctl/action.h
+++ b/ndctl/action.h
@@ -13,5 +13,6 @@ enum device_action {
ACTION_CHECK,
ACTION_WAIT,
ACTION_START,
+ ACTION_READ_INFOBLOCK,
};
#endif /* __NDCTL_ACTION_H__ */
diff --git a/ndctl/builtin.h b/ndctl/builtin.h
index 681a69ff3770..985b7937d884 100644
--- a/ndctl/builtin.h
+++ b/ndctl/builtin.h
@@ -8,6 +8,7 @@ int cmd_create_nfit(int argc, const char **argv, struct ndctl_ctx *ctx);
int cmd_enable_namespace(int argc, const char **argv, struct ndctl_ctx *ctx);
int cmd_create_namespace(int argc, const char **argv, struct ndctl_ctx *ctx);
int cmd_destroy_namespace(int argc, const char **argv, struct ndctl_ctx *ctx);
+int cmd_read_infoblock(int argc, const char **argv, struct ndctl_ctx *ctx);
int cmd_disable_namespace(int argc, const char **argv, struct ndctl_ctx *ctx);
int cmd_check_namespace(int argc, const char **argv, struct ndctl_ctx *ctx);
int cmd_enable_region(int argc, const char **argv, struct ndctl_ctx *ctx);
diff --git a/ndctl/check.c b/ndctl/check.c
index 8a7125053865..3b384c091af5 100644
--- a/ndctl/check.c
+++ b/ndctl/check.c
@@ -297,24 +297,6 @@ static int btt_log_read(struct arena_info *a, u32 lane, struct log_entry *ent)
return 0;
}
-static int btt_checksum_verify(struct btt_sb *btt_sb)
-{
- uint64_t sum;
- le64 sum_save;
-
- BUILD_BUG_ON(sizeof(struct btt_sb) != SZ_4K);
-
- sum_save = btt_sb->checksum;
- btt_sb->checksum = 0;
- sum = fletcher64(btt_sb, sizeof(*btt_sb), 1);
- if (sum != sum_save)
- return 1;
- /* restore the checksum in the buffer */
- btt_sb->checksum = sum_save;
-
- return 0;
-}
-
/*
* Never pass a mmapped buffer to this as it will attempt to write to
* the buffer, and we want writes to only happened in a controlled fashion.
@@ -330,7 +312,7 @@ static int btt_info_verify(struct btt_chk *bttc, struct btt_sb *btt_sb)
if (uuid_compare(bttc->parent_uuid, btt_sb->parent_uuid) != 0)
return -ENXIO;
- if (btt_checksum_verify(btt_sb))
+ if (!verify_infoblock_checksum((union info_block *) btt_sb))
return -ENXIO;
return 0;
diff --git a/ndctl/namespace.c b/ndctl/namespace.c
index 03d805a69ce4..6e42acb695aa 100644
--- a/ndctl/namespace.c
+++ b/ndctl/namespace.c
@@ -21,6 +21,7 @@
#include <ndctl.h>
#include "action.h"
+#include "namespace.h"
#include <sys/stat.h>
#include <uuid/uuid.h>
#include <sys/types.h>
@@ -40,6 +41,9 @@ static struct parameters {
bool do_scan;
bool mode_default;
bool autolabel;
+ bool no_verify;
+ bool human;
+ bool json;
const char *bus;
const char *map;
const char *type;
@@ -51,6 +55,8 @@ static struct parameters {
const char *reconfig;
const char *sector_size;
const char *align;
+ const char *outfile;
+ const char *infile;
} param = {
.autolabel = true,
};
@@ -79,6 +85,13 @@ struct parsed_parameters {
bool autolabel;
};
+#define pr_verbose(fmt, ...) \
+ ({if (verbose) { \
+ fprintf(stderr, fmt, ##__VA_ARGS__); \
+ } else { \
+ do { } while (0); \
+ }})
+
#define debug(fmt, ...) \
({if (verbose) { \
fprintf(stderr, "%s:%d: " fmt, __func__, __LINE__, ##__VA_ARGS__); \
@@ -120,6 +133,16 @@ OPT_BOOLEAN('R', "repair", &repair, "perform metadata repairs"), \
OPT_BOOLEAN('L', "rewrite-log", &logfix, "regenerate the log"), \
OPT_BOOLEAN('f', "force", &force, "check namespace even if currently active")
+#define READ_INFOBLOCK_OPTIONS() \
+OPT_FILENAME('o', "output", ¶m.outfile, "output-file", \
+ "filename to write label area contents"), \
+OPT_FILENAME('f', "file", ¶m.infile, "input-file", \
+ "filename to readinfo block instead of a namespace"), \
+OPT_BOOLEAN('n', "no-verify", ¶m.no_verify, \
+ "skip parent uuid, and checksum validation"), \
+OPT_BOOLEAN('j', "json", ¶m.json, "parse label data into json"), \
+OPT_BOOLEAN('u', "human", ¶m.human, "use human friendly number formats ")
+
static const struct option base_options[] = {
BASE_OPTIONS(),
OPT_END(),
@@ -144,6 +167,12 @@ static const struct option check_options[] = {
OPT_END(),
};
+static const struct option read_infoblock_options[] = {
+ BASE_OPTIONS(),
+ READ_INFOBLOCK_OPTIONS(),
+ OPT_END(),
+};
+
static int set_defaults(enum device_action mode)
{
int rc = 0;
@@ -285,18 +314,30 @@ static const char *parse_namespace_options(int argc, const char **argv,
case ACTION_CHECK:
action_string = "check";
break;
+ case ACTION_READ_INFOBLOCK:
+ action_string = "read-infoblock";
+ break;
default:
action_string = "<>";
break;
}
- error("specify a namespace to %s, or \"all\"\n", action_string);
- rc = -EINVAL;
+
+ if ((mode == ACTION_READ_INFOBLOCK && !param.infile)
+ || mode != ACTION_READ_INFOBLOCK) {
+ error("specify a namespace to %s, or \"all\"\n", action_string);
+ rc = -EINVAL;
+ }
}
for (i = mode == ACTION_CREATE ? 0 : 1; i < argc; i++) {
error("unknown extra parameter \"%s\"\n", argv[i]);
rc = -EINVAL;
}
+ if (mode == ACTION_READ_INFOBLOCK && param.infile && argc) {
+ error("specify a namespace, or --file, not both\n");
+ rc = -EINVAL;
+ }
+
if (rc) {
usage_with_options(u, options);
return NULL; /* we won't return from usage_with_options() */
@@ -1051,10 +1092,319 @@ static int namespace_reconfig(struct ndctl_region *region,
int namespace_check(struct ndctl_namespace *ndns, bool verbose, bool force,
bool repair, bool logfix);
+struct read_infoblock_ctx {
+ struct json_object *jblocks;
+ FILE *f_out;
+};
+
+#define parse_field(sb, field) \
+ jobj = json_object_new_int(le32_to_cpu((sb)->field)); \
+ if (!jobj) \
+ goto err; \
+ json_object_object_add(jblock, #field, jobj);
+
+#define parse_hex(sb, field, sz) \
+ jobj = util_json_object_hex(le##sz##_to_cpu((sb)->field), flags); \
+ if (!jobj) \
+ goto err; \
+ json_object_object_add(jblock, #field, jobj);
+
+
+static json_object *btt_parse(struct btt_sb *btt_sb, struct ndctl_namespace *ndns,
+ const char *path, unsigned long flags)
+{
+ uuid_t uuid;
+ char str[40];
+ struct json_object *jblock, *jobj;
+ const char *cmd = "read-info-block";
+ const bool verify = !param.no_verify;
+
+ if (verify && !verify_infoblock_checksum((union info_block *) btt_sb)) {
+ pr_verbose("%s: %s checksum verification failed\n", cmd, __func__);
+ return NULL;
+ }
+
+ if (ndns) {
+ ndctl_namespace_get_uuid(ndns, uuid);
+ if (verify && !uuid_is_null(uuid) && memcmp(uuid, btt_sb->parent_uuid,
+ sizeof(uuid) != 0)) {
+ pr_verbose("%s: %s uuid verification failed\n", cmd, __func__);
+ return NULL;
+ }
+ }
+
+ jblock = json_object_new_object();
+ if (!jblock)
+ return NULL;
+
+ if (ndns) {
+ jobj = json_object_new_string(ndctl_namespace_get_devname(ndns));
+ if (!jobj)
+ goto err;
+ json_object_object_add(jblock, "dev", jobj);
+ } else {
+ jobj = json_object_new_string(path);
+ if (!jobj)
+ goto err;
+ json_object_object_add(jblock, "file", jobj);
+ }
+
+ jobj = json_object_new_string((char *) btt_sb->signature);
+ if (!jobj)
+ goto err;
+ json_object_object_add(jblock, "signature", jobj);
+
+ uuid_unparse((void *) btt_sb->uuid, str);
+ jobj = json_object_new_string(str);
+ if (!jobj)
+ goto err;
+ json_object_object_add(jblock, "uuid", jobj);
+
+ uuid_unparse((void *) btt_sb->parent_uuid, str);
+ jobj = json_object_new_string(str);
+ if (!jobj)
+ goto err;
+ json_object_object_add(jblock, "parent_uuid", jobj);
+
+ jobj = util_json_object_hex(le32_to_cpu(btt_sb->flags), flags);
+ if (!jobj)
+ goto err;
+ json_object_object_add(jblock, "flags", jobj);
+
+ if (snprintf(str, 4, "%d.%d", btt_sb->version_major,
+ btt_sb->version_minor) >= 4)
+ goto err;
+ jobj = json_object_new_string(str);
+ if (!jobj)
+ goto err;
+ json_object_object_add(jblock, "version", jobj);
+
+ parse_field(btt_sb, external_lbasize);
+ parse_field(btt_sb, external_nlba);
+ parse_field(btt_sb, internal_lbasize);
+ parse_field(btt_sb, internal_nlba);
+ parse_field(btt_sb, nfree);
+ parse_field(btt_sb, infosize);
+ parse_hex(btt_sb, nextoff, 64);
+ parse_hex(btt_sb, dataoff, 64);
+ parse_hex(btt_sb, mapoff, 64);
+ parse_hex(btt_sb, logoff, 64);
+ parse_hex(btt_sb, info2off, 64);
+
+ return jblock;
+err:
+ pr_verbose("%s: failed to create json representation\n", cmd);
+ json_object_put(jblock);
+ return NULL;
+}
+
+static json_object *pfn_parse(struct pfn_sb *pfn_sb, struct ndctl_namespace *ndns,
+ const char *path, unsigned long flags)
+{
+ uuid_t uuid;
+ char str[40];
+ struct json_object *jblock, *jobj;
+ const char *cmd = "read-info-block";
+ const bool verify = !param.no_verify;
+
+ if (verify && !verify_infoblock_checksum((union info_block *) pfn_sb)) {
+ pr_verbose("%s: %s checksum verification failed\n", cmd, __func__);
+ return NULL;
+ }
+
+ if (ndns) {
+ ndctl_namespace_get_uuid(ndns, uuid);
+ if (verify && !uuid_is_null(uuid) && memcmp(uuid, pfn_sb->parent_uuid,
+ sizeof(uuid) != 0)) {
+ pr_verbose("%s: %s uuid verification failed\n", cmd, __func__);
+ return NULL;
+ }
+ }
+
+ jblock = json_object_new_object();
+ if (!jblock)
+ return NULL;
+
+ if (ndns) {
+ jobj = json_object_new_string(ndctl_namespace_get_devname(ndns));
+ if (!jobj)
+ goto err;
+ json_object_object_add(jblock, "dev", jobj);
+ } else {
+ jobj = json_object_new_string(path);
+ if (!jobj)
+ goto err;
+ json_object_object_add(jblock, "file", jobj);
+ }
+
+ jobj = json_object_new_string((char *) pfn_sb->signature);
+ if (!jobj)
+ goto err;
+ json_object_object_add(jblock, "signature", jobj);
+
+ uuid_unparse((void *) pfn_sb->uuid, str);
+ jobj = json_object_new_string(str);
+ if (!jobj)
+ goto err;
+ json_object_object_add(jblock, "uuid", jobj);
+
+ uuid_unparse((void *) pfn_sb->parent_uuid, str);
+ jobj = json_object_new_string(str);
+ if (!jobj)
+ goto err;
+ json_object_object_add(jblock, "parent_uuid", jobj);
+
+ jobj = util_json_object_hex(le32_to_cpu(pfn_sb->flags), flags);
+ if (!jobj)
+ goto err;
+ json_object_object_add(jblock, "flags", jobj);
+
+ if (snprintf(str, 4, "%d.%d", pfn_sb->version_major,
+ pfn_sb->version_minor) >= 4)
+ goto err;
+ jobj = json_object_new_string(str);
+ if (!jobj)
+ goto err;
+ json_object_object_add(jblock, "version", jobj);
+
+ parse_hex(pfn_sb, dataoff, 64);
+ parse_hex(pfn_sb, npfns, 64);
+ parse_field(pfn_sb, mode);
+ parse_hex(pfn_sb, start_pad, 32);
+ parse_hex(pfn_sb, end_trunc, 32);
+ parse_hex(pfn_sb, align, 32);
+
+ return jblock;
+err:
+ pr_verbose("%s: failed to create json representation\n", cmd);
+ json_object_put(jblock);
+ return NULL;
+}
+
+#define INFOBLOCK_SZ SZ_8K
+
+static int parse_namespace_infoblock(char *_buf, struct ndctl_namespace *ndns,
+ const char *path, struct read_infoblock_ctx *ri_ctx)
+{
+ int rc;
+ void *buf = _buf;
+ unsigned long flags = param.human ? UTIL_JSON_HUMAN : 0;
+ struct btt_sb *btt1_sb = buf + SZ_4K, *btt2_sb = buf;
+ struct json_object *jblock = NULL, *jblocks = ri_ctx->jblocks;
+ struct pfn_sb *pfn_sb = buf + SZ_4K, *dax_sb = buf + SZ_4K;
+
+ if (!param.json) {
+ rc = fwrite(buf, 1, INFOBLOCK_SZ, ri_ctx->f_out);
+ if (rc != INFOBLOCK_SZ)
+ return -EIO;
+ fflush(ri_ctx->f_out);
+ return 0;
+ }
+
+ if (!jblocks) {
+ jblocks = json_object_new_array();
+ if (!jblocks)
+ return -ENOMEM;
+ ri_ctx->jblocks = jblocks;
+ }
+
+ if (memcmp(btt1_sb->signature, BTT_SIG, BTT_SIG_LEN) == 0) {
+ jblock = btt_parse(btt1_sb, ndns, path, flags);
+ if (jblock)
+ json_object_array_add(jblocks, jblock);
+ }
+
+ if (memcmp(btt2_sb->signature, BTT_SIG, BTT_SIG_LEN) == 0) {
+ jblock = btt_parse(btt2_sb, ndns, path, flags);
+ if (jblock)
+ json_object_array_add(jblocks, jblock);
+ }
+
+ if (memcmp(pfn_sb->signature, PFN_SIG, PFN_SIG_LEN) == 0) {
+ jblock = pfn_parse(pfn_sb, ndns, path, flags);
+ if (jblock)
+ json_object_array_add(jblocks, jblock);
+ }
+
+ if (memcmp(dax_sb->signature, DAX_SIG, PFN_SIG_LEN) == 0) {
+ jblock = pfn_parse(dax_sb, ndns, path, flags);
+ if (jblock)
+ json_object_array_add(jblocks, jblock);
+ }
+
+ return 0;
+}
+
+static int file_read_infoblock(const char *path, struct ndctl_namespace *ndns,
+ struct read_infoblock_ctx *ri_ctx)
+{
+ const char *devname = ndns ? ndctl_namespace_get_devname(ndns) : "";
+ const char *cmd = "read-info-block";
+ void *buf = NULL;
+ int fd = -1, rc;
+
+ buf = calloc(1, INFOBLOCK_SZ);
+ if (!buf)
+ return -ENOMEM;
+
+ fd = open(path, O_RDONLY|O_EXCL);
+ if (fd < 0) {
+ pr_verbose("%s: %s failed to open %s: %s\n",
+ cmd, devname, path, strerror(errno));
+ rc = -errno;
+ goto out;
+ }
+
+ rc = read(fd, buf, INFOBLOCK_SZ);
+ if (rc < 0) {
+ pr_verbose("%s: %s failed to read %s: %s\n",
+ cmd, devname, path, strerror(errno));
+ rc = -errno;
+ goto out;
+ }
+
+ rc = parse_namespace_infoblock(buf, ndns, path, ri_ctx);
+out:
+ free(buf);
+ if (fd >= 0)
+ close(fd);
+ return rc;
+}
+
+static int namespace_read_infoblock(struct ndctl_namespace *ndns,
+ struct read_infoblock_ctx *ri_ctx)
+{
+ int rc;
+ char path[50];
+ const char *cmd = "read-info-block";
+ const char *devname = ndctl_namespace_get_devname(ndns);
+
+ if (ndctl_namespace_is_active(ndns)) {
+ pr_verbose("%s: %s enabled, must be disabled\n", cmd, devname);
+ return -EBUSY;
+ }
+
+ ndctl_namespace_set_raw_mode(ndns, 1);
+ rc = ndctl_namespace_enable(ndns);
+ if (rc < 0) {
+ pr_verbose("%s: %s failed to enable\n", cmd, devname);
+ goto out;
+ }
+
+ sprintf(path, "/dev/%s", ndctl_namespace_get_block_device(ndns));
+ rc = file_read_infoblock(path, ndns, ri_ctx);
+
+out:
+ ndctl_namespace_set_raw_mode(ndns, 0);
+ ndctl_namespace_disable_invalidate(ndns);
+ return rc;
+}
+
static int do_xaction_namespace(const char *namespace,
enum device_action action, struct ndctl_ctx *ctx,
int *processed)
{
+ struct read_infoblock_ctx ri_ctx = { 0 };
struct ndctl_namespace *ndns, *_n;
struct ndctl_region *region;
const char *ndns_name;
@@ -1063,6 +1413,26 @@ static int do_xaction_namespace(const char *namespace,
*processed = 0;
+ if (action == ACTION_READ_INFOBLOCK) {
+ if (!param.outfile)
+ ri_ctx.f_out = stdout;
+ else {
+ ri_ctx.f_out = fopen(param.outfile, "w+");
+ if (!ri_ctx.f_out) {
+ fprintf(stderr, "failed to open: %s: (%s)\n",
+ param.outfile, strerror(errno));
+ return -errno;
+ }
+ }
+
+ if (param.infile) {
+ rc = file_read_infoblock(param.infile, NULL, &ri_ctx);
+ if (ri_ctx.jblocks)
+ util_display_json_array(ri_ctx.f_out, ri_ctx.jblocks, 0);
+ return rc;
+ }
+ }
+
if (!namespace && action != ACTION_CREATE)
return rc;
@@ -1136,6 +1506,11 @@ static int do_xaction_namespace(const char *namespace,
if (rc == 0)
*processed = 1;
return rc;
+ case ACTION_READ_INFOBLOCK:
+ rc = namespace_read_infoblock(ndns, &ri_ctx);
+ if (rc == 0)
+ (*processed)++;
+ break;
default:
rc = -EINVAL;
break;
@@ -1144,6 +1519,12 @@ static int do_xaction_namespace(const char *namespace,
}
}
+ if (ri_ctx.jblocks)
+ util_display_json_array(ri_ctx.f_out, ri_ctx.jblocks, 0);
+
+ if (ri_ctx.f_out && ri_ctx.f_out != stdout)
+ fclose(ri_ctx.f_out);
+
return rc;
}
@@ -1240,3 +1621,19 @@ int cmd_check_namespace(int argc , const char **argv, struct ndctl_ctx *ctx)
checked == 1 ? "" : "s");
return rc;
}
+
+int cmd_read_infoblock(int argc , const char **argv, struct ndctl_ctx *ctx)
+{
+ char *xable_usage = "ndctl read-info-block <namespace> [<options>]";
+ const char *namespace = parse_namespace_options(argc, argv,
+ ACTION_READ_INFOBLOCK, read_infoblock_options,
+ xable_usage);
+ int read, rc;
+
+ rc = do_xaction_namespace(namespace, ACTION_READ_INFOBLOCK, ctx, &read);
+ if (rc < 0)
+ fprintf(stderr, "error checking namespaces: %s\n",
+ strerror(-rc));
+ fprintf(stderr, "read %d namespace%s\n", read, read == 1 ? "" : "s");
+ return rc;
+}
diff --git a/ndctl/namespace.h b/ndctl/namespace.h
index bc210857642f..861dfbfa5127 100644
--- a/ndctl/namespace.h
+++ b/ndctl/namespace.h
@@ -13,7 +13,9 @@
#ifndef __NDCTL_NAMESPACE_H__
#define __NDCTL_NAMESPACE_H__
#include <sys/types.h>
+#include <util/util.h>
#include <util/size.h>
+#include <util/fletcher.h>
#include <ccan/endian/endian.h>
#include <ccan/short_types/short_types.h>
@@ -202,4 +204,53 @@ struct arena_map {
struct btt_sb *info2;
size_t info2_len;
};
+
+#define PFN_SIG_LEN 16
+#define PFN_SIG "NVDIMM_PFN_INFO\0"
+#define DAX_SIG "NVDIMM_DAX_INFO\0"
+
+struct pfn_sb {
+ u8 signature[PFN_SIG_LEN];
+ u8 uuid[16];
+ u8 parent_uuid[16];
+ le32 flags;
+ le16 version_major;
+ le16 version_minor;
+ le64 dataoff; /* relative to namespace_base + start_pad */
+ le64 npfns;
+ le32 mode;
+ /* minor-version-1 additions for section alignment */
+ le32 start_pad;
+ le32 end_trunc;
+ /* minor-version-2 record the base alignment of the mapping */
+ le32 align;
+ u8 padding[4000];
+ le64 checksum;
+};
+
+union info_block {
+ struct pfn_sb pfn_sb;
+ struct btt_sb btt_sb;
+};
+
+static inline bool verify_infoblock_checksum(union info_block *sb)
+{
+ uint64_t sum;
+ le64 sum_save;
+
+ BUILD_BUG_ON(sizeof(union info_block) != SZ_4K);
+
+ /* all infoblocks share the btt_sb layout for checksum */
+ sum_save = sb->btt_sb.checksum;
+ sb->btt_sb.checksum = 0;
+ sum = fletcher64(&sb->btt_sb, sizeof(*sb), 1);
+ if (sum != sum_save)
+ return false;
+ /* restore the checksum in the buffer */
+ sb->btt_sb.checksum = sum_save;
+
+ return true;
+}
+
+
#endif /* __NDCTL_NAMESPACE_H__ */
diff --git a/ndctl/ndctl.c b/ndctl/ndctl.c
index bd333b292743..5018d486e2c1 100644
--- a/ndctl/ndctl.c
+++ b/ndctl/ndctl.c
@@ -73,6 +73,7 @@ static struct cmd_struct commands[] = {
{ "disable-namespace", { cmd_disable_namespace } },
{ "create-namespace", { cmd_create_namespace } },
{ "destroy-namespace", { cmd_destroy_namespace } },
+ { "read-infoblock", { cmd_read_infoblock } },
{ "check-namespace", { cmd_check_namespace } },
{ "enable-region", { cmd_enable_region } },
{ "disable-region", { cmd_disable_region } },
diff --git a/util/fletcher.h b/util/fletcher.h
index 54e2ecf5d6ed..8fccac4ec758 100644
--- a/util/fletcher.h
+++ b/util/fletcher.h
@@ -1,6 +1,7 @@
#ifndef _NDCTL_FLETCHER_H_
#define _NDCTL_FLETCHER_H_
+#include <stdbool.h>
#include <ccan/endian/endian.h>
#include <ccan/short_types/short_types.h>
diff --git a/util/size.h b/util/size.h
index 34fac58d6945..2426fef74b3c 100644
--- a/util/size.h
+++ b/util/size.h
@@ -16,6 +16,7 @@
#define SZ_1K 0x00000400
#define SZ_4K 0x00001000
+#define SZ_8K 0x00002000
#define SZ_1M 0x00100000
#define SZ_2M 0x00200000
#define SZ_4M 0x00400000
_______________________________________________
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/8] ndctl/test: Update dax-dev to handle multiple e820 ranges
2019-02-12 21:28 [ndctl PATCH 0/8] Improve support + testing for labels + info-blocks Dan Williams
` (3 preceding siblings ...)
2019-02-12 21:29 ` [ndctl PATCH 4/8] ndctl/namespace: Add read-info-block command Dan Williams
@ 2019-02-12 21:29 ` Dan Williams
2019-02-12 21:29 ` [ndctl PATCH 6/8] ndctl/test: Make dax.sh more robust vs small namespaces Dan Williams
` (2 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Dan Williams @ 2019-02-12 21:29 UTC (permalink / raw)
To: linux-nvdimm
Establish a convention that the first, lowest-index, region on the e820
bus always enables in fsdax mode without need for an nd_pfn instance.
This is in preparation for a defining a collision test that requires
multiple section-mis-aligned regions defined by memmap=nn!ss.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
test/dax-dev.c | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/test/dax-dev.c b/test/dax-dev.c
index 0183b7af2052..49ccaa334e31 100644
--- a/test/dax-dev.c
+++ b/test/dax-dev.c
@@ -33,17 +33,28 @@ struct ndctl_namespace *ndctl_get_test_dev(struct ndctl_ctx *ctx)
struct ndctl_bus *bus;
struct ndctl_dax *dax;
struct ndctl_pfn *pfn;
- struct ndctl_region *region;
struct ndctl_namespace *ndns;
enum ndctl_namespace_mode mode;
+ struct ndctl_region *region, *min = NULL;
bus = ndctl_bus_get_by_provider(ctx, "e820");
if (!bus)
goto out;
- region = ndctl_region_get_first(bus);
- if (!region)
+ ndctl_region_foreach(bus, region) {
+ if (!min) {
+ min = region;
+ continue;
+ }
+ if (ndctl_region_get_id(region) < ndctl_region_get_id(min))
+ min = region;
+ }
+ if (!min)
goto out;
+ region = min;
+
+ /* attempt to re-enable the region if a previous test disabled it */
+ ndctl_region_enable(region);
ndns = ndctl_namespace_get_first(region);
if (!ndns)
_______________________________________________
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/8] ndctl/test: Make dax.sh more robust vs small namespaces
2019-02-12 21:28 [ndctl PATCH 0/8] Improve support + testing for labels + info-blocks Dan Williams
` (4 preceding siblings ...)
2019-02-12 21:29 ` [ndctl PATCH 5/8] ndctl/test: Update dax-dev to handle multiple e820 ranges Dan Williams
@ 2019-02-12 21:29 ` Dan Williams
2019-02-12 21:29 ` [ndctl PATCH 7/8] ndctl/namespace: Always zero info-blocks Dan Williams
2019-02-12 21:29 ` [ndctl PATCH 8/8] ndctl/test: Test inter-region collision handling Dan Williams
7 siblings, 0 replies; 12+ messages in thread
From: Dan Williams @ 2019-02-12 21:29 UTC (permalink / raw)
To: linux-nvdimm
If the namespace returned by test/dax-dev is too small ext4 may default
to a 1K block-size. A 1K block-size precludes dax operation, so force a
4K block-size in all cases.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
test/dax.sh | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/test/dax.sh b/test/dax.sh
index d38fd01acb07..e703e1222dee 100755
--- a/test/dax.sh
+++ b/test/dax.sh
@@ -47,7 +47,7 @@ json=$($NDCTL list -N -n $dev)
eval $(json2var <<< "$json")
rc=1
-mkfs.ext4 /dev/$blockdev
+mkfs.ext4 -b 4096 /dev/$blockdev
mount /dev/$blockdev $MNT -o dax
fallocate -l 1GiB $MNT/$FILE
run_test
@@ -59,7 +59,7 @@ eval $(json2var <<< "$json")
[ $mode != "fsdax" ] && echo "fail: $LINENO" && exit 1
#note the blockdev returned from ndctl create-namespace lacks the /dev prefix
-mkfs.ext4 /dev/$blockdev
+mkfs.ext4 -b 4096 /dev/$blockdev
mount /dev/$blockdev $MNT -o dax
fallocate -l 1GiB $MNT/$FILE
run_test
_______________________________________________
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/8] ndctl/namespace: Always zero info-blocks
2019-02-12 21:28 [ndctl PATCH 0/8] Improve support + testing for labels + info-blocks Dan Williams
` (5 preceding siblings ...)
2019-02-12 21:29 ` [ndctl PATCH 6/8] ndctl/test: Make dax.sh more robust vs small namespaces Dan Williams
@ 2019-02-12 21:29 ` Dan Williams
2019-02-12 21:29 ` [ndctl PATCH 8/8] ndctl/test: Test inter-region collision handling Dan Williams
7 siblings, 0 replies; 12+ messages in thread
From: Dan Williams @ 2019-02-12 21:29 UTC (permalink / raw)
To: linux-nvdimm
Do not gate zeroing on whether a namespace is claimed by a personality.
The namespace might not have been able to be claimed due to info-block
corruption.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
ndctl/namespace.c | 15 +++++----------
1 file changed, 5 insertions(+), 10 deletions(-)
diff --git a/ndctl/namespace.c b/ndctl/namespace.c
index 6e42acb695aa..63b870ff7a6d 100644
--- a/ndctl/namespace.c
+++ b/ndctl/namespace.c
@@ -917,9 +917,6 @@ static int namespace_destroy(struct ndctl_region *region,
struct ndctl_namespace *ndns)
{
const char *devname = ndctl_namespace_get_devname(ndns);
- struct ndctl_pfn *pfn = ndctl_namespace_get_pfn(ndns);
- struct ndctl_dax *dax = ndctl_namespace_get_dax(ndns);
- struct ndctl_btt *btt = ndctl_namespace_get_btt(ndns);
bool did_zero = false;
int rc;
@@ -941,13 +938,11 @@ static int namespace_destroy(struct ndctl_region *region,
ndctl_namespace_set_enforce_mode(ndns, NDCTL_NS_MODE_RAW);
- if (pfn || btt || dax) {
- rc = zero_info_block(ndns);
- if (rc < 0)
- return rc;
- if (rc == 0)
- did_zero = true;
- }
+ rc = zero_info_block(ndns);
+ if (rc < 0)
+ return rc;
+ if (rc == 0)
+ did_zero = true;
switch (ndctl_namespace_get_type(ndns)) {
case ND_DEVICE_NAMESPACE_PMEM:
_______________________________________________
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 8/8] ndctl/test: Test inter-region collision handling
2019-02-12 21:28 [ndctl PATCH 0/8] Improve support + testing for labels + info-blocks Dan Williams
` (6 preceding siblings ...)
2019-02-12 21:29 ` [ndctl PATCH 7/8] ndctl/namespace: Always zero info-blocks Dan Williams
@ 2019-02-12 21:29 ` Dan Williams
7 siblings, 0 replies; 12+ messages in thread
From: Dan Williams @ 2019-02-12 21:29 UTC (permalink / raw)
To: linux-nvdimm
Given the discovery of a broken padding implementation in the kernel
introduce a regression test to validate collision handling and dax
operation. It is known to fail as of v5.0-rc1.
The test relies on a custom memmap= configuration to generate the
problematic physical alignment condition. Details of the required memmap
configuration are listed / validated in the test script.
The test also validates that the kernel implementation preserves the
pre-v1.3 info block behavior while implementing the new v1.3+ behavior.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
test/Makefile.am | 1
test/collide.sh | 226 ++++++++++++++++++++++++++++++++++++++++++++++++++
test/fsdax-info0.xxd | 11 ++
test/fsdax-info1.xxd | 11 ++
test/fsdax-info2.xxd | 11 ++
test/fsdax-info3.xxd | 11 ++
6 files changed, 271 insertions(+)
create mode 100755 test/collide.sh
create mode 100644 test/fsdax-info0.xxd
create mode 100644 test/fsdax-info1.xxd
create mode 100644 test/fsdax-info2.xxd
create mode 100644 test/fsdax-info3.xxd
diff --git a/test/Makefile.am b/test/Makefile.am
index 42009c310b14..2f7cf5f24afd 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -53,6 +53,7 @@ TESTS +=\
dax.sh \
device-dax \
device-dax-fio.sh \
+ collide.sh \
mmap.sh
check_PROGRAMS +=\
diff --git a/test/collide.sh b/test/collide.sh
new file mode 100755
index 000000000000..65b2664bbcc3
--- /dev/null
+++ b/test/collide.sh
@@ -0,0 +1,226 @@
+#!/bin/bash -x
+
+# SPDX-License-Identifier: GPL-2.0
+# Copyright(c) 2015-2019 Intel Corporation. All rights reserved.
+
+set -e
+
+SKIP=77
+FAIL=1
+SUCCESS=0
+
+. ./common
+
+check_min_kver "5.0" || do_skip "may lack align collision fixes"
+check_prereq xxd
+
+MNT=test_dax_mnt
+mkdir -p $MNT
+
+rc=$FAIL
+cleanup() {
+ if [ $rc -ne $SUCCESS ]; then
+ echo "test/collide.sh: failed at line $1"
+ fi
+ if mountpoint -q $MNT; then
+ umount $MNT
+ fi
+ rmdir $MNT
+ # opportunistic cleanup, not fatal if these fail
+ for i in $regions
+ do
+ if ! $NDCTL destroy-namespace -f -r $i all; then
+ echo "test/collide.sh: cleanup() failed to destroy $i"
+ fi
+ if ! $NDCTL enable-namespace -r $i all; then
+ echo "test/collide.sh: cleanup() failed to re-enable $i"
+ fi
+ done
+ exit $rc
+}
+
+
+trap 'err $LINENO cleanup' ERR
+
+modprobe nd_e820
+
+# Require TEST_NUM consecutive regions of TEST_SIZE in size, where
+# TEST_SIZE causes every other namespace to collide within a 128MB
+# boundary. I.e. trigger the kernel to allocate a 'start_pad' area. As
+# of writing, an example memmap= configuration this test expects is:
+# memmap=$((4 << 30))!$((( 7 << 30)))
+# memmap=$((64 * 3 << 20))!$(((11 << 30)))
+# memmap=$((64 * 3 << 20))!$(((11 << 30) + (64 * 3 << 20)))
+# memmap=$((64 * 3 << 20))!$(((11 << 30) + (64 * 6 << 20)))
+# memmap=$((64 * 3 << 20))!$(((11 << 30) + (64 * 9 << 20)))
+# ...where the first region is the area for tests that depend on the
+# namespace identified by test/dax-dev, and the rest are four namespace
+# that collide per the expectations of this test.
+TEST_NUM=4
+TEST_SIZE=$((64*3 << 20))
+json=$($NDCTL list -Ri -b e820)
+len=$(echo $json | jq length)
+if [ $len -lt $TEST_NUM ]; then
+ exit $SKIP
+fi
+
+found=0
+prev_resource=0
+regions=$(echo $json | jq -r ". | sort_by(.dev) | .[].dev")
+first_region=""
+for i in $regions
+do
+ resource=$(cat /sys/bus/nd/devices/$i/resource)
+ size=$(cat /sys/bus/nd/devices/$i/size)
+ if [ $((size)) -ne $TEST_SIZE ]; then
+ prev_resource=0
+ found=0
+ continue
+ fi
+ if [ $((prev_resource)) -gt 0 ]; then
+ if [ $((prev_resource + TEST_SIZE)) -ne $((resource)) ]; then
+ prev_resource=0
+ found=0
+ else
+ prev_resource=$resource
+ found=$((found+1))
+ fi
+ else
+ first_region=$i
+ prev_resource=$resource
+ found=1
+ fi
+done
+if [ $found -lt $TEST_NUM ]; then
+ echo "failed to find $TEST_NUM regions of size $((TEST_SIZE >> 20))MB"
+ exit $FAIL
+fi
+
+region_id() {
+ echo ${1:6}
+}
+
+reset_region() {
+ id=$(region_id $1)
+ idx=$2
+ ns="namespace${id}.0"
+ # clear out any existing info blocks
+ $NDCTL enable-region $1
+ $NDCTL destroy-namespace $ns -f
+
+ # check that every other namespace fails to auto-enable due to
+ # dev_pagemap collisions
+ if $NDCTL enable-namespace $ns; then
+ if [ $((idx & 1)) -eq 1 ]; then
+ echo "expected enable region$id (idx: $idx) failure"
+ exit $FAIL
+ fi
+ else
+ if [ $((idx & 1)) -eq 0 ]; then
+ echo "expected enable region$id (idx: $idx) success"
+ exit $FAIL
+ fi
+ fi
+}
+
+restore_region() {
+ id=$(region_id $1)
+ idx=$2
+ ns="namespace${id}.0"
+ # restore saved v1.2 info block
+ $NDCTL enable-region $1
+ $NDCTL destroy-namespace $ns -f
+ echo 1 > /sys/bus/nd/devices/$ns/force_raw
+ $NDCTL enable-namespace $ns
+ xxd -r fsdax-info$idx.xxd /dev/pmem$id
+ blockdev --flushbufs /dev/pmem$id
+ echo 0 > /sys/bus/nd/devices/$ns/force_raw
+ $NDCTL disable-namespace $ns
+
+ # check size
+ $NDCTL enable-namespace $ns
+ size=$($NDCTL list -n $ns | jq -r '.[].size')
+ if [ $size -ne 130023424 ]; then
+ false
+ fi
+
+ # check for every other @idx dax-mount fails
+ mkfs.ext4 -b 4096 /dev/pmem$id
+ fail=0
+ mount -o dax /dev/pmem$id $MNT || fail=1
+ if [ $fail -eq 0 ]; then
+ umount $MNT
+ if [ $((idx & 1)) -eq 1 ]; then
+ echo "expected dax-mount region$id (idx: $idx) failure"
+ false
+ fi
+ else
+ if [ $((idx & 1)) -eq 0 ]; then
+ echo "expected dax-mount region$id (idx: $idx) success"
+ false
+ fi
+ fi
+}
+
+# validate pre-5.1 info block handling
+idx=0
+$NDCTL disable-region all -b e820
+for i in $regions
+do
+ if [ $(region_id $i) -lt $(region_id $first_region) ]; then
+ continue
+ fi
+ restore_region $i $idx
+ idx=$((idx+1))
+done
+
+# validate alignment collision assumptions
+idx=0
+$NDCTL disable-region -b e820 all
+for i in $regions
+do
+ if [ $(region_id $i) -lt $(region_id $first_region) ]; then
+ continue
+ fi
+ reset_region $i $idx
+ idx=$((idx+1))
+done
+
+# use ext4 to check for successful dax mount
+check_dax() {
+ id=$(region_id $1)
+ idx=$2
+ ns="namespace${id}.0"
+
+ $NDCTL create-namespace -e $ns -m fsdax -M dev -f
+ mkfs.ext4 -b 4096 /dev/pmem$id
+ mount -o dax /dev/pmem$id $MNT
+ umount $MNT
+}
+
+check_size() {
+ id=$(region_id $1)
+ ns="namespace${id}.0"
+ pfn_size=$($NDCTL list -n $ns | jq -r ".[] | .size")
+ bdev_size=$(blockdev --getsize64 /dev/pmem$id)
+
+ if [ $pfn_size -ne $bdev_size ]; then
+ false
+ fi
+}
+
+for i in $regions
+do
+ if [ $(region_id $i) -lt $(region_id $first_region) ]; then
+ continue
+ fi
+ check_dax $i
+ check_size $i
+done
+
+# check probe
+$NDCTL disable-namespace -b e820 all
+$NDCTL enable-namespace -b e820 all
+
+rc=$SUCCESS
+cleanup $LINENO
diff --git a/test/fsdax-info0.xxd b/test/fsdax-info0.xxd
new file mode 100644
index 000000000000..a89f581ffd7e
--- /dev/null
+++ b/test/fsdax-info0.xxd
@@ -0,0 +1,11 @@
+00000000: 0000 0000 0000 0000 0000 0000 0000 0000 ................
+*
+00001000: 4e56 4449 4d4d 5f50 464e 5f49 4e46 4f00 NVDIMM_PFN_INFO.
+00001010: 2406 11fa 696a 40e7 b85f b9b9 e326 4a3a $...ij@.._...&J:
+00001020: 0000 0000 0000 0000 0000 0000 0000 0000 ................
+00001030: 0000 0000 0100 0200 0000 4000 0000 0000 ..........@.....
+00001040: 007c 0000 0000 0000 0200 0000 0000 0000 .|..............
+00001050: 0000 0004 0000 2000 0200 0000 0000 0000 ...... .........
+00001060: 0000 0000 0000 0000 0000 0000 0000 0000 ................
+*
+00001ff0: 0000 0000 0000 0000 5cab 09bd be77 7a8d ........\....wz.
diff --git a/test/fsdax-info1.xxd b/test/fsdax-info1.xxd
new file mode 100644
index 000000000000..36dd36d897bc
--- /dev/null
+++ b/test/fsdax-info1.xxd
@@ -0,0 +1,11 @@
+00000000: 0000 0000 0000 0000 0000 0000 0000 0000 ................
+*
+00001000: 4e56 4449 4d4d 5f50 464e 5f49 4e46 4f00 NVDIMM_PFN_INFO.
+00001010: af1d b9a0 b422 4188 8b3f 67bc 610c 546b ....."A..?g.a.Tk
+00001020: 0000 0000 0000 0000 0000 0000 0000 0000 ................
+00001030: 0000 0000 0100 0200 0000 4000 0000 0000 ..........@.....
+00001040: 007c 0000 0000 0000 0200 0000 0000 0004 .|..............
+00001050: 0000 0000 0000 2000 0200 0000 0000 0000 ...... .........
+00001060: 0000 0000 0000 0000 0000 0000 0000 0000 ................
+*
+00001ff0: 0000 0000 0000 0000 8340 6a38 b796 d2ec .........@j8....
diff --git a/test/fsdax-info2.xxd b/test/fsdax-info2.xxd
new file mode 100644
index 000000000000..dc19f7a89342
--- /dev/null
+++ b/test/fsdax-info2.xxd
@@ -0,0 +1,11 @@
+00000000: 0000 0000 0000 0000 0000 0000 0000 0000 ................
+*
+00001000: 4e56 4449 4d4d 5f50 464e 5f49 4e46 4f00 NVDIMM_PFN_INFO.
+00001010: 4c1e 026f 2939 4910 bcf7 0f8e 4dbd ab56 L..o)9I.....M..V
+00001020: 0000 0000 0000 0000 0000 0000 0000 0000 ................
+00001030: 0000 0000 0100 0200 0000 4000 0000 0000 ..........@.....
+00001040: 007c 0000 0000 0000 0200 0000 0000 0000 .|..............
+00001050: 0000 0004 0000 2000 0200 0000 0000 0000 ...... .........
+00001060: 0000 0000 0000 0000 0000 0000 0000 0000 ................
+*
+00001ff0: 0000 0000 0000 0000 b2c0 bb4b 60b8 2cf4 ...........K`.,.
diff --git a/test/fsdax-info3.xxd b/test/fsdax-info3.xxd
new file mode 100644
index 000000000000..468fea13b78a
--- /dev/null
+++ b/test/fsdax-info3.xxd
@@ -0,0 +1,11 @@
+00000000: 0000 0000 0000 0000 0000 0000 0000 0000 ................
+*
+00001000: 4e56 4449 4d4d 5f50 464e 5f49 4e46 4f00 NVDIMM_PFN_INFO.
+00001010: 80ee 77a1 321b 4938 80f2 74a5 234d 2468 ..w.2.I8..t.#M$h
+00001020: 0000 0000 0000 0000 0000 0000 0000 0000 ................
+00001030: 0000 0000 0100 0200 0000 4000 0000 0000 ..........@.....
+00001040: 007c 0000 0000 0000 0200 0000 0000 0004 .|..............
+00001050: 0000 0000 0000 2000 0200 0000 0000 0000 ...... .........
+00001060: 0000 0000 0000 0000 0000 0000 0000 0000 ................
+*
+00001ff0: 0000 0000 0000 0000 89fd 0ecf f199 9fac ................
_______________________________________________
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 2/8] ndctl/dimm: Add --human support to read-labels
2019-02-12 21:28 ` [ndctl PATCH 2/8] ndctl/dimm: Add --human support to read-labels Dan Williams
@ 2019-03-19 22:39 ` Verma, Vishal L
2019-03-19 22:51 ` Dan Williams
0 siblings, 1 reply; 12+ messages in thread
From: Verma, Vishal L @ 2019-03-19 22:39 UTC (permalink / raw)
To: Williams, Dan J, linux-nvdimm
On Tue, 2019-02-12 at 13:28 -0800, Dan Williams wrote:
> Allow for easier comparisons between 'read-labels' output and list.
>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> ---
> ndctl/dimm.c | 18 +++++++++++-------
> 1 file changed, 11 insertions(+), 7 deletions(-)
>
> diff --git a/ndctl/dimm.c b/ndctl/dimm.c
> index 292beebf9734..5ff730f42a45 100644
> --- a/ndctl/dimm.c
> +++ b/ndctl/dimm.c
> @@ -50,6 +50,7 @@ static struct parameters {
> bool crypto_erase;
> bool overwrite;
> bool master_pass;
> + bool human;
Should --human also imply --json? It doesn't make sense to have human
for binary data, so it might be surprising if --human doesn't output
json.
Also I think this is missing the man page update to add --human (and
that would be a good place to clarify the human/json behavior).
Looks good otherwise.
_______________________________________________
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 2/8] ndctl/dimm: Add --human support to read-labels
2019-03-19 22:39 ` Verma, Vishal L
@ 2019-03-19 22:51 ` Dan Williams
0 siblings, 0 replies; 12+ messages in thread
From: Dan Williams @ 2019-03-19 22:51 UTC (permalink / raw)
To: Verma, Vishal L; +Cc: linux-nvdimm
On Tue, Mar 19, 2019 at 3:39 PM Verma, Vishal L
<vishal.l.verma@intel.com> wrote:
>
>
> On Tue, 2019-02-12 at 13:28 -0800, Dan Williams wrote:
> > Allow for easier comparisons between 'read-labels' output and list.
> >
> > Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> > ---
> > ndctl/dimm.c | 18 +++++++++++-------
> > 1 file changed, 11 insertions(+), 7 deletions(-)
> >
> > diff --git a/ndctl/dimm.c b/ndctl/dimm.c
> > index 292beebf9734..5ff730f42a45 100644
> > --- a/ndctl/dimm.c
> > +++ b/ndctl/dimm.c
> > @@ -50,6 +50,7 @@ static struct parameters {
> > bool crypto_erase;
> > bool overwrite;
> > bool master_pass;
> > + bool human;
>
> Should --human also imply --json? It doesn't make sense to have human
> for binary data, so it might be surprising if --human doesn't output
> json.
>
> Also I think this is missing the man page update to add --human (and
> that would be a good place to clarify the human/json behavior).
>
Agree with both.
> Looks good otherwise.
Will respin, 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 4/8] ndctl/namespace: Add read-info-block command
2019-02-12 21:29 ` [ndctl PATCH 4/8] ndctl/namespace: Add read-info-block command Dan Williams
@ 2019-03-19 23:11 ` Verma, Vishal L
0 siblings, 0 replies; 12+ messages in thread
From: Verma, Vishal L @ 2019-03-19 23:11 UTC (permalink / raw)
To: Williams, Dan J, linux-nvdimm
On Tue, 2019-02-12 at 13:29 -0800, Dan Williams wrote:
> Namespaces may contain an info-block that correlates with the possible
> modes of a namespace: 'sector', 'fsdax', or 'devdax'. Provide a command
> that can temporarily convert the namespace into 'raw' mode to read the
> info-block.
>
> Also, similar to 'read-labels' provide a facility to decode the
> info-block into json.
Nice, I like this!
>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> ---
> ndctl/action.h | 1
> ndctl/builtin.h | 1
> ndctl/check.c | 20 ---
> ndctl/namespace.c | 401 +++++++++++++++++++++++++++++++++++++++++++++++++++++
> ndctl/namespace.h | 51 +++++++
> ndctl/ndctl.c | 1
> util/fletcher.h | 1
> util/size.h | 1
> 8 files changed, 456 insertions(+), 21 deletions(-)
[..]
>
> +#define READ_INFOBLOCK_OPTIONS() \
> +OPT_FILENAME('o', "output", ¶m.outfile, "output-file", \
> + "filename to write label area contents"), \
copy/paste staleness, should be "write infoblock contents"
> +OPT_FILENAME('f', "file", ¶m.infile, "input-file", \
> + "filename to readinfo block instead of a namespace"), \
Perhaps make this consistent with the label commands, and call the file
option -i/--input. This also frees up -f for --force, which might be
nice to have since the namespaces are expected to be disabled (That's
only a minor convenience thing though - I'm equally OK leaving out the
--force for now)
> +OPT_BOOLEAN('n', "no-verify", ¶m.no_verify, \
> + "skip parent uuid, and checksum validation"), \
Since the option handling framework automatically provides a no-* option
for boolean options, should we call this --verify, default to on, and
then document the availability of the automatic --no-verify option?
Currently, this ends up in an automatic --no-no-verify option :)
> +OPT_BOOLEAN('j', "json", ¶m.json, "parse label data into json"), \
> +OPT_BOOLEAN('u', "human", ¶m.human, "use human friendly number formats ")
> +
[..]
> + if (mode == ACTION_READ_INFOBLOCK && param.infile && argc) {
> + error("specify a namespace, or --file, not both\n");
> + rc = -EINVAL;
> + }
> +
Similar comment as read-labels about auto enabling --json if --human
supplied standalone.
_______________________________________________
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
end of thread, other threads:[~2019-03-19 23:11 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-12 21:28 [ndctl PATCH 0/8] Improve support + testing for labels + info-blocks Dan Williams
2019-02-12 21:28 ` [ndctl PATCH 1/8] ndctl/dimm: Add 'flags' field to read-labels output Dan Williams
2019-02-12 21:28 ` [ndctl PATCH 2/8] ndctl/dimm: Add --human support to read-labels Dan Williams
2019-03-19 22:39 ` Verma, Vishal L
2019-03-19 22:51 ` Dan Williams
2019-02-12 21:29 ` [ndctl PATCH 3/8] ndctl/build: Drop -Wpointer-arith Dan Williams
2019-02-12 21:29 ` [ndctl PATCH 4/8] ndctl/namespace: Add read-info-block command Dan Williams
2019-03-19 23:11 ` Verma, Vishal L
2019-02-12 21:29 ` [ndctl PATCH 5/8] ndctl/test: Update dax-dev to handle multiple e820 ranges Dan Williams
2019-02-12 21:29 ` [ndctl PATCH 6/8] ndctl/test: Make dax.sh more robust vs small namespaces Dan Williams
2019-02-12 21:29 ` [ndctl PATCH 7/8] ndctl/namespace: Always zero info-blocks Dan Williams
2019-02-12 21:29 ` [ndctl PATCH 8/8] ndctl/test: Test inter-region collision handling 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).