* [PATCH 1/9] libnvdimm, pfn: kill ND_PFN_ALIGN
2015-12-15 2:14 [PATCH 0/9] libnvdimm, pfn updates for 4.5 Dan Williams
@ 2015-12-15 2:14 ` Dan Williams
2015-12-15 2:14 ` [PATCH 2/9] libnvdimm, pfn: clean up pfn create parameters Dan Williams
` (7 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Dan Williams @ 2015-12-15 2:14 UTC (permalink / raw)
To: linux-nvdimm; +Cc: willy, ross.zwisler, linux-kernel
The alignment constraint isn't necessary now that devm_memremap_pages()
allows for unaligned mappings.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
drivers/nvdimm/nd.h | 7 -------
drivers/nvdimm/pfn_devs.c | 11 +----------
drivers/nvdimm/pmem.c | 15 ---------------
3 files changed, 1 insertion(+), 32 deletions(-)
diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
index 417e521d299c..2ce428e9b584 100644
--- a/drivers/nvdimm/nd.h
+++ b/drivers/nvdimm/nd.h
@@ -29,13 +29,6 @@ enum {
ND_MAX_LANES = 256,
SECTOR_SHIFT = 9,
INT_LBASIZE_ALIGNMENT = 64,
-#if IS_ENABLED(CONFIG_NVDIMM_PFN)
- ND_PFN_ALIGN = PAGES_PER_SECTION * PAGE_SIZE,
- ND_PFN_MASK = ND_PFN_ALIGN - 1,
-#else
- ND_PFN_ALIGN = 0,
- ND_PFN_MASK = 0,
-#endif
};
struct nvdimm_drvdata {
diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c
index 71805a1aa0f3..96c122918ee1 100644
--- a/drivers/nvdimm/pfn_devs.c
+++ b/drivers/nvdimm/pfn_devs.c
@@ -241,10 +241,6 @@ int nd_pfn_validate(struct nd_pfn *nd_pfn)
if (!is_nd_pmem(nd_pfn->dev.parent))
return -ENODEV;
- /* section alignment for simple hotplug */
- if (nvdimm_namespace_capacity(ndns) < ND_PFN_ALIGN)
- return -ENODEV;
-
if (nvdimm_read_bytes(ndns, SZ_4K, pfn_sb, sizeof(*pfn_sb)))
return -ENXIO;
@@ -286,12 +282,7 @@ int nd_pfn_validate(struct nd_pfn *nd_pfn)
*/
offset = le64_to_cpu(pfn_sb->dataoff);
nsio = to_nd_namespace_io(&ndns->dev);
- if (nsio->res.start & ND_PFN_MASK) {
- dev_err(&nd_pfn->dev,
- "init failed: %s not section aligned\n",
- dev_name(&ndns->dev));
- return -EBUSY;
- } else if (offset >= resource_size(&nsio->res)) {
+ if (offset >= resource_size(&nsio->res)) {
dev_err(&nd_pfn->dev, "pfn array size exceeds capacity of %s\n",
dev_name(&ndns->dev));
return -EBUSY;
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c
index 8ee79893d2f5..520c00321dad 100644
--- a/drivers/nvdimm/pmem.c
+++ b/drivers/nvdimm/pmem.c
@@ -241,11 +241,6 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn)
if (rc == 0 || rc == -EBUSY)
return rc;
- /* section alignment for simple hotplug */
- if (nvdimm_namespace_capacity(ndns) < ND_PFN_ALIGN
- || pmem->phys_addr & ND_PFN_MASK)
- return -ENODEV;
-
nd_region = to_nd_region(nd_pfn->dev.parent);
if (nd_region->ro) {
dev_info(&nd_pfn->dev,
@@ -326,16 +321,6 @@ static int nvdimm_namespace_attach_pfn(struct nd_namespace_common *ndns)
if (rc)
return rc;
- if (PAGE_SIZE != SZ_4K) {
- dev_err(dev, "only supported on systems with 4K PAGE_SIZE\n");
- return -ENXIO;
- }
- if (nsio->res.start & ND_PFN_MASK) {
- dev_err(dev, "%s not memory hotplug section aligned\n",
- dev_name(&ndns->dev));
- return -ENXIO;
- }
-
pfn_sb = nd_pfn->pfn_sb;
offset = le64_to_cpu(pfn_sb->dataoff);
nd_pfn->mode = le32_to_cpu(nd_pfn->pfn_sb->mode);
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH 2/9] libnvdimm, pfn: clean up pfn create parameters
2015-12-15 2:14 [PATCH 0/9] libnvdimm, pfn updates for 4.5 Dan Williams
2015-12-15 2:14 ` [PATCH 1/9] libnvdimm, pfn: kill ND_PFN_ALIGN Dan Williams
@ 2015-12-15 2:14 ` Dan Williams
2015-12-15 2:14 ` [PATCH 3/9] libnvdimm, pfn: add 'align' attribute, default to HPAGE_SIZE Dan Williams
` (6 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Dan Williams @ 2015-12-15 2:14 UTC (permalink / raw)
To: linux-nvdimm; +Cc: willy, ross.zwisler, linux-kernel
In all cases __nd_pfn_create is called with default parameters which are
then overridden by values in the info block. Clean up pfn creation by
dropping the parameters and setting default values internal to
__nd_pfn_create.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
drivers/nvdimm/pfn_devs.c | 11 +++--------
1 file changed, 3 insertions(+), 8 deletions(-)
diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c
index 96c122918ee1..613ffcca6ecb 100644
--- a/drivers/nvdimm/pfn_devs.c
+++ b/drivers/nvdimm/pfn_devs.c
@@ -179,7 +179,6 @@ static const struct attribute_group *nd_pfn_attribute_groups[] = {
};
static struct device *__nd_pfn_create(struct nd_region *nd_region,
- u8 *uuid, enum nd_pfn_mode mode,
struct nd_namespace_common *ndns)
{
struct nd_pfn *nd_pfn;
@@ -199,10 +198,7 @@ static struct device *__nd_pfn_create(struct nd_region *nd_region,
return NULL;
}
- nd_pfn->mode = mode;
- if (uuid)
- uuid = kmemdup(uuid, 16, GFP_KERNEL);
- nd_pfn->uuid = uuid;
+ nd_pfn->mode = PFN_MODE_NONE;
dev = &nd_pfn->dev;
dev_set_name(dev, "pfn%d.%d", nd_region->id, nd_pfn->id);
dev->parent = &nd_region->dev;
@@ -220,8 +216,7 @@ static struct device *__nd_pfn_create(struct nd_region *nd_region,
struct device *nd_pfn_create(struct nd_region *nd_region)
{
- struct device *dev = __nd_pfn_create(nd_region, NULL, PFN_MODE_NONE,
- NULL);
+ struct device *dev = __nd_pfn_create(nd_region, NULL);
if (dev)
__nd_device_register(dev);
@@ -304,7 +299,7 @@ int nd_pfn_probe(struct nd_namespace_common *ndns, void *drvdata)
return -ENODEV;
nvdimm_bus_lock(&ndns->dev);
- dev = __nd_pfn_create(nd_region, NULL, PFN_MODE_NONE, ndns);
+ dev = __nd_pfn_create(nd_region, ndns);
nvdimm_bus_unlock(&ndns->dev);
if (!dev)
return -ENOMEM;
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH 3/9] libnvdimm, pfn: add 'align' attribute, default to HPAGE_SIZE
2015-12-15 2:14 [PATCH 0/9] libnvdimm, pfn updates for 4.5 Dan Williams
2015-12-15 2:14 ` [PATCH 1/9] libnvdimm, pfn: kill ND_PFN_ALIGN Dan Williams
2015-12-15 2:14 ` [PATCH 2/9] libnvdimm, pfn: clean up pfn create parameters Dan Williams
@ 2015-12-15 2:14 ` Dan Williams
2015-12-15 2:14 ` [PATCH 4/9] libnvdimm, pfn: add parent uuid validation Dan Williams
` (5 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Dan Williams @ 2015-12-15 2:14 UTC (permalink / raw)
To: linux-nvdimm; +Cc: willy, ross.zwisler, linux-kernel
When setting aside capacity for struct page it must be aligned to the
largest mapping size that is to be made available via DAX. Make the
alignment configurable to enable support for 1GiB page-size mappings.
The offset for PFN_MODE_RAM may now be larger than SZ_8K, so fixup the
offset check in nvdimm_namespace_attach_pfn().
Reported-by: Toshi Kani <toshi.kani@hpe.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
drivers/nvdimm/nd.h | 1 +
drivers/nvdimm/pfn_devs.c | 61 +++++++++++++++++++++++++++++++++++++++++++++
drivers/nvdimm/pmem.c | 6 ++--
3 files changed, 65 insertions(+), 3 deletions(-)
diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
index 2ce428e9b584..e4e9f9ae0cc8 100644
--- a/drivers/nvdimm/nd.h
+++ b/drivers/nvdimm/nd.h
@@ -146,6 +146,7 @@ struct nd_pfn {
int id;
u8 *uuid;
struct device dev;
+ unsigned long align;
unsigned long npfns;
enum nd_pfn_mode mode;
struct nd_pfn_sb *pfn_sb;
diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c
index 613ffcca6ecb..95ecd7b0fab3 100644
--- a/drivers/nvdimm/pfn_devs.c
+++ b/drivers/nvdimm/pfn_devs.c
@@ -103,6 +103,52 @@ static ssize_t mode_store(struct device *dev,
}
static DEVICE_ATTR_RW(mode);
+static ssize_t align_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct nd_pfn *nd_pfn = to_nd_pfn(dev);
+
+ return sprintf(buf, "%lx\n", nd_pfn->align);
+}
+
+static ssize_t __align_store(struct nd_pfn *nd_pfn, const char *buf)
+{
+ unsigned long val;
+ int rc;
+
+ rc = kstrtoul(buf, 0, &val);
+ if (rc)
+ return rc;
+
+ if (!is_power_of_2(val) || val < PAGE_SIZE || val > SZ_1G)
+ return -EINVAL;
+
+ if (nd_pfn->dev.driver)
+ return -EBUSY;
+ else
+ nd_pfn->align = val;
+
+ return 0;
+}
+
+static ssize_t align_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t len)
+{
+ struct nd_pfn *nd_pfn = to_nd_pfn(dev);
+ ssize_t rc;
+
+ device_lock(dev);
+ nvdimm_bus_lock(dev);
+ rc = __align_store(nd_pfn, buf);
+ dev_dbg(dev, "%s: result: %zd wrote: %s%s", __func__,
+ rc, buf, buf[len - 1] == '\n' ? "" : "\n");
+ nvdimm_bus_unlock(dev);
+ device_unlock(dev);
+
+ return rc ? rc : len;
+}
+static DEVICE_ATTR_RW(align);
+
static ssize_t uuid_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -164,6 +210,7 @@ static struct attribute *nd_pfn_attributes[] = {
&dev_attr_mode.attr,
&dev_attr_namespace.attr,
&dev_attr_uuid.attr,
+ &dev_attr_align.attr,
NULL,
};
@@ -199,6 +246,7 @@ static struct device *__nd_pfn_create(struct nd_region *nd_region,
}
nd_pfn->mode = PFN_MODE_NONE;
+ nd_pfn->align = HPAGE_SIZE;
dev = &nd_pfn->dev;
dev_set_name(dev, "pfn%d.%d", nd_region->id, nd_pfn->id);
dev->parent = &nd_region->dev;
@@ -269,6 +317,12 @@ int nd_pfn_validate(struct nd_pfn *nd_pfn)
return -EINVAL;
}
+ if (nd_pfn->align > nvdimm_namespace_capacity(ndns)) {
+ dev_err(&nd_pfn->dev, "alignment: %lx exceeds capacity %llx\n",
+ nd_pfn->align, nvdimm_namespace_capacity(ndns));
+ return -EINVAL;
+ }
+
/*
* These warnings are verbose because they can only trigger in
* the case where the physical address alignment of the
@@ -283,6 +337,13 @@ int nd_pfn_validate(struct nd_pfn *nd_pfn)
return -EBUSY;
}
+ nd_pfn->align = 1UL << ilog2(offset);
+ if (!is_power_of_2(offset) || offset < PAGE_SIZE) {
+ dev_err(&nd_pfn->dev, "bad offset: %#llx dax disabled\n",
+ offset);
+ return -ENXIO;
+ }
+
return 0;
}
EXPORT_SYMBOL(nd_pfn_validate);
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c
index 520c00321dad..5ba351e4f26a 100644
--- a/drivers/nvdimm/pmem.c
+++ b/drivers/nvdimm/pmem.c
@@ -258,9 +258,9 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn)
* ->direct_access() to those that are included in the memmap.
*/
if (nd_pfn->mode == PFN_MODE_PMEM)
- offset = ALIGN(SZ_8K + 64 * npfns, PMD_SIZE);
+ offset = ALIGN(SZ_8K + 64 * npfns, nd_pfn->align);
else if (nd_pfn->mode == PFN_MODE_RAM)
- offset = SZ_8K;
+ offset = ALIGN(SZ_8K, nd_pfn->align);
else
goto err;
@@ -325,7 +325,7 @@ static int nvdimm_namespace_attach_pfn(struct nd_namespace_common *ndns)
offset = le64_to_cpu(pfn_sb->dataoff);
nd_pfn->mode = le32_to_cpu(nd_pfn->pfn_sb->mode);
if (nd_pfn->mode == PFN_MODE_RAM) {
- if (offset != SZ_8K)
+ if (offset < SZ_8K)
return -EINVAL;
nd_pfn->npfns = le64_to_cpu(pfn_sb->npfns);
altmap = NULL;
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH 4/9] libnvdimm, pfn: add parent uuid validation
2015-12-15 2:14 [PATCH 0/9] libnvdimm, pfn updates for 4.5 Dan Williams
` (2 preceding siblings ...)
2015-12-15 2:14 ` [PATCH 3/9] libnvdimm, pfn: add 'align' attribute, default to HPAGE_SIZE Dan Williams
@ 2015-12-15 2:14 ` Dan Williams
2015-12-15 2:14 ` [PATCH 5/9] libnvdimm, pfn: fix pfn seed creation Dan Williams
` (4 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Dan Williams @ 2015-12-15 2:14 UTC (permalink / raw)
To: linux-nvdimm; +Cc: willy, ross.zwisler, linux-kernel
Track and check the uuid of the namespace hosting a pfn instance. This
forces the pfn info block to be invalidated if the namespace is
re-configured with a different uuid.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
drivers/nvdimm/pfn_devs.c | 10 +++++++---
drivers/nvdimm/pmem.c | 1 +
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c
index 95ecd7b0fab3..f9b674bc49db 100644
--- a/drivers/nvdimm/pfn_devs.c
+++ b/drivers/nvdimm/pfn_devs.c
@@ -273,10 +273,11 @@ struct device *nd_pfn_create(struct nd_region *nd_region)
int nd_pfn_validate(struct nd_pfn *nd_pfn)
{
- struct nd_namespace_common *ndns = nd_pfn->ndns;
- struct nd_pfn_sb *pfn_sb = nd_pfn->pfn_sb;
- struct nd_namespace_io *nsio;
u64 checksum, offset;
+ struct nd_namespace_io *nsio;
+ struct nd_pfn_sb *pfn_sb = nd_pfn->pfn_sb;
+ struct nd_namespace_common *ndns = nd_pfn->ndns;
+ const u8 *parent_uuid = nd_dev_to_uuid(&ndns->dev);
if (!pfn_sb || !ndns)
return -ENODEV;
@@ -296,6 +297,9 @@ int nd_pfn_validate(struct nd_pfn *nd_pfn)
return -ENODEV;
pfn_sb->checksum = cpu_to_le64(checksum);
+ if (memcmp(pfn_sb->parent_uuid, parent_uuid, 16) != 0)
+ return -ENODEV;
+
switch (le32_to_cpu(pfn_sb->mode)) {
case PFN_MODE_RAM:
break;
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c
index 5ba351e4f26a..dc6866734f70 100644
--- a/drivers/nvdimm/pmem.c
+++ b/drivers/nvdimm/pmem.c
@@ -270,6 +270,7 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn)
pfn_sb->npfns = cpu_to_le64(npfns);
memcpy(pfn_sb->signature, PFN_SIG, PFN_SIG_LEN);
memcpy(pfn_sb->uuid, nd_pfn->uuid, 16);
+ memcpy(pfn_sb->parent_uuid, nd_dev_to_uuid(&ndns->dev), 16);
pfn_sb->version_major = cpu_to_le16(1);
checksum = nd_sb_checksum((struct nd_gen_sb *) pfn_sb);
pfn_sb->checksum = cpu_to_le64(checksum);
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH 5/9] libnvdimm, pfn: fix pfn seed creation
2015-12-15 2:14 [PATCH 0/9] libnvdimm, pfn updates for 4.5 Dan Williams
` (3 preceding siblings ...)
2015-12-15 2:14 ` [PATCH 4/9] libnvdimm, pfn: add parent uuid validation Dan Williams
@ 2015-12-15 2:14 ` Dan Williams
2015-12-15 2:15 ` [PATCH 6/9] libnvdimm, pfn: enable pfn sysfs interface unit testing Dan Williams
` (3 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Dan Williams @ 2015-12-15 2:14 UTC (permalink / raw)
To: linux-nvdimm; +Cc: willy, ross.zwisler, linux-kernel
Similar to btt, plant a new pfn seed when the existing one is activated.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
drivers/nvdimm/namespace_devs.c | 12 ++++++++++++
drivers/nvdimm/nd-core.h | 1 +
drivers/nvdimm/region_devs.c | 7 +++++++
3 files changed, 20 insertions(+)
diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c
index f981177524a1..ea8dd0cb28ca 100644
--- a/drivers/nvdimm/namespace_devs.c
+++ b/drivers/nvdimm/namespace_devs.c
@@ -1707,6 +1707,18 @@ void nd_region_create_blk_seed(struct nd_region *nd_region)
nd_device_register(nd_region->ns_seed);
}
+void nd_region_create_pfn_seed(struct nd_region *nd_region)
+{
+ WARN_ON(!is_nvdimm_bus_locked(&nd_region->dev));
+ nd_region->pfn_seed = nd_pfn_create(nd_region);
+ /*
+ * Seed creation failures are not fatal, provisioning is simply
+ * disabled until memory becomes available
+ */
+ if (!nd_region->pfn_seed)
+ dev_err(&nd_region->dev, "failed to create pfn namespace\n");
+}
+
void nd_region_create_btt_seed(struct nd_region *nd_region)
{
WARN_ON(!is_nvdimm_bus_locked(&nd_region->dev));
diff --git a/drivers/nvdimm/nd-core.h b/drivers/nvdimm/nd-core.h
index 159aed532042..3249c498892a 100644
--- a/drivers/nvdimm/nd-core.h
+++ b/drivers/nvdimm/nd-core.h
@@ -52,6 +52,7 @@ void nd_region_probe_success(struct nvdimm_bus *nvdimm_bus, struct device *dev);
struct nd_region;
void nd_region_create_blk_seed(struct nd_region *nd_region);
void nd_region_create_btt_seed(struct nd_region *nd_region);
+void nd_region_create_pfn_seed(struct nd_region *nd_region);
void nd_region_disable(struct nvdimm_bus *nvdimm_bus, struct device *dev);
int nvdimm_bus_create_ndctl(struct nvdimm_bus *nvdimm_bus);
void nvdimm_bus_destroy_ndctl(struct nvdimm_bus *nvdimm_bus);
diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
index 3d730d1f25db..9c632f73915e 100644
--- a/drivers/nvdimm/region_devs.c
+++ b/drivers/nvdimm/region_devs.c
@@ -490,6 +490,13 @@ static void nd_region_notify_driver_action(struct nvdimm_bus *nvdimm_bus,
nd_region_create_blk_seed(nd_region);
nvdimm_bus_unlock(dev);
}
+ if (is_nd_pfn(dev) && probe) {
+ nd_region = to_nd_region(dev->parent);
+ nvdimm_bus_lock(dev);
+ if (nd_region->pfn_seed == dev)
+ nd_region_create_pfn_seed(nd_region);
+ nvdimm_bus_unlock(dev);
+ }
}
void nd_region_probe_success(struct nvdimm_bus *nvdimm_bus, struct device *dev)
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH 6/9] libnvdimm, pfn: enable pfn sysfs interface unit testing
2015-12-15 2:14 [PATCH 0/9] libnvdimm, pfn updates for 4.5 Dan Williams
` (4 preceding siblings ...)
2015-12-15 2:14 ` [PATCH 5/9] libnvdimm, pfn: fix pfn seed creation Dan Williams
@ 2015-12-15 2:15 ` Dan Williams
2015-12-15 2:15 ` [PATCH 7/9] libnvdimm, pfn: fix nd_pfn_validate() return value handling Dan Williams
` (2 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Dan Williams @ 2015-12-15 2:15 UTC (permalink / raw)
To: linux-nvdimm; +Cc: willy, ross.zwisler, linux-kernel
The unit test infrastructure uses CMA and real memory to emulate nvdimm
resources. The call to devm_memremap_pages() can simply be mocked in
the same manner as memremap and we mock phys_to_pfn_t() to clear PFN_MAP
since these resources are not registered with in the pgmap_radix.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
tools/testing/nvdimm/Kbuild | 2 ++
tools/testing/nvdimm/test/iomap.c | 30 ++++++++++++++++++++++++++++++
2 files changed, 32 insertions(+)
diff --git a/tools/testing/nvdimm/Kbuild b/tools/testing/nvdimm/Kbuild
index 38b00ecb2ed5..a34bfd0c8928 100644
--- a/tools/testing/nvdimm/Kbuild
+++ b/tools/testing/nvdimm/Kbuild
@@ -9,6 +9,8 @@ ldflags-y += --wrap=memunmap
ldflags-y += --wrap=__devm_request_region
ldflags-y += --wrap=__request_region
ldflags-y += --wrap=__release_region
+ldflags-y += --wrap=devm_memremap_pages
+ldflags-y += --wrap=phys_to_pfn_t
DRIVERS := ../../../drivers
NVDIMM_SRC := $(DRIVERS)/nvdimm
diff --git a/tools/testing/nvdimm/test/iomap.c b/tools/testing/nvdimm/test/iomap.c
index b7251314bbc0..802d3a173ccf 100644
--- a/tools/testing/nvdimm/test/iomap.c
+++ b/tools/testing/nvdimm/test/iomap.c
@@ -94,6 +94,36 @@ void *__wrap_devm_memremap(struct device *dev, resource_size_t offset,
}
EXPORT_SYMBOL(__wrap_devm_memremap);
+void *__wrap_devm_memremap_pages(struct device *dev, struct resource *res)
+{
+ struct nfit_test_resource *nfit_res;
+ resource_size_t offset = res->start;
+
+ rcu_read_lock();
+ nfit_res = get_nfit_res(offset);
+ rcu_read_unlock();
+ if (nfit_res)
+ return nfit_res->buf + offset - nfit_res->res->start;
+ return devm_memremap_pages(dev, res);
+}
+EXPORT_SYMBOL(__wrap_devm_memremap_pages);
+
+#ifdef PFN_MAP
+pfn_t __wrap_phys_to_pfn_t(dma_addr_t addr, unsigned long flags)
+{
+ struct nfit_test_resource *nfit_res;
+
+ rcu_read_lock();
+ nfit_res = get_nfit_res(offset);
+ rcu_read_unlock();
+
+ if (nfit_res)
+ flags &= ~PFN_MAP;
+ return phys_to_pfn_t(addr >> PAGE_SHIFT, flags);
+}
+EXPORT_SYMBOL(__wrap_phys_to_pfn_t);
+#endif
+
void *__wrap_memremap(resource_size_t offset, size_t size,
unsigned long flags)
{
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH 7/9] libnvdimm, pfn: fix nd_pfn_validate() return value handling
2015-12-15 2:14 [PATCH 0/9] libnvdimm, pfn updates for 4.5 Dan Williams
` (5 preceding siblings ...)
2015-12-15 2:15 ` [PATCH 6/9] libnvdimm, pfn: enable pfn sysfs interface unit testing Dan Williams
@ 2015-12-15 2:15 ` Dan Williams
2015-12-15 2:15 ` [PATCH 8/9] tools/testing/libnvdimm: cleanup mock resource lookup Dan Williams
2015-12-15 2:15 ` [PATCH 9/9] libnvdimm, pfn: move 'memory mode' indication to sysfs Dan Williams
8 siblings, 0 replies; 11+ messages in thread
From: Dan Williams @ 2015-12-15 2:15 UTC (permalink / raw)
To: linux-nvdimm; +Cc: willy, ross.zwisler, linux-kernel
The -ENODEV case indicates that the info-block needs to established.
All other return codes cause nd_pfn_init() to abort.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
drivers/nvdimm/pmem.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c
index dc6866734f70..ab689bca727d 100644
--- a/drivers/nvdimm/pmem.c
+++ b/drivers/nvdimm/pmem.c
@@ -238,7 +238,9 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn)
nd_pfn->pfn_sb = pfn_sb;
rc = nd_pfn_validate(nd_pfn);
- if (rc == 0 || rc == -EBUSY)
+ if (rc == -ENODEV)
+ /* no info block, do init */;
+ else
return rc;
nd_region = to_nd_region(nd_pfn->dev.parent);
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH 8/9] tools/testing/libnvdimm: cleanup mock resource lookup
2015-12-15 2:14 [PATCH 0/9] libnvdimm, pfn updates for 4.5 Dan Williams
` (6 preceding siblings ...)
2015-12-15 2:15 ` [PATCH 7/9] libnvdimm, pfn: fix nd_pfn_validate() return value handling Dan Williams
@ 2015-12-15 2:15 ` Dan Williams
2015-12-15 7:11 ` Dan Williams
2015-12-15 2:15 ` [PATCH 9/9] libnvdimm, pfn: move 'memory mode' indication to sysfs Dan Williams
8 siblings, 1 reply; 11+ messages in thread
From: Dan Williams @ 2015-12-15 2:15 UTC (permalink / raw)
To: linux-nvdimm; +Cc: willy, ross.zwisler, linux-kernel
Push the locking around get_nfit_res() into get_nfit_res().
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
tools/testing/nvdimm/test/iomap.c | 86 +++++++++++++++++--------------------
1 file changed, 39 insertions(+), 47 deletions(-)
diff --git a/tools/testing/nvdimm/test/iomap.c b/tools/testing/nvdimm/test/iomap.c
index 802d3a173ccf..d9c6c5af67e8 100644
--- a/tools/testing/nvdimm/test/iomap.c
+++ b/tools/testing/nvdimm/test/iomap.c
@@ -16,6 +16,7 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/io.h>
+#include <linux/mm.h>
#include "nfit_test.h"
static LIST_HEAD(iomap_head);
@@ -41,7 +42,7 @@ void nfit_test_teardown(void)
}
EXPORT_SYMBOL(nfit_test_teardown);
-static struct nfit_test_resource *get_nfit_res(resource_size_t resource)
+static struct nfit_test_resource *__get_nfit_res(resource_size_t resource)
{
struct iomap_ops *ops;
@@ -51,14 +52,22 @@ static struct nfit_test_resource *get_nfit_res(resource_size_t resource)
return NULL;
}
-void __iomem *__nfit_test_ioremap(resource_size_t offset, unsigned long size,
- void __iomem *(*fallback_fn)(resource_size_t, unsigned long))
+static struct nfit_test_resource *get_nfit_res(resource_size_t resource)
{
- struct nfit_test_resource *nfit_res;
+ struct nfit_test_resource *res;
rcu_read_lock();
- nfit_res = get_nfit_res(offset);
+ res = __get_nfit_res(resource);
rcu_read_unlock();
+
+ return res;
+}
+
+void __iomem *__nfit_test_ioremap(resource_size_t offset, unsigned long size,
+ void __iomem *(*fallback_fn)(resource_size_t, unsigned long))
+{
+ struct nfit_test_resource *nfit_res = get_nfit_res(offset);
+
if (nfit_res)
return (void __iomem *) nfit_res->buf + offset
- nfit_res->res->start;
@@ -68,11 +77,8 @@ void __iomem *__nfit_test_ioremap(resource_size_t offset, unsigned long size,
void __iomem *__wrap_devm_ioremap_nocache(struct device *dev,
resource_size_t offset, unsigned long size)
{
- struct nfit_test_resource *nfit_res;
+ struct nfit_test_resource *nfit_res = get_nfit_res(offset);
- rcu_read_lock();
- nfit_res = get_nfit_res(offset);
- rcu_read_unlock();
if (nfit_res)
return (void __iomem *) nfit_res->buf + offset
- nfit_res->res->start;
@@ -83,55 +89,55 @@ EXPORT_SYMBOL(__wrap_devm_ioremap_nocache);
void *__wrap_devm_memremap(struct device *dev, resource_size_t offset,
size_t size, unsigned long flags)
{
- struct nfit_test_resource *nfit_res;
+ struct nfit_test_resource *nfit_res = get_nfit_res(offset);
- rcu_read_lock();
- nfit_res = get_nfit_res(offset);
- rcu_read_unlock();
if (nfit_res)
return nfit_res->buf + offset - nfit_res->res->start;
return devm_memremap(dev, offset, size, flags);
}
EXPORT_SYMBOL(__wrap_devm_memremap);
-void *__wrap_devm_memremap_pages(struct device *dev, struct resource *res)
+#ifdef PFN_MAP
+void *__wrap_devm_memremap_pages(struct device *dev, struct resource *res,
+ struct percpu_ref *ref, struct vmem_altmap *altmap)
{
- struct nfit_test_resource *nfit_res;
resource_size_t offset = res->start;
+ struct nfit_test_resource *nfit_res = get_nfit_res(offset);
- rcu_read_lock();
- nfit_res = get_nfit_res(offset);
- rcu_read_unlock();
if (nfit_res)
return nfit_res->buf + offset - nfit_res->res->start;
- return devm_memremap_pages(dev, res);
+ return devm_memremap_pages(dev, res, ref, altmap);
}
EXPORT_SYMBOL(__wrap_devm_memremap_pages);
-#ifdef PFN_MAP
pfn_t __wrap_phys_to_pfn_t(dma_addr_t addr, unsigned long flags)
{
- struct nfit_test_resource *nfit_res;
-
- rcu_read_lock();
- nfit_res = get_nfit_res(offset);
- rcu_read_unlock();
+ struct nfit_test_resource *nfit_res = get_nfit_res(addr);
if (nfit_res)
flags &= ~PFN_MAP;
- return phys_to_pfn_t(addr >> PAGE_SHIFT, flags);
+ return phys_to_pfn_t(addr, flags);
}
EXPORT_SYMBOL(__wrap_phys_to_pfn_t);
+#else
+/* to be removed post 4.5-rc1 */
+void *__wrap_devm_memremap_pages(struct device *dev, struct resource *res)
+{
+ resource_size_t offset = res->start;
+ struct nfit_test_resource *nfit_res = get_nfit_res(offset);
+
+ if (nfit_res)
+ return nfit_res->buf + offset - nfit_res->res->start;
+ return devm_memremap_pages(dev, res);
+}
+EXPORT_SYMBOL(__wrap_devm_memremap_pages);
#endif
void *__wrap_memremap(resource_size_t offset, size_t size,
unsigned long flags)
{
- struct nfit_test_resource *nfit_res;
+ struct nfit_test_resource *nfit_res = get_nfit_res(offset);
- rcu_read_lock();
- nfit_res = get_nfit_res(offset);
- rcu_read_unlock();
if (nfit_res)
return nfit_res->buf + offset - nfit_res->res->start;
return memremap(offset, size, flags);
@@ -140,11 +146,8 @@ EXPORT_SYMBOL(__wrap_memremap);
void __wrap_devm_memunmap(struct device *dev, void *addr)
{
- struct nfit_test_resource *nfit_res;
+ struct nfit_test_resource *nfit_res = get_nfit_res((long) addr);
- rcu_read_lock();
- nfit_res = get_nfit_res((unsigned long) addr);
- rcu_read_unlock();
if (nfit_res)
return;
return devm_memunmap(dev, addr);
@@ -165,11 +168,7 @@ EXPORT_SYMBOL(__wrap_ioremap_wc);
void __wrap_iounmap(volatile void __iomem *addr)
{
- struct nfit_test_resource *nfit_res;
-
- rcu_read_lock();
- nfit_res = get_nfit_res((unsigned long) addr);
- rcu_read_unlock();
+ struct nfit_test_resource *nfit_res = get_nfit_res((long) addr);
if (nfit_res)
return;
return iounmap(addr);
@@ -178,11 +177,8 @@ EXPORT_SYMBOL(__wrap_iounmap);
void __wrap_memunmap(void *addr)
{
- struct nfit_test_resource *nfit_res;
+ struct nfit_test_resource *nfit_res = get_nfit_res((long) addr);
- rcu_read_lock();
- nfit_res = get_nfit_res((unsigned long) addr);
- rcu_read_unlock();
if (nfit_res)
return;
return memunmap(addr);
@@ -196,9 +192,7 @@ static struct resource *nfit_test_request_region(struct device *dev,
struct nfit_test_resource *nfit_res;
if (parent == &iomem_resource) {
- rcu_read_lock();
nfit_res = get_nfit_res(start);
- rcu_read_unlock();
if (nfit_res) {
struct resource *res = nfit_res->res + 1;
@@ -248,9 +242,7 @@ void __wrap___release_region(struct resource *parent, resource_size_t start,
struct nfit_test_resource *nfit_res;
if (parent == &iomem_resource) {
- rcu_read_lock();
nfit_res = get_nfit_res(start);
- rcu_read_unlock();
if (nfit_res) {
struct resource *res = nfit_res->res + 1;
^ permalink raw reply [flat|nested] 11+ messages in thread* Re: [PATCH 8/9] tools/testing/libnvdimm: cleanup mock resource lookup
2015-12-15 2:15 ` [PATCH 8/9] tools/testing/libnvdimm: cleanup mock resource lookup Dan Williams
@ 2015-12-15 7:11 ` Dan Williams
0 siblings, 0 replies; 11+ messages in thread
From: Dan Williams @ 2015-12-15 7:11 UTC (permalink / raw)
To: linux-nvdimm@lists.01.org; +Cc: Ross Zwisler, linux-kernel
On Mon, Dec 14, 2015 at 6:15 PM, Dan Williams <dan.j.williams@intel.com> wrote:
> Push the locking around get_nfit_res() into get_nfit_res().
>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> ---
> tools/testing/nvdimm/test/iomap.c | 86 +++++++++++++++++--------------------
> 1 file changed, 39 insertions(+), 47 deletions(-)
>
> diff --git a/tools/testing/nvdimm/test/iomap.c b/tools/testing/nvdimm/test/iomap.c
> index 802d3a173ccf..d9c6c5af67e8 100644
> --- a/tools/testing/nvdimm/test/iomap.c
> +++ b/tools/testing/nvdimm/test/iomap.c
[..]
> @@ -83,55 +89,55 @@ EXPORT_SYMBOL(__wrap_devm_ioremap_nocache);
> void *__wrap_devm_memremap(struct device *dev, resource_size_t offset,
> size_t size, unsigned long flags)
> {
> - struct nfit_test_resource *nfit_res;
> + struct nfit_test_resource *nfit_res = get_nfit_res(offset);
>
> - rcu_read_lock();
> - nfit_res = get_nfit_res(offset);
> - rcu_read_unlock();
> if (nfit_res)
> return nfit_res->buf + offset - nfit_res->res->start;
> return devm_memremap(dev, offset, size, flags);
> }
> EXPORT_SYMBOL(__wrap_devm_memremap);
>
> -void *__wrap_devm_memremap_pages(struct device *dev, struct resource *res)
> +#ifdef PFN_MAP
> +void *__wrap_devm_memremap_pages(struct device *dev, struct resource *res,
> + struct percpu_ref *ref, struct vmem_altmap *altmap)
> {
> - struct nfit_test_resource *nfit_res;
> resource_size_t offset = res->start;
> + struct nfit_test_resource *nfit_res = get_nfit_res(offset);
>
> - rcu_read_lock();
> - nfit_res = get_nfit_res(offset);
> - rcu_read_unlock();
> if (nfit_res)
> return nfit_res->buf + offset - nfit_res->res->start;
> - return devm_memremap_pages(dev, res);
> + return devm_memremap_pages(dev, res, ref, altmap);
> }
> EXPORT_SYMBOL(__wrap_devm_memremap_pages);
>
> -#ifdef PFN_MAP
> pfn_t __wrap_phys_to_pfn_t(dma_addr_t addr, unsigned long flags)
> {
> - struct nfit_test_resource *nfit_res;
> -
> - rcu_read_lock();
> - nfit_res = get_nfit_res(offset);
> - rcu_read_unlock();
> + struct nfit_test_resource *nfit_res = get_nfit_res(addr);
>
> if (nfit_res)
> flags &= ~PFN_MAP;
> - return phys_to_pfn_t(addr >> PAGE_SHIFT, flags);
> + return phys_to_pfn_t(addr, flags);
> }
> EXPORT_SYMBOL(__wrap_phys_to_pfn_t);
> +#else
> +/* to be removed post 4.5-rc1 */
> +void *__wrap_devm_memremap_pages(struct device *dev, struct resource *res)
> +{
> + resource_size_t offset = res->start;
> + struct nfit_test_resource *nfit_res = get_nfit_res(offset);
> +
> + if (nfit_res)
> + return nfit_res->buf + offset - nfit_res->res->start;
> + return devm_memremap_pages(dev, res);
> +}
> +EXPORT_SYMBOL(__wrap_devm_memremap_pages);
> #endif
Whoops, the above hunk was meant to be folded into [PATCH 6/9]
libnvdimm, pfn: enable pfn sysfs interface unit testing
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 9/9] libnvdimm, pfn: move 'memory mode' indication to sysfs
2015-12-15 2:14 [PATCH 0/9] libnvdimm, pfn updates for 4.5 Dan Williams
` (7 preceding siblings ...)
2015-12-15 2:15 ` [PATCH 8/9] tools/testing/libnvdimm: cleanup mock resource lookup Dan Williams
@ 2015-12-15 2:15 ` Dan Williams
8 siblings, 0 replies; 11+ messages in thread
From: Dan Williams @ 2015-12-15 2:15 UTC (permalink / raw)
To: linux-nvdimm; +Cc: willy, ross.zwisler, linux-kernel
'Memory mode' is defined as the capability of a DAX mapping to be the
source/target of DMA and other "direct I/O" scenarios. While it
currently requires allocating 'struct page' for each page frame of
persistent memory in the namespace it will not always be the case. Work
continues on reducing the kernel's dependency on 'struct page'.
Let's not maintain a suffix that is expected to lose meaning over time.
In other words a future 'raw mode' pmem namespace may be as capable as
today's 'memory mode' namespace. Undo the encoding of the mode in the
device name and leave it to other tooling to determine the mode of the
namespace from its attributes.
Reported-by: Matthew Wilcox <willy@linux.intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
drivers/nvdimm/namespace_devs.c | 41 +++++++++++++++++++++++++++------------
1 file changed, 28 insertions(+), 13 deletions(-)
diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c
index ea8dd0cb28ca..ee6dee41155a 100644
--- a/drivers/nvdimm/namespace_devs.c
+++ b/drivers/nvdimm/namespace_devs.c
@@ -104,20 +104,10 @@ const char *nvdimm_namespace_disk_name(struct nd_namespace_common *ndns,
struct nd_region *nd_region = to_nd_region(ndns->dev.parent);
const char *suffix = NULL;
- if (ndns->claim) {
- if (is_nd_btt(ndns->claim))
- suffix = "s";
- else if (is_nd_pfn(ndns->claim))
- suffix = "m";
- else
- dev_WARN_ONCE(&ndns->dev, 1,
- "unknown claim type by %s\n",
- dev_name(ndns->claim));
- }
+ if (ndns->claim && is_nd_btt(ndns->claim))
+ suffix = "s";
if (is_namespace_pmem(&ndns->dev) || is_namespace_io(&ndns->dev)) {
- if (!suffix && pmem_should_map_pages(&ndns->dev))
- suffix = "m";
sprintf(name, "pmem%d%s", nd_region->id, suffix ? suffix : "");
} else if (is_namespace_blk(&ndns->dev)) {
struct nd_namespace_blk *nsblk;
@@ -1224,6 +1214,29 @@ static ssize_t holder_show(struct device *dev,
}
static DEVICE_ATTR_RO(holder);
+static ssize_t mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct nd_namespace_common *ndns = to_ndns(dev);
+ struct device *claim;
+ char *mode;
+ ssize_t rc;
+
+ device_lock(dev);
+ claim = ndns->claim;
+ if (pmem_should_map_pages(dev) || (claim && is_nd_pfn(claim)))
+ mode = "memory";
+ else if (claim && is_nd_btt(claim))
+ mode = "safe";
+ else
+ mode = "raw";
+ rc = sprintf(buf, "%s\n", mode);
+ device_unlock(dev);
+
+ return rc;
+}
+static DEVICE_ATTR_RO(mode);
+
static ssize_t force_raw_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
@@ -1247,6 +1260,7 @@ static DEVICE_ATTR_RW(force_raw);
static struct attribute *nd_namespace_attributes[] = {
&dev_attr_nstype.attr,
&dev_attr_size.attr,
+ &dev_attr_mode.attr,
&dev_attr_uuid.attr,
&dev_attr_holder.attr,
&dev_attr_resource.attr,
@@ -1280,7 +1294,8 @@ static umode_t namespace_visible(struct kobject *kobj,
if (a == &dev_attr_nstype.attr || a == &dev_attr_size.attr
|| a == &dev_attr_holder.attr
- || a == &dev_attr_force_raw.attr)
+ || a == &dev_attr_force_raw.attr
+ || a == &dev_attr_mode.attr)
return a->mode;
return 0;
^ permalink raw reply [flat|nested] 11+ messages in thread