Skip to content

Commit 807e336

Browse files
djbwgregkh
authored andcommitted
libnvdimm, dax: fix 1GB-aligned namespaces vs physical misalignment
commit 41fce90 upstream. The following namespace configuration attempt: # ndctl create-namespace -e namespace0.0 -m devdax -a 1G -f libndctl: ndctl_dax_enable: dax0.1: failed to enable Error: namespace0.0: failed to enable failed to reconfigure namespace: No such device or address ...fails when the backing memory range is not physically aligned to 1G: # cat /proc/iomem | grep Persistent 210000000-30fffffff : Persistent Memory (legacy) In the above example the 4G persistent memory range starts and ends on a 256MB boundary. We handle this case correctly when needing to handle cases that violate section alignment (128MB) collisions against "System RAM", and we simply need to extend that padding/truncation for the 1GB alignment use case. Cc: <stable@vger.kernel.org> Fixes: 315c562 ("libnvdimm, pfn: add 'align' attribute...") Reported-and-tested-by: Jane Chu <jane.chu@oracle.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 00a6e63 commit 807e336

2 files changed

Lines changed: 13 additions & 3 deletions

File tree

drivers/nvdimm/pfn_devs.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,12 @@ static struct vmem_altmap *__nvdimm_setup_pfn(struct nd_pfn *nd_pfn,
563563
return altmap;
564564
}
565565

566+
static u64 phys_pmem_align_down(struct nd_pfn *nd_pfn, u64 phys)
567+
{
568+
return min_t(u64, PHYS_SECTION_ALIGN_DOWN(phys),
569+
ALIGN_DOWN(phys, nd_pfn->align));
570+
}
571+
566572
static int nd_pfn_init(struct nd_pfn *nd_pfn)
567573
{
568574
u32 dax_label_reserve = is_nd_dax(&nd_pfn->dev) ? SZ_128K : 0;
@@ -618,13 +624,16 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn)
618624
start = nsio->res.start;
619625
size = PHYS_SECTION_ALIGN_UP(start + size) - start;
620626
if (region_intersects(start, size, IORESOURCE_SYSTEM_RAM,
621-
IORES_DESC_NONE) == REGION_MIXED) {
627+
IORES_DESC_NONE) == REGION_MIXED
628+
|| !IS_ALIGNED(start + resource_size(&nsio->res),
629+
nd_pfn->align)) {
622630
size = resource_size(&nsio->res);
623-
end_trunc = start + size - PHYS_SECTION_ALIGN_DOWN(start + size);
631+
end_trunc = start + size - phys_pmem_align_down(nd_pfn,
632+
start + size);
624633
}
625634

626635
if (start_pad + end_trunc)
627-
dev_info(&nd_pfn->dev, "%s section collision, truncate %d bytes\n",
636+
dev_info(&nd_pfn->dev, "%s alignment collision, truncate %d bytes\n",
628637
dev_name(&ndns->dev), start_pad + end_trunc);
629638

630639
/*

include/linux/kernel.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#define REPEAT_BYTE(x) ((~0ul / 0xff) * (x))
4747

4848
#define ALIGN(x, a) __ALIGN_KERNEL((x), (a))
49+
#define ALIGN_DOWN(x, a) __ALIGN_KERNEL((x) - ((a) - 1), (a))
4950
#define __ALIGN_MASK(x, mask) __ALIGN_KERNEL_MASK((x), (mask))
5051
#define PTR_ALIGN(p, a) ((typeof(p))ALIGN((unsigned long)(p), (a)))
5152
#define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a) - 1)) == 0)

0 commit comments

Comments
 (0)