diff mbox series

[v4,4/6] libnvdimm/namespace: Validate namespace size when creating a new namespace.

Message ID 20200120140749.69549-5-aneesh.kumar@linux.ibm.com (mailing list archive)
State New, archived
Headers show
Series Validating namespace size and start address attributes. | expand

Commit Message

Aneesh Kumar K.V Jan. 20, 2020, 2:07 p.m. UTC
Kernel should validate the namespace size against SUBSECTION_SIZE rather than
PAGE_SIZE. blk namespace continues to use old rule so that the new kernel don't
break the creation of blk namespaces.

Use the new helper arch_namespace_align_size() so that architecture specific
restrictions are also taken care of.

kernel log will contain the below details
[  939.620064] nd namespace0.3: 1071644672 is not 16384K aligned

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
---
 drivers/nvdimm/namespace_devs.c | 24 +++++++++++++++++++-----
 1 file changed, 19 insertions(+), 5 deletions(-)

Comments

Dan Williams Jan. 25, 2020, 2:22 a.m. UTC | #1
On Mon, Jan 20, 2020 at 6:08 AM Aneesh Kumar K.V
<aneesh.kumar@linux.ibm.com> wrote:
>
> Kernel should validate the namespace size against SUBSECTION_SIZE rather than
> PAGE_SIZE. blk namespace continues to use old rule so that the new kernel don't
> break the creation of blk namespaces.
>
> Use the new helper arch_namespace_align_size() so that architecture specific
> restrictions are also taken care of.
>
> kernel log will contain the below details
> [  939.620064] nd namespace0.3: 1071644672 is not 16384K aligned

This can't be enforced at size_store() time because the size is only
invalid relative to whether someone wants to create more namespaces or
assign a personality. Instead the free space allocation code needs to
pick the correct alignment by default, and it needs to assume that the
boot-to-boot physical address alignment variation is something greater
than memremap_compat_align(). For x86 it's typically 64MiB, do you
happen to know if Power firmware would ever physically remap a
resource range in a way that would violate that 16MiB minimum
alignment guarantee?

If we have that guarantee then the new kernel enabling needed is a way
to adjust the free-space allocator to align new allocations to
memremap_compat_align(), but that ndctl would likely bump that up to
16MiB across the board since it knows that Power needs more alignment
than x86 and it is the agent that wants to enforce cross-arch
compatibility. Otherwise the kernel should do it's best to support
requested size_store().
diff mbox series

Patch

diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c
index 0e2c90730ce3..e318566ae135 100644
--- a/drivers/nvdimm/namespace_devs.c
+++ b/drivers/nvdimm/namespace_devs.c
@@ -891,6 +891,17 @@  static int grow_dpa_allocation(struct nd_region *nd_region,
 	return 0;
 }
 
+static unsigned long nvdimm_validate_namespace_size(struct nd_region *nd_region,
+		unsigned long size, unsigned long align_size)
+{
+	u32 remainder;
+
+	div_u64_rem(size, align_size * nd_region->ndr_mappings, &remainder);
+	if (remainder)
+		return align_size * nd_region->ndr_mappings;
+	return 0;
+}
+
 static void nd_namespace_pmem_set_resource(struct nd_region *nd_region,
 		struct nd_namespace_pmem *nspm, resource_size_t size)
 {
@@ -945,11 +956,13 @@  static ssize_t __size_store(struct device *dev, unsigned long long val)
 {
 	resource_size_t allocated = 0, available = 0;
 	struct nd_region *nd_region = to_nd_region(dev->parent);
+	unsigned long align_size = arch_namespace_align_size();
 	struct nd_namespace_common *ndns = to_ndns(dev);
 	struct nd_mapping *nd_mapping;
 	struct nvdimm_drvdata *ndd;
 	struct nd_label_id label_id;
-	u32 flags = 0, remainder;
+	unsigned long map_size;
+	u32 flags = 0;
 	int rc, i, id = -1;
 	u8 *uuid = NULL;
 
@@ -967,6 +980,8 @@  static ssize_t __size_store(struct device *dev, unsigned long long val)
 		uuid = nsblk->uuid;
 		flags = NSLABEL_FLAG_LOCAL;
 		id = nsblk->id;
+		/* Let's not break blk region */
+		align_size = PAGE_SIZE;
 	}
 
 	/*
@@ -980,10 +995,9 @@  static ssize_t __size_store(struct device *dev, unsigned long long val)
 		return -ENXIO;
 	}
 
-	div_u64_rem(val, PAGE_SIZE * nd_region->ndr_mappings, &remainder);
-	if (remainder) {
-		dev_dbg(dev, "%llu is not %ldK aligned\n", val,
-				(PAGE_SIZE * nd_region->ndr_mappings) / SZ_1K);
+	map_size = nvdimm_validate_namespace_size(nd_region, val, align_size);
+	if (map_size) {
+		dev_err(dev, "%llu is not %ldK aligned\n", val, map_size / SZ_1K);
 		return -EINVAL;
 	}