[PATCH v3 0/3] nfit, address-range-scrub: rework and fixes
by Dan Williams
Changes since v2 [1]:
* Handle -EAGAIN (no result) ars_status responses
---
Given the fact that ARS can take 10s to 100s of seconds it is not
feasible to wait for ARS completion before publishing persistent memory
namespaces. Instead convert the ARS implementation to perform a short
ARS for critical errors, ones that caused a previous system reset,
before registering namespaces. Finally, arrange for all long ARS
operations to run in the background and populate the badblock lists at
run time.
In the extreme situation that an implementation is unable to return
sufficient results in a short scan and the system encounters media
errors that machine check recovery does not handle, an administrator can
arrange to wait for a full ARS scan by doing the following:
1/ Boot with "modprobe.blacklist=nd_pmem" to stop pmem namespaces from
starting automatically
2/ Call "ndctl wait-scrub" to wait for the OS or BIOS initiated ARS to complete
3/ Manually start up namespaces with the up to date error list
"modprobe nd_pmem"
---
Dan Williams (3):
nfit, address-range-scrub: determine one platform max_ars value
nfit, address-range-scrub: rework and simplify ARS state machine
nfit, address-range-scrub: add module option to skip initial ars
drivers/acpi/nfit/core.c | 557 +++++++++++++++++++++-------------------------
drivers/acpi/nfit/nfit.h | 6
2 files changed, 261 insertions(+), 302 deletions(-)
4 years, 2 months
[PATCH] libnvdimm, region: quiet region probe
by Dan Williams
The message about constraining number of online cpus to be less than or
equal to ND_MAX_LANES (256) is only useful for block-aperture
configurations and BTT. Make it debug since its only relevant when
debugging performance.
Signed-off-by: Dan Williams <dan.j.williams(a)intel.com>
---
drivers/nvdimm/region.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/nvdimm/region.c b/drivers/nvdimm/region.c
index 034f0a07d627..b9ca0033cc99 100644
--- a/drivers/nvdimm/region.c
+++ b/drivers/nvdimm/region.c
@@ -27,10 +27,10 @@ static int nd_region_probe(struct device *dev)
if (nd_region->num_lanes > num_online_cpus()
&& nd_region->num_lanes < num_possible_cpus()
&& !test_and_set_bit(0, &once)) {
- dev_info(dev, "online cpus (%d) < concurrent i/o lanes (%d) < possible cpus (%d)\n",
+ dev_dbg(dev, "online cpus (%d) < concurrent i/o lanes (%d) < possible cpus (%d)\n",
num_online_cpus(), nd_region->num_lanes,
num_possible_cpus());
- dev_info(dev, "setting nr_cpus=%d may yield better libnvdimm device performance\n",
+ dev_dbg(dev, "setting nr_cpus=%d may yield better libnvdimm device performance\n",
nd_region->num_lanes);
}
4 years, 2 months
[PATCH] libnvdimm, namespace: use a safe lookup for dimm device name
by Dan Williams
The following NULL dereference results from incorrectly assuming that
ndd is valid in this print:
struct nvdimm_drvdata *ndd = to_ndd(&nd_region->mapping[i]);
/*
* Give up if we don't find an instance of a uuid at each
* position (from 0 to nd_region->ndr_mappings - 1), or if we
* find a dimm with two instances of the same uuid.
*/
dev_err(&nd_region->dev, "%s missing label for %pUb\n",
dev_name(ndd->dev), nd_label->uuid);
BUG: unable to handle kernel NULL pointer dereference at 0000000000000000
IP: nd_region_register_namespaces+0xd67/0x13c0 [libnvdimm]
PGD 0 P4D 0
Oops: 0000 [#1] SMP PTI
CPU: 43 PID: 673 Comm: kworker/u609:10 Not tainted 4.16.0-rc4+ #1
[..]
RIP: 0010:nd_region_register_namespaces+0xd67/0x13c0 [libnvdimm]
[..]
Call Trace:
? devres_add+0x2f/0x40
? devm_kmalloc+0x52/0x60
? nd_region_activate+0x9c/0x320 [libnvdimm]
nd_region_probe+0x94/0x260 [libnvdimm]
? kernfs_add_one+0xe4/0x130
nvdimm_bus_probe+0x63/0x100 [libnvdimm]
Switch to using the nvdimm device directly.
Fixes: 0e3b0d123c8f ("libnvdimm, namespace: allow multiple pmem...")
Cc: <stable(a)vger.kernel.org>
Reported-by: Dave Jiang <dave.jiang(a)intel.com>
Signed-off-by: Dan Williams <dan.j.williams(a)intel.com>
---
drivers/nvdimm/namespace_devs.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c
index 89b40ff83025..28afdd668905 100644
--- a/drivers/nvdimm/namespace_devs.c
+++ b/drivers/nvdimm/namespace_devs.c
@@ -1921,7 +1921,7 @@ static struct device *create_namespace_pmem(struct nd_region *nd_region,
}
if (i < nd_region->ndr_mappings) {
- struct nvdimm_drvdata *ndd = to_ndd(&nd_region->mapping[i]);
+ struct nvdimm *nvdimm = nd_region->mapping[i].nvdimm;
/*
* Give up if we don't find an instance of a uuid at each
@@ -1929,7 +1929,7 @@ static struct device *create_namespace_pmem(struct nd_region *nd_region,
* find a dimm with two instances of the same uuid.
*/
dev_err(&nd_region->dev, "%s missing label for %pUb\n",
- dev_name(ndd->dev), nd_label->uuid);
+ nvdimm_name(nvdimm), nd_label->uuid);
rc = -EINVAL;
goto err;
}
4 years, 2 months
[PATCH] libnvdimm, dimm: fix dpa reservation vs uninitialized label area
by Dan Williams
At initialization time the 'dimm' driver caches a copy of the memory
device's label area and reserves address space for each of the
namespaces defined.
However, as can be seen below, the reservation occurs even when the
index blocks are invalid:
nvdimm nmem0: nvdimm_init_config_data: len: 131072 rc: 0
nvdimm nmem0: config data size: 131072
nvdimm nmem0: __nd_label_validate: nsindex0 labelsize 1 invalid
nvdimm nmem0: __nd_label_validate: nsindex1 labelsize 1 invalid
nvdimm nmem0: : pmem-6025e505: 0x1000000000 @ 0xf50000000 reserve <-- bad
Gate dpa reservation on the presence of valid index blocks.
Cc: <stable(a)vger.kernel.org>
Fixes: 4a826c83db4e ("libnvdimm: namespace indices: read and validate")
Reported-by: Krzysztof Rusocki <krzysztof.rusocki(a)intel.com>
Signed-off-by: Dan Williams <dan.j.williams(a)intel.com>
---
drivers/nvdimm/dimm.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/nvdimm/dimm.c b/drivers/nvdimm/dimm.c
index f8913b8124b6..233907889f96 100644
--- a/drivers/nvdimm/dimm.c
+++ b/drivers/nvdimm/dimm.c
@@ -67,9 +67,11 @@ static int nvdimm_probe(struct device *dev)
ndd->ns_next = nd_label_next_nsindex(ndd->ns_current);
nd_label_copy(ndd, to_next_namespace_index(ndd),
to_current_namespace_index(ndd));
- rc = nd_label_reserve_dpa(ndd);
- if (ndd->ns_current >= 0)
- nvdimm_set_aliasing(dev);
+ if (ndd->ns_current >= 0) {
+ rc = nd_label_reserve_dpa(ndd);
+ if (rc == 0)
+ nvdimm_set_aliasing(dev);
+ }
nvdimm_clear_locked(dev);
nvdimm_bus_unlock(dev);
4 years, 2 months
[PATCH v3 1/4] libnvdimm: Add of_node to region and bus descriptors
by Oliver O'Halloran
We want to be able to cross reference the region and bus devices
with the device tree node that they were spawned from. libNVDIMM
handles creating the actual devices for these internally, so we
need to pass in a pointer to the relevant node in the descriptor.
Signed-off-by: Oliver O'Halloran <oohall(a)gmail.com>
Acked-by: Dan Williams <dan.j.williams(a)intel.com>
---
drivers/nvdimm/bus.c | 1 +
drivers/nvdimm/region_devs.c | 1 +
include/linux/libnvdimm.h | 3 +++
3 files changed, 5 insertions(+)
diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
index 78eabc3a1ab1..c6106914f396 100644
--- a/drivers/nvdimm/bus.c
+++ b/drivers/nvdimm/bus.c
@@ -358,6 +358,7 @@ struct nvdimm_bus *nvdimm_bus_register(struct device *parent,
nvdimm_bus->dev.release = nvdimm_bus_release;
nvdimm_bus->dev.groups = nd_desc->attr_groups;
nvdimm_bus->dev.bus = &nvdimm_bus_type;
+ nvdimm_bus->dev.of_node = nd_desc->of_node;
dev_set_name(&nvdimm_bus->dev, "ndbus%d", nvdimm_bus->id);
rc = device_register(&nvdimm_bus->dev);
if (rc) {
diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
index 1593e1806b16..30d5dc8b9bb2 100644
--- a/drivers/nvdimm/region_devs.c
+++ b/drivers/nvdimm/region_devs.c
@@ -1014,6 +1014,7 @@ static struct nd_region *nd_region_create(struct nvdimm_bus *nvdimm_bus,
dev->parent = &nvdimm_bus->dev;
dev->type = dev_type;
dev->groups = ndr_desc->attr_groups;
+ dev->of_node = ndr_desc->of_node;
nd_region->ndr_size = resource_size(ndr_desc->res);
nd_region->ndr_start = ndr_desc->res->start;
nd_device_register(dev);
diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
index ff855ed965fb..f61cb5050297 100644
--- a/include/linux/libnvdimm.h
+++ b/include/linux/libnvdimm.h
@@ -76,12 +76,14 @@ typedef int (*ndctl_fn)(struct nvdimm_bus_descriptor *nd_desc,
struct nvdimm *nvdimm, unsigned int cmd, void *buf,
unsigned int buf_len, int *cmd_rc);
+struct device_node;
struct nvdimm_bus_descriptor {
const struct attribute_group **attr_groups;
unsigned long bus_dsm_mask;
unsigned long cmd_mask;
struct module *module;
char *provider_name;
+ struct device_node *of_node;
ndctl_fn ndctl;
int (*flush_probe)(struct nvdimm_bus_descriptor *nd_desc);
int (*clear_to_send)(struct nvdimm_bus_descriptor *nd_desc,
@@ -123,6 +125,7 @@ struct nd_region_desc {
int num_lanes;
int numa_node;
unsigned long flags;
+ struct device_node *of_node;
};
struct device;
--
2.9.5
4 years, 2 months
[ndctl PATCH v2 0/3] nfit, address-range-scrub: rework and fixes
by Dan Williams
Changes since v1:
* Merge the cleanups and fixes with Dave's reviewed-by
* Rework acpi_nfit_query_poison() to be independent of the spa range
* Rework all acpi_nfit_query_poison() usage to call it once and then
iterate the result buffer over all SPA ranges
* Make sure the implementation never attempts to scrub / register
unknown SPA types
* Change no_init_ars to a bool type so it can be specified without an
'=' character.
---
Given the fact that ARS can take 10s to 100s of seconds it is not
feasible to wait for ARS completion before publishing persistent memory
namespaces. Instead convert the ARS implementation to perform a short
ARS for critical errors, ones that caused a previous system reset,
before registering namespaces. Finally, arrange for all long ARS
operations to run in the background and populate the badblock lists at
run time.
---
Dan Williams (3):
nfit, address-range-scrub: determine one platform max_ars value
nfit, address-range-scrub: rework and simplify ARS state machine
nfit, address-range-scrub: add module option to skip initial ars
drivers/acpi/nfit/core.c | 542 ++++++++++++++++++++--------------------------
drivers/acpi/nfit/nfit.h | 6 -
2 files changed, 243 insertions(+), 305 deletions(-)
4 years, 2 months
[ndctl PATCH] ndctl: export ndctl.h
by Dan Williams
The ndctl project maintains a local version of the ndctl.h header file
published by the kernel. Given that the kernel header may be out of date
relative to the header used to build ndctl, provide the local version in
ndctl/ndctl.h alongside ndctl/libndctl.h so that consumers of the
library have access to the same definitions used to build the library.
Reported-by: Juston Li <juston.li(a)intel.com>
Signed-off-by: Dan Williams <dan.j.williams(a)intel.com>
---
ndctl/lib/Makefile.am | 2 +-
ndctl/ndctl.h | 2 ++
test/ack-shutdown-count-set.c | 3 ---
3 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/ndctl/lib/Makefile.am b/ndctl/lib/Makefile.am
index e3a12e7177e9..77970399bf00 100644
--- a/ndctl/lib/Makefile.am
+++ b/ndctl/lib/Makefile.am
@@ -3,7 +3,7 @@ include $(top_srcdir)/Makefile.am.in
%.pc: %.pc.in Makefile
$(SED_PROCESS)
-pkginclude_HEADERS = ../libndctl.h
+pkginclude_HEADERS = ../libndctl.h ../ndctl.h
lib_LTLIBRARIES = libndctl.la
libndctl_la_SOURCES =\
diff --git a/ndctl/ndctl.h b/ndctl/ndctl.h
index ebd2a41cce46..c6aaa4c0981f 100644
--- a/ndctl/ndctl.h
+++ b/ndctl/ndctl.h
@@ -13,7 +13,9 @@
#ifndef __NDCTL_H__
#define __NDCTL_H__
+#ifndef ARRAY_SIZE
#include <ccan/array_size/array_size.h>
+#endif
#include <linux/types.h>
#include <sys/user.h>
#include <unistd.h>
diff --git a/test/ack-shutdown-count-set.c b/test/ack-shutdown-count-set.c
index ef38176442f1..6766c5f3b021 100644
--- a/test/ack-shutdown-count-set.c
+++ b/test/ack-shutdown-count-set.c
@@ -15,9 +15,6 @@
#include <ccan/array_size/array_size.h>
#include <ndctl/libndctl.h>
-#ifdef HAVE_NDCTL_H
-#include <linux/ndctl.h>
-#else
#include <ndctl.h>
#endif
#include <test.h>
4 years, 2 months
[PATCH] ndctl: fix ndctl_persistence_domain declaration
by lukasz.plewa@intel.com
From: Łukasz Plewa <lukasz.plewa(a)intel.com>
the declaration of ndctl_persistence_domain should be above first use
of this enum
Reported-by: Kamil Diedrich <kamil.diedrich(a)intel.com>
Signed-off-by: Łukasz Plewa <lukasz.plewa(a)intel.com>
---
ndctl/libndctl.h | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/ndctl/libndctl.h b/ndctl/libndctl.h
index cf6a77f..684fcd4 100644
--- a/ndctl/libndctl.h
+++ b/ndctl/libndctl.h
@@ -97,6 +97,13 @@ void ndctl_set_log_priority(struct ndctl_ctx *ctx, int priority);
void ndctl_set_userdata(struct ndctl_ctx *ctx, void *userdata);
void *ndctl_get_userdata(struct ndctl_ctx *ctx);
+enum ndctl_persistence_domain {
+ PERSISTENCE_NONE = 0,
+ PERSISTENCE_MEM_CTRL = 10,
+ PERSISTENCE_CPU_CACHE = 20,
+ PERSISTENCE_UNKNOWN = INT_MAX,
+};
+
struct ndctl_bus;
struct ndctl_bus *ndctl_bus_get_first(struct ndctl_ctx *ctx);
struct ndctl_bus *ndctl_bus_get_next(struct ndctl_bus *bus);
@@ -309,13 +316,6 @@ struct badblock {
unsigned int len;
};
-enum ndctl_persistence_domain {
- PERSISTENCE_NONE = 0,
- PERSISTENCE_MEM_CTRL = 10,
- PERSISTENCE_CPU_CACHE = 20,
- PERSISTENCE_UNKNOWN = INT_MAX,
-};
-
struct ndctl_region;
struct ndctl_region *ndctl_region_get_first(struct ndctl_bus *bus);
struct ndctl_region *ndctl_region_get_next(struct ndctl_region *region);
--
2.7.4
4 years, 2 months
[PATCH 0/6] nfit, address-range-scrub: rework and fixes
by Dan Williams
Given the fact that ARS can take 10s to 100s of seconds it is not
feasible to wait for ARS completion before publishing persistent memory
namespaces. Instead convert the ARS implementation to perform a short
ARS for critical errors, ones that caused a previous system reset,
before registering namespaces. Finally, arrange for all long ARS
operations to run in the background and populate the badblock lists at
run time.
While developing this rework a handful of cleanups and fixes also fell
out.
---
Dan Williams (6):
nfit: fix region registration vs block-data-window ranges
nfit, address-range-scrub: fix scrub in-progress reporting
libnvdimm: add an api to cast a 'struct nd_region' to its 'struct device'
nfit, address-range-scrub: introduce nfit_spa->ars_state
nfit, address-range-scrub: rework and simplify ARS state machine
nfit, address-range-scrub: add module option to skip initial ars
drivers/acpi/nfit/core.c | 443 ++++++++++++++++++------------------------
drivers/acpi/nfit/nfit.h | 13 +
drivers/nvdimm/nd.h | 1
drivers/nvdimm/region_devs.c | 8 +
include/linux/libnvdimm.h | 1
5 files changed, 213 insertions(+), 253 deletions(-)
4 years, 2 months
[RESEND v2 1/4] libnvdimm: Add of_node to region and bus descriptors
by Oliver O'Halloran
We want to be able to cross reference the region and bus devices
with the device tree node that they were spawned from. libNVDIMM
handles creating the actual devices for these internally, so we
need to pass in a pointer to the relevant node in the descriptor.
Signed-off-by: Oliver O'Halloran <oohall(a)gmail.com>
Acked-by: Dan Williams <dan.j.williams(a)intel.com>
---
drivers/nvdimm/bus.c | 1 +
drivers/nvdimm/region_devs.c | 1 +
include/linux/libnvdimm.h | 3 +++
3 files changed, 5 insertions(+)
diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
index 78eabc3a1ab1..c6106914f396 100644
--- a/drivers/nvdimm/bus.c
+++ b/drivers/nvdimm/bus.c
@@ -358,6 +358,7 @@ struct nvdimm_bus *nvdimm_bus_register(struct device *parent,
nvdimm_bus->dev.release = nvdimm_bus_release;
nvdimm_bus->dev.groups = nd_desc->attr_groups;
nvdimm_bus->dev.bus = &nvdimm_bus_type;
+ nvdimm_bus->dev.of_node = nd_desc->of_node;
dev_set_name(&nvdimm_bus->dev, "ndbus%d", nvdimm_bus->id);
rc = device_register(&nvdimm_bus->dev);
if (rc) {
diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
index e6d01911e092..2f1d5771100e 100644
--- a/drivers/nvdimm/region_devs.c
+++ b/drivers/nvdimm/region_devs.c
@@ -1005,6 +1005,7 @@ static struct nd_region *nd_region_create(struct nvdimm_bus *nvdimm_bus,
dev->parent = &nvdimm_bus->dev;
dev->type = dev_type;
dev->groups = ndr_desc->attr_groups;
+ dev->of_node = ndr_desc->of_node;
nd_region->ndr_size = resource_size(ndr_desc->res);
nd_region->ndr_start = ndr_desc->res->start;
nd_device_register(dev);
diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
index ff855ed965fb..f61cb5050297 100644
--- a/include/linux/libnvdimm.h
+++ b/include/linux/libnvdimm.h
@@ -76,12 +76,14 @@ typedef int (*ndctl_fn)(struct nvdimm_bus_descriptor *nd_desc,
struct nvdimm *nvdimm, unsigned int cmd, void *buf,
unsigned int buf_len, int *cmd_rc);
+struct device_node;
struct nvdimm_bus_descriptor {
const struct attribute_group **attr_groups;
unsigned long bus_dsm_mask;
unsigned long cmd_mask;
struct module *module;
char *provider_name;
+ struct device_node *of_node;
ndctl_fn ndctl;
int (*flush_probe)(struct nvdimm_bus_descriptor *nd_desc);
int (*clear_to_send)(struct nvdimm_bus_descriptor *nd_desc,
@@ -123,6 +125,7 @@ struct nd_region_desc {
int num_lanes;
int numa_node;
unsigned long flags;
+ struct device_node *of_node;
};
struct device;
--
2.9.5
4 years, 2 months