Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Aneesh Kumar K.V and committed by
Dan Williams
8f4b01fc c1f45d86

+84 -37
+3 -3
drivers/dax/pmem/core.c
··· 25 25 ndns = nvdimm_namespace_common_probe(dev); 26 26 if (IS_ERR(ndns)) 27 27 return ERR_CAST(ndns); 28 - nsio = to_nd_namespace_io(&ndns->dev); 29 28 30 29 /* 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()); 32 31 if (rc) 33 32 return ERR_PTR(rc); 34 33 rc = nvdimm_setup_pfn(nd_pfn, &pgmap); 35 34 if (rc) 36 35 return ERR_PTR(rc); 37 - devm_nsio_disable(dev, nsio); 36 + devm_namespace_disable(dev, ndns); 38 37 39 38 /* reserve the metadata area, device-dax will reserve the data */ 40 39 pfn_sb = nd_pfn->pfn_sb; 41 40 offset = le64_to_cpu(pfn_sb->dataoff); 41 + nsio = to_nd_namespace_io(&ndns->dev); 42 42 if (!devm_request_mem_region(dev, nsio->res.start, offset, 43 43 dev_name(&ndns->dev))) { 44 44 dev_warn(dev, "could not reserve metadata\n");
+8 -2
drivers/nvdimm/btt.c
··· 1674 1674 struct nd_region *nd_region; 1675 1675 struct btt_sb *btt_sb; 1676 1676 struct btt *btt; 1677 - size_t rawsize; 1677 + size_t size, rawsize; 1678 + int rc; 1678 1679 1679 1680 if (!nd_btt->uuid || !nd_btt->ndns || !nd_btt->lbasize) { 1680 1681 dev_dbg(&nd_btt->dev, "incomplete btt configuration\n"); ··· 1686 1685 if (!btt_sb) 1687 1686 return -ENOMEM; 1688 1687 1688 + size = nvdimm_namespace_capacity(ndns); 1689 + rc = devm_namespace_enable(&nd_btt->dev, ndns, size); 1690 + if (rc) 1691 + return rc; 1692 + 1689 1693 /* 1690 1694 * If this returns < 0, that is ok as it just means there wasn't 1691 1695 * an existing BTT, and we're creating a new one. We still need to ··· 1699 1693 */ 1700 1694 nd_btt_version(nd_btt, ndns, btt_sb); 1701 1695 1702 - rawsize = nvdimm_namespace_capacity(ndns) - nd_btt->initial_offset; 1696 + rawsize = size - nd_btt->initial_offset; 1703 1697 if (rawsize < ARENA_MIN_SIZE) { 1704 1698 dev_dbg(&nd_btt->dev, "%s must be at least %ld bytes\n", 1705 1699 dev_name(&ndns->dev),
+6 -8
drivers/nvdimm/claim.c
··· 300 300 return rc; 301 301 } 302 302 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) 304 305 { 305 306 struct resource *res = &nsio->res; 306 307 struct nd_namespace_common *ndns = &nsio->common; 307 308 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, 310 311 dev_name(&ndns->dev))) { 311 312 dev_warn(dev, "could not reserve region %pR\n", res); 312 313 return -EBUSY; ··· 319 318 nvdimm_badblocks_populate(to_nd_region(ndns->dev.parent), &nsio->bb, 320 319 &nsio->res); 321 320 322 - nsio->addr = devm_memremap(dev, res->start, resource_size(res), 323 - ARCH_MEMREMAP_PMEM); 321 + nsio->addr = devm_memremap(dev, res->start, size, ARCH_MEMREMAP_PMEM); 324 322 325 323 return PTR_ERR_OR_ZERO(nsio->addr); 326 324 } 327 - EXPORT_SYMBOL_GPL(devm_nsio_enable); 328 325 329 326 void devm_nsio_disable(struct device *dev, struct nd_namespace_io *nsio) 330 327 { ··· 330 331 331 332 devm_memunmap(dev, nsio->addr); 332 333 devm_exit_badblocks(dev, &nsio->bb); 333 - devm_release_mem_region(dev, res->start, resource_size(res)); 334 + devm_release_mem_region(dev, res->start, nsio->size); 334 335 } 335 - EXPORT_SYMBOL_GPL(devm_nsio_disable);
+17
drivers/nvdimm/namespace_devs.c
··· 1759 1759 } 1760 1760 EXPORT_SYMBOL(nvdimm_namespace_common_probe); 1761 1761 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 + 1762 1779 static struct device **create_namespace_io(struct nd_region *nd_region) 1763 1780 { 1764 1781 struct nd_namespace_io *nsio;
+17
drivers/nvdimm/nd-core.h
··· 171 171 struct nd_pfn *to_nd_pfn_safe(struct device *dev); 172 172 bool is_nvdimm_bus(struct device *dev); 173 173 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 + 174 191 #ifdef CONFIG_PROVE_LOCKING 175 192 extern struct class *nd_class; 176 193
+9 -13
drivers/nvdimm/nd.h
··· 212 212 struct nd_pfn nd_pfn; 213 213 }; 214 214 215 + static inline u32 nd_info_block_reserve(void) 216 + { 217 + return ALIGN(SZ_8K, PAGE_SIZE); 218 + } 219 + 215 220 enum nd_async_mode { 216 221 ND_SYNC, 217 222 ND_ASYNC, ··· 375 370 unsigned int pmem_sector_size(struct nd_namespace_common *ndns); 376 371 void nvdimm_badblocks_populate(struct nd_region *nd_region, 377 372 struct badblocks *bb, const struct resource *res); 373 + int devm_namespace_enable(struct device *dev, struct nd_namespace_common *ndns, 374 + resource_size_t size); 375 + void devm_namespace_disable(struct device *dev, 376 + struct nd_namespace_common *ndns); 378 377 #if IS_ENABLED(CONFIG_ND_CLAIM) 379 - 380 378 /* max struct page size independent of kernel config */ 381 379 #define MAX_STRUCT_PAGE_SIZE 64 382 - 383 380 int nvdimm_setup_pfn(struct nd_pfn *nd_pfn, struct dev_pagemap *pgmap); 384 - int devm_nsio_enable(struct device *dev, struct nd_namespace_io *nsio); 385 - void devm_nsio_disable(struct device *dev, struct nd_namespace_io *nsio); 386 381 #else 387 382 static inline int nvdimm_setup_pfn(struct nd_pfn *nd_pfn, 388 383 struct dev_pagemap *pgmap) 389 384 { 390 385 return -ENXIO; 391 - } 392 - static inline int devm_nsio_enable(struct device *dev, 393 - struct nd_namespace_io *nsio) 394 - { 395 - return -ENXIO; 396 - } 397 - static inline void devm_nsio_disable(struct device *dev, 398 - struct nd_namespace_io *nsio) 399 - { 400 386 } 401 387 #endif 402 388 int nd_blk_region_init(struct nd_region *nd_region);
+11 -7
drivers/nvdimm/pfn_devs.c
··· 382 382 meta_start = (SZ_4K + sizeof(*pfn_sb)) >> 9; 383 383 meta_num = (le64_to_cpu(pfn_sb->dataoff) >> 9) - meta_start; 384 384 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 + 385 394 do { 386 395 unsigned long zero_len; 387 396 u64 nsoff; ··· 644 635 } 645 636 EXPORT_SYMBOL(nd_pfn_probe); 646 637 647 - static u32 info_block_reserve(void) 648 - { 649 - return ALIGN(SZ_8K, PAGE_SIZE); 650 - } 651 - 652 638 /* 653 639 * We hotplug memory at sub-section granularity, pad the reserved area 654 640 * from the previous section base to the namespace base address. ··· 657 653 658 654 static unsigned long init_altmap_reserve(resource_size_t base) 659 655 { 660 - unsigned long reserve = info_block_reserve() >> PAGE_SHIFT; 656 + unsigned long reserve = nd_info_block_reserve() >> PAGE_SHIFT; 661 657 unsigned long base_pfn = PHYS_PFN(base); 662 658 663 659 reserve += base_pfn - SUBSECTION_ALIGN_DOWN(base_pfn); ··· 672 668 u64 offset = le64_to_cpu(pfn_sb->dataoff); 673 669 u32 start_pad = __le32_to_cpu(pfn_sb->start_pad); 674 670 u32 end_trunc = __le32_to_cpu(pfn_sb->end_trunc); 675 - u32 reserve = info_block_reserve(); 671 + u32 reserve = nd_info_block_reserve(); 676 672 struct nd_namespace_common *ndns = nd_pfn->ndns; 677 673 struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev); 678 674 resource_size_t base = nsio->res.start + start_pad;
+13 -4
drivers/nvdimm/pmem.c
··· 372 372 if (!pmem) 373 373 return -ENOMEM; 374 374 375 + rc = devm_namespace_enable(dev, ndns, nd_info_block_reserve()); 376 + if (rc) 377 + return rc; 378 + 375 379 /* while nsio_rw_bytes is active, parse a pfn info block if present */ 376 380 if (is_nd_pfn(dev)) { 377 381 nd_pfn = to_nd_pfn(dev); ··· 385 381 } 386 382 387 383 /* we're attaching a block device, disable raw namespace access */ 388 - devm_nsio_disable(dev, nsio); 384 + devm_namespace_disable(dev, ndns); 389 385 390 386 dev_set_drvdata(dev, pmem); 391 387 pmem->phys_addr = res->start; ··· 501 497 if (IS_ERR(ndns)) 502 498 return PTR_ERR(ndns); 503 499 504 - if (devm_nsio_enable(dev, to_nd_namespace_io(&ndns->dev))) 505 - return -ENXIO; 506 - 507 500 if (is_nd_btt(dev)) 508 501 return nvdimm_namespace_attach_btt(ndns); 509 502 510 503 if (is_nd_pfn(dev)) 511 504 return pmem_attach_disk(dev, ndns); 505 + 506 + ret = devm_namespace_enable(dev, ndns, nd_info_block_reserve()); 507 + if (ret) 508 + return ret; 512 509 513 510 ret = nd_btt_probe(dev, ndns); 514 511 if (ret == 0) ··· 537 532 return -ENXIO; 538 533 else if (ret == -EOPNOTSUPP) 539 534 return ret; 535 + 536 + /* probe complete, attach handles namespace enabling */ 537 + devm_namespace_disable(dev, ndns); 538 + 540 539 return pmem_attach_disk(dev, ndns); 541 540 } 542 541