]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
libnvdimm, pfn: fix memmap reservation sizing
authorDan Williams <dan.j.williams@intel.com>
Sat, 30 Apr 2016 20:07:06 +0000 (13:07 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 11 May 2016 09:21:35 +0000 (11:21 +0200)
commit 658922e57b847bb7112aa67f6441b6bbc6554412 upstream.

When configuring a pfn-device instance to allocate the memmap array it
needs to account for the fact that vmemmap_populate_hugepages()
allocates struct page blocks in HPAGE_SIZE chunks.  We need to align the
reserved area size to 2MB otherwise arch_add_memory() runs out of memory
while establishing the memmap:

 WARNING: CPU: 0 PID: 496 at arch/x86/mm/init_64.c:704 arch_add_memory+0xe7/0xf0
 [..]
 Call Trace:
  [<ffffffff8148bdb3>] dump_stack+0x85/0xc2
  [<ffffffff810a749b>] __warn+0xcb/0xf0
  [<ffffffff810a75cd>] warn_slowpath_null+0x1d/0x20
  [<ffffffff8106a497>] arch_add_memory+0xe7/0xf0
  [<ffffffff811d2097>] devm_memremap_pages+0x287/0x450
  [<ffffffff811d1ffa>] ? devm_memremap_pages+0x1ea/0x450
  [<ffffffffa0000298>] __wrap_devm_memremap_pages+0x58/0x70 [nfit_test_iomap]
  [<ffffffffa0047a58>] pmem_attach_disk+0x318/0x420 [nd_pmem]
  [<ffffffffa0047bcf>] nd_pmem_probe+0x6f/0x90 [nd_pmem]
  [<ffffffffa0009469>] nvdimm_bus_probe+0x69/0x110 [libnvdimm]
 [..]
  ndbus0: nd_pmem.probe(pfn3.0) = -12
 nd_pmem: probe of pfn3.0 failed with error -12
libndctl: ndctl_pfn_enable: pfn3.0: failed to enable

Reported-by: Namratha Kothapalli <namratha.n.kothapalli@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/nvdimm/pmem.c

index 544b802a594c5eba2b29deaabd0fbc4edc3e76e9..02c574f8ccb345175ab4319bda40841ad51e6e7b 100644 (file)
@@ -314,9 +314,16 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn)
         * implementation will limit the pfns advertised through
         * ->direct_access() to those that are included in the memmap.
         */
-       if (nd_pfn->mode == PFN_MODE_PMEM)
-               offset = ALIGN(SZ_8K + 64 * npfns, nd_pfn->align);
-       else if (nd_pfn->mode == PFN_MODE_RAM)
+       if (nd_pfn->mode == PFN_MODE_PMEM) {
+               unsigned long memmap_size;
+
+               /*
+                * vmemmap_populate_hugepages() allocates the memmap array in
+                * HPAGE_SIZE chunks.
+                */
+               memmap_size = ALIGN(64 * npfns, PMD_SIZE);
+               offset = ALIGN(SZ_8K + memmap_size, nd_pfn->align);
+       } else if (nd_pfn->mode == PFN_MODE_RAM)
                offset = ALIGN(SZ_8K, nd_pfn->align);
        else
                goto err;