Re: create devdax with "-a 1g" failed from 5.3.0-rc1

Jeff Moyer
2019-08-16T19:38:31Z

Hi, Yi,

Yi Zhang <yi.zhang@redhat.com> writes:

> Hi Dan
>
> As subject, I found it failed from bellow commit[1], steps list here
> [2] and I've attached the full dmesg, let me know if you need more
> info, thanks.
>
> [1]
> commit a3619190d62ed9d66416891be2416f6bea2b3ca4 (refs/bisect/bad)
> Author: Dan Williams <dan.j.williams@intel.com>
> Date: Thu Jul 18 15:58:40 2019 -0700
>
> libnvdimm/pfn: stop padding pmem namespaces to section alignment
>
> [2]
> # ./ndctl destroy-namespace all -r all -f
> destroyed 5 namespaces
> # ./ndctl create-namespace -r region1 -m devdax -a 1g -s 12G -vv
> libndctl: ndctl_dax_enable: dax1.0: failed to enable
> Error: namespace1.0: failed to enable
>
> failed to create namespace: No such device or address
> # ./ndctl -v
> 65

Thanks for bisecting. The problem is that your pmem region is not
aligned to 1GB. The current code handles the start offset just fine,
but does not even consider that the end address might be misaligned. We
could bring back end_trunc, and that solves the problem. Unfortunately,
it means that if you request a 12GB namespace, for example, you'll only
get 11GB of usable space. Note that the old code functioned in this
manner, too. A better solution would be to bump the allocation so that
you get 12GB of usable memory. I'm not quite sure how to go about that,
though. Dan?

Below is a patch that fixes the regression on my end. Feel free to give
it a try.

-Jeff

diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c
index 3e7b11c..cb98b8f 100644
--- a/drivers/nvdimm/pfn_devs.c
+++ b/drivers/nvdimm/pfn_devs.c
@@ -655,6 +655,7 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn)
resource_size_t start, size;
struct nd_region *nd_region;
unsigned long npfns, align;
+ u32 end_trunc;
struct nd_pfn_sb *pfn_sb;
phys_addr_t offset;
const char *sig;
@@ -696,6 +697,7 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn)
size = resource_size(&nsio->res);
npfns = PHYS_PFN(size - SZ_8K);
align = max(nd_pfn->align, (1UL << SUBSECTION_SHIFT));
+ end_trunc = start + size - ALIGN_DOWN(start + size, align);
if (nd_pfn->mode == PFN_MODE_PMEM) {
/*
* The altmap should be padded out to the block size used
@@ -714,7 +716,7 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn)
return -ENXIO;
}

- npfns = PHYS_PFN(size - offset);
+ npfns = PHYS_PFN(size - offset - end_trunc);
pfn_sb->mode = cpu_to_le32(nd_pfn->mode);
pfn_sb->dataoff = cpu_to_le64(offset);
pfn_sb->npfns = cpu_to_le64(npfns);
@@ -723,6 +725,7 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn)
memcpy(pfn_sb->parent_uuid, nd_dev_to_uuid(&ndns->dev), 16);
pfn_sb->version_major = cpu_to_le16(1);
pfn_sb->version_minor = cpu_to_le16(3);
+ pfn_sb->end_trunc = cpu_to_le32(end_trunc);
pfn_sb->align = cpu_to_le32(nd_pfn->align);
checksum = nd_sb_checksum((struct nd_gen_sb *) pfn_sb);
pfn_sb->checksum = cpu_to_le64(checksum);