Skip to content

Commit 8f4b01f

Browse files
kvaneeshdjbw
authored andcommitted
libnvdimm/namespace: Differentiate between probe mapping and runtime mapping
The nvdimm core currently maps the full namespace to an ioremap range while probing the namespace mode. This can result in probe failures on architectures that have limited ioremap space. For example, with a large btt namespace that consumes most of I/O remap range, depending on the sequence of namespace initialization, the user can find a pfn namespace initialization failure due to unavailable I/O remap space which nvdimm core uses for temporary mapping. nvdimm core can avoid this failure by only mapping the reserved info block area to check for pfn superblock type and map the full namespace resource only before using the namespace. Given that personalities like BTT can be layered on top of any namespace type create a generic form of devm_nsio_enable (devm_namespace_enable) and use it inside the per-personality attach routines. Now devm_namespace_enable() is always paired with disable unless the mapping is going to be used for long term runtime access. Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com> Link: https://lore.kernel.org/r/20191017073308.32645-1-aneesh.kumar@linux.ibm.com [djbw: reworks to move devm_namespace_{en,dis}able into *attach helpers] Reported-by: kbuild test robot <lkp@intel.com> Link: https://lore.kernel.org/r/20191031105741.102793-2-aneesh.kumar@linux.ibm.com Signed-off-by: Dan Williams <dan.j.williams@intel.com>
1 parent c1f45d8 commit 8f4b01f

File tree

8 files changed

+84
-37
lines changed

8 files changed

+84
-37
lines changed

drivers/dax/pmem/core.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,20 @@ struct dev_dax *__dax_pmem_probe(struct device *dev, enum dev_dax_subsys subsys)
2525
ndns = nvdimm_namespace_common_probe(dev);
2626
if (IS_ERR(ndns))
2727
return ERR_CAST(ndns);
28-
nsio = to_nd_namespace_io(&ndns->dev);
2928

3029
/* parse the 'pfn' info block via ->rw_bytes */
31-
rc = devm_nsio_enable(dev, nsio);
30+
rc = devm_namespace_enable(dev, ndns, nd_info_block_reserve());
3231
if (rc)
3332
return ERR_PTR(rc);
3433
rc = nvdimm_setup_pfn(nd_pfn, &pgmap);
3534
if (rc)
3635
return ERR_PTR(rc);
37-
devm_nsio_disable(dev, nsio);
36+
devm_namespace_disable(dev, ndns);
3837

