|
|
e0018b |
From 7e98977c10ad5f4baf5e3bc4d5b4b2fd733a8b7e Mon Sep 17 00:00:00 2001
|
|
|
e0018b |
From: Jingqi Liu <jingqi.liu@intel.com>
|
|
|
e0018b |
Date: Thu, 8 Jul 2021 16:14:46 +0800
|
|
|
e0018b |
Subject: [PATCH 027/217] ndctl/dimm: Fix label index block calculations
|
|
|
e0018b |
|
|
|
e0018b |
The following bug is caused by setting the size of Label Index Block
|
|
|
e0018b |
to a fixed 256 bytes.
|
|
|
e0018b |
|
|
|
e0018b |
Use the following Qemu command to start a Guest with 2MB label-size:
|
|
|
e0018b |
-object memory-backend-file,id=mem1,share=on,mem-path=/dev/dax1.1,size=14G,align=2M
|
|
|
e0018b |
-device nvdimm,memdev=mem1,id=nv1,label-size=2M
|
|
|
e0018b |
|
|
|
e0018b |
There is a namespace in the Guest as follows:
|
|
|
e0018b |
$ ndctl list
|
|
|
e0018b |
[
|
|
|
e0018b |
{
|
|
|
e0018b |
"dev":"namespace0.0",
|
|
|
e0018b |
"mode":"devdax",
|
|
|
e0018b |
"map":"dev",
|
|
|
e0018b |
"size":14780727296,
|
|
|
e0018b |
"uuid":"58ad5282-5a16-404f-b8ee-e28b4c784eb8",
|
|
|
e0018b |
"chardev":"dax0.0",
|
|
|
e0018b |
"align":2097152,
|
|
|
e0018b |
"name":"namespace0.0"
|
|
|
e0018b |
}
|
|
|
e0018b |
]
|
|
|
e0018b |
|
|
|
e0018b |
Fail to read labels. The result is as follows:
|
|
|
e0018b |
$ ndctl read-labels -u nmem0
|
|
|
e0018b |
[
|
|
|
e0018b |
]
|
|
|
e0018b |
read 0 nmem
|
|
|
e0018b |
|
|
|
e0018b |
If using the following Qemu command to start the Guest with 128K
|
|
|
e0018b |
label-size, this label can be read correctly.
|
|
|
e0018b |
-object memory-backend-file,id=mem1,share=on,mem-path=/dev/dax1.1,size=14G,align=2M
|
|
|
e0018b |
-device nvdimm,memdev=mem1,id=nv1,label-size=128K
|
|
|
e0018b |
|
|
|
e0018b |
The size of a Label Index Block depends on how many label slots fit into
|
|
|
e0018b |
the label storage area. The minimum size of an index block is 256 bytes
|
|
|
e0018b |
and the size must be a multiple of 256 bytes. For a storage area of 128KB,
|
|
|
e0018b |
the corresponding Label Index Block size is 256 bytes. But if the label
|
|
|
e0018b |
storage area is not 128KB, the Label Index Block size should not be 256 bytes.
|
|
|
e0018b |
|
|
|
e0018b |
Namespace Label Index Block appears twice at the top of the label storage area.
|
|
|
e0018b |
Following the two index blocks, an array for storing labels takes up the
|
|
|
e0018b |
remainder of the label storage area.
|
|
|
e0018b |
|
|
|
e0018b |
For obtaining the size of Namespace Index Block, we also cannot rely on
|
|
|
e0018b |
the field of 'mysize' in this index block since it might be corrupted.
|
|
|
e0018b |
Similar to the linux kernel, we use sizeof_namespace_index() to get the size
|
|
|
e0018b |
of Namespace Index Block. Then we can also correctly calculate the starting
|
|
|
e0018b |
offset of the following namespace labels.
|
|
|
e0018b |
|
|
|
e0018b |
Link: https://lore.kernel.org/r/20210708081446.14323-1-jingqi.liu@intel.com
|
|
|
e0018b |
Suggested-by: Dan Williams <dan.j.williams@intel.com>
|
|
|
e0018b |
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
|
|
|
e0018b |
Reviewed-by: Vishal Verma <vishal.l.verma@intel.com>
|
|
|
e0018b |
Signed-off-by: Jingqi Liu <jingqi.liu@intel.com>
|
|
|
e0018b |
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
|
|
e0018b |
---
|
|
|
e0018b |
ndctl/dimm.c | 19 +++++++++++++++----
|
|
|
e0018b |
ndctl/lib/dimm.c | 5 +++++
|
|
|
e0018b |
ndctl/lib/libndctl.sym | 1 +
|
|
|
e0018b |
ndctl/libndctl.h | 1 +
|
|
|
e0018b |
4 files changed, 22 insertions(+), 4 deletions(-)
|
|
|
e0018b |
|
|
|
e0018b |
diff --git a/ndctl/dimm.c b/ndctl/dimm.c
|
|
|
e0018b |
index 09ce49e..1d2d9a2 100644
|
|
|
e0018b |
--- a/ndctl/dimm.c
|
|
|
e0018b |
+++ b/ndctl/dimm.c
|
|
|
e0018b |
@@ -94,13 +94,18 @@ static struct json_object *dump_label_json(struct ndctl_dimm *dimm,
|
|
|
e0018b |
struct json_object *jarray = json_object_new_array();
|
|
|
e0018b |
struct json_object *jlabel = NULL;
|
|
|
e0018b |
struct namespace_label nslabel;
|
|
|
e0018b |
+ unsigned int nsindex_size;
|
|
|
e0018b |
unsigned int slot = -1;
|
|
|
e0018b |
ssize_t offset;
|
|
|
e0018b |
|
|
|
e0018b |
if (!jarray)
|
|
|
e0018b |
return NULL;
|
|
|
e0018b |
|
|
|
e0018b |
- for (offset = NSINDEX_ALIGN * 2; offset < size;
|
|
|
e0018b |
+ nsindex_size = ndctl_dimm_sizeof_namespace_index(dimm);
|
|
|
e0018b |
+ if (nsindex_size == 0)
|
|
|
e0018b |
+ return NULL;
|
|
|
e0018b |
+
|
|
|
e0018b |
+ for (offset = nsindex_size * 2; offset < size;
|
|
|
e0018b |
offset += ndctl_dimm_sizeof_namespace_label(dimm)) {
|
|
|
e0018b |
ssize_t len = min_t(ssize_t,
|
|
|
e0018b |
ndctl_dimm_sizeof_namespace_label(dimm),
|
|
|
e0018b |
@@ -204,17 +209,23 @@ static struct json_object *dump_label_json(struct ndctl_dimm *dimm,
|
|
|
e0018b |
return jarray;
|
|
|
e0018b |
}
|
|
|
e0018b |
|
|
|
e0018b |
-static struct json_object *dump_index_json(struct ndctl_cmd *cmd_read, ssize_t size)
|
|
|
e0018b |
+static struct json_object *dump_index_json(struct ndctl_dimm *dimm,
|
|
|
e0018b |
+ struct ndctl_cmd *cmd_read, ssize_t size)
|
|
|
e0018b |
{
|
|
|
e0018b |
struct json_object *jarray = json_object_new_array();
|
|
|
e0018b |
struct json_object *jindex = NULL;
|
|
|
e0018b |
struct namespace_index nsindex;
|
|
|
e0018b |
+ unsigned int nsindex_size;
|
|
|
e0018b |
ssize_t offset;
|
|
|
e0018b |
|
|
|
e0018b |
if (!jarray)
|
|
|
e0018b |
return NULL;
|
|
|
e0018b |
|
|
|
e0018b |
- for (offset = 0; offset < NSINDEX_ALIGN * 2; offset += NSINDEX_ALIGN) {
|
|
|
e0018b |
+ nsindex_size = ndctl_dimm_sizeof_namespace_index(dimm);
|
|
|
e0018b |
+ if (nsindex_size == 0)
|
|
|
e0018b |
+ return NULL;
|
|
|
e0018b |
+
|
|
|
e0018b |
+ for (offset = 0; offset < nsindex_size * 2; offset += nsindex_size) {
|
|
|
e0018b |
ssize_t len = min_t(ssize_t, sizeof(nsindex), size - offset);
|
|
|
e0018b |
struct json_object *jobj;
|
|
|
e0018b |
|
|
|
e0018b |
@@ -288,7 +299,7 @@ static struct json_object *dump_json(struct ndctl_dimm *dimm,
|
|
|
e0018b |
goto err;
|
|
|
e0018b |
json_object_object_add(jdimm, "dev", jobj);
|
|
|
e0018b |
|
|
|
e0018b |
- jindex = dump_index_json(cmd_read, size);
|
|
|
e0018b |
+ jindex = dump_index_json(dimm, cmd_read, size);
|
|
|
e0018b |
if (!jindex)
|
|
|
e0018b |
goto err;
|
|
|
e0018b |
json_object_object_add(jdimm, "index", jindex);
|
|
|
e0018b |
diff --git a/ndctl/lib/dimm.c b/ndctl/lib/dimm.c
|
|
|
e0018b |
index c045cbe..9e36e28 100644
|
|
|
e0018b |
--- a/ndctl/lib/dimm.c
|
|
|
e0018b |
+++ b/ndctl/lib/dimm.c
|
|
|
e0018b |
@@ -256,6 +256,11 @@ static int __label_validate(struct nvdimm_data *ndd)
|
|
|
e0018b |
return -EINVAL;
|
|
|
e0018b |
}
|
|
|
e0018b |
|
|
|
e0018b |
+NDCTL_EXPORT unsigned int ndctl_dimm_sizeof_namespace_index(struct ndctl_dimm *dimm)
|
|
|
e0018b |
+{
|
|
|
e0018b |
+ return sizeof_namespace_index(&dimm->ndd);
|
|
|
e0018b |
+}
|
|
|
e0018b |
+
|
|
|
e0018b |
/*
|
|
|
e0018b |
* If the dimm labels have not been previously validated this routine
|
|
|
e0018b |
* will make up a default size. Otherwise, it will pick the size based
|
|
|
e0018b |
diff --git a/ndctl/lib/libndctl.sym b/ndctl/lib/libndctl.sym
|
|
|
e0018b |
index 58afb74..5ee73b7 100644
|
|
|
e0018b |
--- a/ndctl/lib/libndctl.sym
|
|
|
e0018b |
+++ b/ndctl/lib/libndctl.sym
|
|
|
e0018b |
@@ -454,4 +454,5 @@ LIBNDCTL_25 {
|
|
|
e0018b |
|
|
|
e0018b |
LIBNDCTL_26 {
|
|
|
e0018b |
ndctl_bus_nfit_translate_spa;
|
|
|
e0018b |
+ ndctl_dimm_sizeof_namespace_index;
|
|
|
e0018b |
} LIBNDCTL_25;
|
|
|
e0018b |
diff --git a/ndctl/libndctl.h b/ndctl/libndctl.h
|
|
|
e0018b |
index 87d07b7..df109bb 100644
|
|
|
e0018b |
--- a/ndctl/libndctl.h
|
|
|
e0018b |
+++ b/ndctl/libndctl.h
|
|
|
e0018b |
@@ -337,6 +337,7 @@ int ndctl_dimm_init_labels(struct ndctl_dimm *dimm,
|
|
|
e0018b |
enum ndctl_namespace_version v);
|
|
|
e0018b |
unsigned long ndctl_dimm_get_available_labels(struct ndctl_dimm *dimm);
|
|
|
e0018b |
unsigned int ndctl_dimm_sizeof_namespace_label(struct ndctl_dimm *dimm);
|
|
|
e0018b |
+unsigned int ndctl_dimm_sizeof_namespace_index(struct ndctl_dimm *dimm);
|
|
|
e0018b |
unsigned int ndctl_cmd_cfg_size_get_size(struct ndctl_cmd *cfg_size);
|
|
|
e0018b |
ssize_t ndctl_cmd_cfg_read_get_data(struct ndctl_cmd *cfg_read, void *buf,
|
|
|
e0018b |
unsigned int len, unsigned int offset);
|
|
|
e0018b |
--
|
|
|
e0018b |
2.27.0
|
|
|
e0018b |
|