diff options
author | Jeff Moyer <jmoyer@redhat.com> | 2019-08-28 11:49:46 -0400 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2019-08-28 10:33:13 -0700 |
commit | 274b924088e93593c76fb122d24bc0ef18d0ddf4 (patch) | |
tree | 2ec36ff79fd8d90827d6854d38a58b5e6d4ac293 /drivers/nvdimm/pfn_devs.c | |
parent | a55aa89aab90fae7c815b0551b07be37db359d76 (diff) | |
download | linux-274b924088e93593c76fb122d24bc0ef18d0ddf4.tar.gz linux-274b924088e93593c76fb122d24bc0ef18d0ddf4.tar.bz2 linux-274b924088e93593c76fb122d24bc0ef18d0ddf4.zip |
libnvdimm/pfn: Fix namespace creation on misaligned addresses
Yi reported[1] that after commit a3619190d62e ("libnvdimm/pfn: stop
padding pmem namespaces to section alignment"), it was no longer
possible to create a device dax namespace with a 1G alignment. The
reason was that the pmem region was not itself 1G-aligned. The code
happily skips past the first 512M, but fails to account for a now
misaligned end offset (since space was allocated starting at that
misaligned address, and extending for size GBs). Reintroduce
end_trunc, so that the code correctly handles the misaligned end
address. This results in the same behavior as before the introduction
of the offending commit.
[1] https://lists.01.org/pipermail/linux-nvdimm/2019-July/022813.html
Fixes: a3619190d62e ("libnvdimm/pfn: stop padding pmem namespaces ...")
Reported-and-tested-by: Yi Zhang <yi.zhang@redhat.com>
Signed-off-by: Jeff Moyer <jmoyer@redhat.com>
Link: https://lore.kernel.org/r/x49ftll8f39.fsf@segfault.boston.devel.redhat.com
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/nvdimm/pfn_devs.c')
-rw-r--r-- | drivers/nvdimm/pfn_devs.c | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c index 3e7b11cf1aae..cb98b8fe786e 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); |