libnvdimm: Fix altmap reservation size calculation
authorOliver O'Halloran <oohall@gmail.com>
Wed, 6 Feb 2019 02:04:53 +0000 (13:04 +1100)
committerDan Williams <dan.j.williams@intel.com>
Tue, 12 Feb 2019 18:36:34 +0000 (10:36 -0800)
Libnvdimm reserves the first 8K of pfn and devicedax namespaces to
store a superblock describing the namespace. This 8K reservation
is contained within the altmap area which the kernel uses for the
vmemmap backing for the pages within the namespace. The altmap
allows for some pages at the start of the altmap area to be reserved
and that mechanism is used to protect the superblock from being
re-used as vmemmap backing.

The number of PFNs to reserve is calculated using:

PHYS_PFN(SZ_8K)

Which is implemented as:

 #define PHYS_PFN(x) ((unsigned long)((x) >> PAGE_SHIFT))

So on systems where PAGE_SIZE is greater than 8K the reservation
size is truncated to zero and the superblock area is re-used as
vmemmap backing. As a result all the namespace information stored
in the superblock (i.e. if it's a PFN or DAX namespace) is lost
and the namespace needs to be re-created to get access to the
contents.

This patch fixes this by using PFN_UP() rather than PHYS_PFN() to ensure
that at least one page is reserved. On systems with a 4K pages size this
patch should have no effect.

Cc: stable@vger.kernel.org
Cc: Dan Williams <dan.j.williams@intel.com>
Fixes: ac515c084be9 ("libnvdimm, pmem, pfn: move pfn setup to the core")
Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
Reviewed-by: Vishal Verma <vishal.l.verma@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
drivers/nvdimm/pfn_devs.c

index 040bbd9..7760c1b 100644 (file)
@@ -593,7 +593,7 @@ static unsigned long init_altmap_base(resource_size_t base)
 
 static unsigned long init_altmap_reserve(resource_size_t base)
 {
-       unsigned long reserve = PHYS_PFN(SZ_8K);
+       unsigned long reserve = PFN_UP(SZ_8K);
        unsigned long base_pfn = PHYS_PFN(base);
 
        reserve += base_pfn - PFN_SECTION_ALIGN_DOWN(base_pfn);