| From d5483feda85a8f39ee2e940e279547c686aac30c Mon Sep 17 00:00:00 2001 |
| From: Dan Williams <dan.j.williams@intel.com> |
| Date: Thu, 4 May 2017 19:54:42 -0700 |
| Subject: [PATCH] libnvdimm, pfn: fix 'npfns' vs section alignment |
| |
| commit d5483feda85a8f39ee2e940e279547c686aac30c upstream. |
| |
| Fix failures to create namespaces due to the vmem_altmap not advertising |
| enough free space to store the memmap. |
| |
| WARNING: CPU: 15 PID: 8022 at arch/x86/mm/init_64.c:656 arch_add_memory+0xde/0xf0 |
| [..] |
| Call Trace: |
| dump_stack+0x63/0x83 |
| __warn+0xcb/0xf0 |
| warn_slowpath_null+0x1d/0x20 |
| arch_add_memory+0xde/0xf0 |
| devm_memremap_pages+0x244/0x440 |
| pmem_attach_disk+0x37e/0x490 [nd_pmem] |
| nd_pmem_probe+0x7e/0xa0 [nd_pmem] |
| nvdimm_bus_probe+0x71/0x120 [libnvdimm] |
| driver_probe_device+0x2bb/0x460 |
| bind_store+0x114/0x160 |
| drv_attr_store+0x25/0x30 |
| |
| In commit 658922e57b84 "libnvdimm, pfn: fix memmap reservation sizing" |
| we arranged for the capacity to be allocated, but failed to also update |
| the 'npfns' parameter. This leads to cases where there is enough |
| capacity reserved to hold all the allocated sections, but |
| vmemmap_populate_hugepages() still encounters -ENOMEM from |
| altmap_alloc_block_buf(). |
| |
| This fix is a stop-gap until we can teach the core memory hotplug |
| implementation to permit sub-section hotplug. |
| |
| Cc: <stable@vger.kernel.org> |
| Fixes: 658922e57b84 ("libnvdimm, pfn: fix memmap reservation sizing") |
| Reported-by: Anisha Allada <anisha.allada@intel.com> |
| Signed-off-by: Dan Williams <dan.j.williams@intel.com> |
| |
| diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c |
| index c38566f4da7d..335c8175410b 100644 |
| --- a/drivers/nvdimm/pfn_devs.c |
| +++ b/drivers/nvdimm/pfn_devs.c |
| @@ -538,7 +538,8 @@ static struct vmem_altmap *__nvdimm_setup_pfn(struct nd_pfn *nd_pfn, |
| nd_pfn->npfns = le64_to_cpu(pfn_sb->npfns); |
| altmap = NULL; |
| } else if (nd_pfn->mode == PFN_MODE_PMEM) { |
| - nd_pfn->npfns = (resource_size(res) - offset) / PAGE_SIZE; |
| + nd_pfn->npfns = PFN_SECTION_ALIGN_UP((resource_size(res) |
| + - offset) / PAGE_SIZE); |
| if (le64_to_cpu(nd_pfn->pfn_sb->npfns) > nd_pfn->npfns) |
| dev_info(&nd_pfn->dev, |
| "number of pfns truncated from %lld to %ld\n", |
| @@ -625,7 +626,8 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn) |
| */ |
| start += start_pad; |
| size = resource_size(&nsio->res); |
| - npfns = (size - start_pad - end_trunc - SZ_8K) / SZ_4K; |
| + npfns = PFN_SECTION_ALIGN_UP((size - start_pad - end_trunc - SZ_8K) |
| + / PAGE_SIZE); |
| if (nd_pfn->mode == PFN_MODE_PMEM) { |
| /* |
| * vmemmap_populate_hugepages() allocates the memmap array in |
| -- |
| 2.12.0 |
| |