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

Yi Zhang
2019-08-19T06:28:56Z

Thanks Jeff

This patch works on my side.

# ndctl create-namespace -r region0 -m devdax -a 1g -s 12G
{
"dev":"namespace0.3",
"mode":"devdax",
"map":"dev",
"size":"11.00 GiB (11.81 GB)",
"uuid":"84645a0a-ae21-4608-8512-1248cc48b085",
"daxregion":{
"id":0,
"size":"11.00 GiB (11.81 GB)",
"align":1073741824,
"devices":[
{
"chardev":"dax0.3",
"size":"11.00 GiB (11.81 GB)"
}
]
},
"align":1073741824
}

On 8/17/19 3:36 AM, Jeff Moyer wrote:
> 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);