Skip to content

Commit

Permalink
libnvdimm, dax: fix 1GB-aligned namespaces vs physical misalignment
Browse files Browse the repository at this point in the history
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: <[email protected]>
Fixes: 315c562 ("libnvdimm, pfn: add 'align' attribute...")
Reported-and-tested-by: Jane Chu <[email protected]>
Signed-off-by: Dan Williams <[email protected]>
  • Loading branch information
djbw committed Dec 19, 2017
1 parent 19deaa2 commit 41fce90
Showing 1 changed file with 12 additions and 3 deletions.
15 changes: 12 additions & 3 deletions drivers/nvdimm/pfn_devs.c
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,12 @@ static struct vmem_altmap *__nvdimm_setup_pfn(struct nd_pfn *nd_pfn,
return altmap;
}

static u64 phys_pmem_align_down(struct nd_pfn *nd_pfn, u64 phys)
{
return min_t(u64, PHYS_SECTION_ALIGN_DOWN(phys),
ALIGN_DOWN(phys, nd_pfn->align));
}

static int nd_pfn_init(struct nd_pfn *nd_pfn)
{
u32 dax_label_reserve = is_nd_dax(&nd_pfn->dev) ? SZ_128K : 0;
Expand Down Expand Up @@ -638,13 +644,16 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn)
start = nsio->res.start;
size = PHYS_SECTION_ALIGN_UP(start + size) - start;
if (region_intersects(start, size, IORESOURCE_SYSTEM_RAM,
IORES_DESC_NONE) == REGION_MIXED) {
IORES_DESC_NONE) == REGION_MIXED
|| !IS_ALIGNED(start + resource_size(&nsio->res),
nd_pfn->align)) {
size = resource_size(&nsio->res);
end_trunc = start + size - PHYS_SECTION_ALIGN_DOWN(start + size);
end_trunc = start + size - phys_pmem_align_down(nd_pfn,
start + size);
}

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

/*
Expand Down

0 comments on commit 41fce90

Please sign in to comment.