3938
/* reserve the metadata area, device-dax will reserve the data */
4039
pfn_sb = nd_pfn->pfn_sb;
4140
offset = le64_to_cpu(pfn_sb->dataoff);
41+
nsio = to_nd_namespace_io(&ndns->dev);
4242
if (!devm_request_mem_region(dev, nsio->res.start, offset,
4343
dev_name(&ndns->dev))) {
4444
dev_warn(dev, "could not reserve metadata\n");

drivers/nvdimm/btt.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1674,7 +1674,8 @@ int nvdimm_namespace_attach_btt(struct nd_namespace_common *ndns)
16741674
struct nd_region *nd_region;
16751675
struct btt_sb *btt_sb;
16761676
struct btt *btt;
1677-
size_t rawsize;
1677+
size_t size, rawsize;
1678+
int rc;
16781679

16791680
if (!nd_btt->uuid || !nd_btt->ndns || !nd_btt->lbasize) {
16801681
dev_dbg(&nd_btt->dev, "incomplete btt configuration\n");
@@ -1685,6 +1686,11 @@ int nvdimm_namespace_attach_btt(struct nd_namespace_common *ndns)
16851686
if (!btt_sb)
16861687
return -ENOMEM;
16871688

1689+
size = nvdimm_namespace_capacity(ndns);
1690+
rc = devm_namespace_enable(&nd_btt->dev, ndns, size);
1691+
if (rc)
1692+
return rc;
1693+
16881694
/*
16891695
* If this returns < 0, that is ok as it just means there wasn't
16901696
* an existing BTT, and we're creating a new one. We still need to
@@ -1693,7 +1699,7 @@ int nvdimm_namespace_attach_btt(struct nd_namespace_common *ndns)
16931699
*/
16941700
nd_btt_version(nd_btt, ndns, btt_sb);
16951701

1696-
rawsize = nvdimm_namespace_capacity(ndns) - nd_btt->initial_offset;
1702+
rawsize = size - nd_btt->initial_offset;
16971703
if (rawsize < ARENA_MIN_SIZE) {
16981704
dev_dbg(&nd_btt->dev, "%s must be at least %ld bytes\n",
16991705
dev_name(&ndns->dev),

drivers/nvdimm/claim.c

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -300,13 +300,14 @@ static int nsio_rw_bytes(struct nd_namespace_common *ndns,
300300
return rc;
301301
}
302302

303-
int devm_nsio_enable(struct device *dev, struct nd_namespace_io *nsio)
303+
int devm_nsio_enable(struct device *dev, struct nd_namespace_io *nsio,
304+
resource_size_t size)
304305
{
305306
struct resource *res = &nsio->res;
306307
struct nd_namespace_common *ndns = &nsio->common;
307308

308-
nsio->size = resource_size(res);
309-
if (!devm_request_mem_region(dev, res->start, resource_size(res),
309+
nsio->size = size;
310+
if (!devm_request_mem_region(dev, res->start, size,
310311
dev_name(&ndns->dev))) {
311312
dev_warn(dev, "could not reserve region %pR\n", res);
312313
return -EBUSY;
@@ -318,19 +319,16 @@ int devm_nsio_enable(struct device *dev, struct nd_namespace_io *nsio)
318319
nvdimm_badblocks_populate(to_nd_region(ndns->dev.parent), &nsio->bb,
319320
&nsio->res);
320321

321-
nsio->addr = devm_memremap(dev, res->start, resource_size(res),
322-
ARCH_MEMREMAP_PMEM);
322+
nsio->addr = devm_memremap(dev, res->start, size, ARCH_MEMREMAP_PMEM);
323323

324324
return PTR_ERR_OR_ZERO(nsio->addr);
325325
}
326-
EXPORT_SYMBOL_GPL(devm_nsio_enable);
327326

328327
void devm_nsio_disable(struct device *dev, struct nd_namespace_io *nsio)
329328
{
330329
struct resource *res = &nsio->res;
331330

332331
devm_memunmap(dev, nsio->addr);
333332
devm_exit_badblocks(dev, &nsio->bb);
334-
devm_release_mem_region(dev, res->start, resource_size(res));
333+
devm_release_mem_region(dev, res->start, nsio->size);
335334
}
336-
EXPORT_SYMBOL_GPL(devm_nsio_disable);

drivers/nvdimm/namespace_devs.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1759,6 +1759,23 @@ struct nd_namespace_common *nvdimm_namespace_common_probe(struct device *dev)
17591759
}
17601760
EXPORT_SYMBOL(nvdimm_namespace_common_probe);
17611761

1762+
int devm_namespace_enable(struct device *dev, struct nd_namespace_common *ndns,
1763+
resource_size_t size)
1764+
{
1765+
if (is_namespace_blk(&ndns->dev))
1766+
return 0;
1767+
return devm_nsio_enable(dev, to_nd_namespace_io(&ndns->dev), size);
1768+
}
1769+
EXPORT_SYMBOL_GPL(devm_namespace_enable);
1770+
1771+
void devm_namespace_disable(struct device *dev, struct nd_namespace_common *ndns)
1772+
{
1773+
if (is_namespace_blk(&ndns->dev))
1774+
return;
1775+
devm_nsio_disable(dev, to_nd_namespace_io(&ndns->dev));
1776+
}
1777+
EXPORT_SYMBOL_GPL(devm_namespace_disable);
1778+
17621779
static struct device **create_namespace_io(struct nd_region *nd_region)
17631780
{
17641781
struct nd_namespace_io *nsio;

drivers/nvdimm/nd-core.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,23 @@ ssize_t nd_namespace_store(struct device *dev,
171171
struct nd_pfn *to_nd_pfn_safe(struct device *dev);
172172
bool is_nvdimm_bus(struct device *dev);
173173

174+
#if IS_ENABLED(CONFIG_ND_CLAIM)
175+
int devm_nsio_enable(struct device *dev, struct nd_namespace_io *nsio,
176+
resource_size_t size);
177+
void devm_nsio_disable(struct device *dev, struct nd_namespace_io *nsio);
178+
#else
179+
static inline int devm_nsio_enable(struct device *dev,
180+
struct nd_namespace_io *nsio, resource_size_t size)
181+
{
182+
return -ENXIO;
183+
}
184+
185+
static inline void devm_nsio_disable(struct device *dev,
186+
struct nd_namespace_io *nsio)
187+
{
188+
}
189+
#endif
190+
174191
#ifdef CONFIG_PROVE_LOCKING
175192
extern struct class *nd_class;
176193

drivers/nvdimm/nd.h

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,11 @@ struct nd_dax {
212212
struct nd_pfn nd_pfn;
213213
};
214214

215+
static inline u32 nd_info_block_reserve(void)
216+
{
217+
return ALIGN(SZ_8K, PAGE_SIZE);
218+
}
219+
215220
enum nd_async_mode {
216221
ND_SYNC,
217222
ND_ASYNC,
@@ -370,29 +375,20 @@ const char *nvdimm_namespace_disk_name(struct nd_namespace_common *ndns,
370375
unsigned int pmem_sector_size(struct nd_namespace_common *ndns);
371376
void nvdimm_badblocks_populate(struct nd_region *nd_region,
372377
struct badblocks *bb, const struct resource *res);
378+
int devm_namespace_enable(struct device *dev, struct nd_namespace_common *ndns,
379+
resource_size_t size);
380+
void devm_namespace_disable(struct device *dev,
381+
struct nd_namespace_common *ndns);
373382
#if IS_ENABLED(CONFIG_ND_CLAIM)
374-
375383
/* max struct page size independent of kernel config */
376384
#define MAX_STRUCT_PAGE_SIZE 64
377-
378385
int nvdimm_setup_pfn(struct nd_pfn *nd_pfn, struct dev_pagemap *pgmap);
379-
int devm_nsio_enable(struct device *dev, struct nd_namespace_io *nsio);
380-
void devm_nsio_disable(struct device *dev, struct nd_namespace_io *nsio);
381386
#else
382387
static inline int nvdimm_setup_pfn(struct nd_pfn *nd_pfn,
383388
struct dev_pagemap *pgmap)
384389
{
385390
return -ENXIO;
386391
}
387-
static inline int devm_nsio_enable(struct device *dev,
388-
struct nd_namespace_io *nsio)
389-
{
390-
return -ENXIO;
391-
}
392-
static inline void devm_nsio_disable(struct device *dev,
393-
struct nd_namespace_io *nsio)
394-
{
395-
}
396392
#endif
397393
int nd_blk_region_init(struct nd_region *nd_region);
398394
int nd_region_activate(struct nd_region *nd_region);

drivers/nvdimm/pfn_devs.c

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,15 @@ static int nd_pfn_clear_memmap_errors(struct nd_pfn *nd_pfn)
382382
meta_start = (SZ_4K + sizeof(*pfn_sb)) >> 9;
383383
meta_num = (le64_to_cpu(pfn_sb->dataoff) >> 9) - meta_start;
384384

385+
/*
386+
* re-enable the namespace with correct size so that we can access
387+
* the device memmap area.
388+
*/
389+
devm_namespace_disable(&nd_pfn->dev, ndns);
390+
rc = devm_namespace_enable(&nd_pfn->dev, ndns, le64_to_cpu(pfn_sb->dataoff));
391+
if (rc)
392+
return rc;
393+
385394
do {
386395
unsigned long zero_len;
387396
u64 nsoff;
@@ -635,11 +644,6 @@ int nd_pfn_probe(struct device *dev, struct nd_namespace_common *ndns)
635644
}
636645
EXPORT_SYMBOL(nd_pfn_probe);
637646

638-
static u32 info_block_reserve(void)
639-
{
640-
return ALIGN(SZ_8K, PAGE_SIZE);
641-
}
642-
643647
/*
644648
* We hotplug memory at sub-section granularity, pad the reserved area
645649
* from the previous section base to the namespace base address.
@@ -653,7 +657,7 @@ static unsigned long init_altmap_base(resource_size_t base)
653657

654658
static unsigned long init_altmap_reserve(resource_size_t base)
655659
{
656-
unsigned long reserve = info_block_reserve() >> PAGE_SHIFT;
660+
unsigned long reserve = nd_info_block_reserve() >> PAGE_SHIFT;
657661
unsigned long base_pfn = PHYS_PFN(base);
658662

659663
reserve += base_pfn - SUBSECTION_ALIGN_DOWN(base_pfn);
@@ -668,7 +672,7 @@ static int __nvdimm_setup_pfn(struct nd_pfn *nd_pfn, struct dev_pagemap *pgmap)
668672
u64 offset = le64_to_cpu(pfn_sb->dataoff);
669673
u32 start_pad = __le32_to_cpu(pfn_sb->start_pad);
670674
u32 end_trunc = __le32_to_cpu(pfn_sb->end_trunc);
671-
u32 reserve = info_block_reserve();
675+
u32 reserve = nd_info_block_reserve();
672676
struct nd_namespace_common *ndns = nd_pfn->ndns;
673677
struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev);
674678
resource_size_t base = nsio->res.start + start_pad;

drivers/nvdimm/pmem.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,10 @@ static int pmem_attach_disk(struct device *dev,
372372
if (!pmem)
373373
return -ENOMEM;
374374

375+
rc = devm_namespace_enable(dev, ndns, nd_info_block_reserve());
376+
if (rc)
377+
return rc;
378+
375379
/* while nsio_rw_bytes is active, parse a pfn info block if present */
376380
if (is_nd_pfn(dev)) {
377381
nd_pfn = to_nd_pfn(dev);
@@ -381,7 +385,7 @@ static int pmem_attach_disk(struct device *dev,
381385
}
382386

383387
/* we're attaching a block device, disable raw namespace access */
384-
devm_nsio_disable(dev, nsio);
388+
devm_namespace_disable(dev, ndns);
385389

386390
dev_set_drvdata(dev, pmem);
387391
pmem->phys_addr = res->start;
@@ -497,15 +501,16 @@ static int nd_pmem_probe(struct device *dev)
497501
if (IS_ERR(ndns))
498502
return PTR_ERR(ndns);
499503

500-
if (devm_nsio_enable(dev, to_nd_namespace_io(&ndns->dev)))
501-
return -ENXIO;
502-
503504
if (is_nd_btt(dev))
504505
return nvdimm_namespace_attach_btt(ndns);
505506

506507
if (is_nd_pfn(dev))
507508
return pmem_attach_disk(dev, ndns);
508509

510+
ret = devm_namespace_enable(dev, ndns, nd_info_block_reserve());
511+
if (ret)
512+
return ret;
513+
509514
ret = nd_btt_probe(dev, ndns);
510515
if (ret == 0)
511516
return -ENXIO;
@@ -532,6 +537,10 @@ static int nd_pmem_probe(struct device *dev)
532537
return -ENXIO;
533538
else if (ret == -EOPNOTSUPP)
534539
return ret;
540+
541+
/* probe complete, attach handles namespace enabling */
542+
devm_namespace_disable(dev, ndns);
543+
535544
return pmem_attach_disk(dev, ndns);
536545
}
537546

0 commit comments

Comments
 (0)