mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v3 0/2] dax: Fix Device DAX range allocation validation
@ 2026-09-24  2:50 Muchun Song
  2026-09-24  2:50 ` [PATCH v3 1/2] dax/bus: fix mapping attribute error reporting Muchun Song
  2026-09-24  2:50 ` [PATCH v3 2/2] dax/bus: fix Device DAX range alignment validation Muchun Song
  0 siblings, 2 replies; 7+ messages in thread
From: Muchun Song @ 2026-09-24  2:50 UTC (permalink / raw)
  To: Dan Williams, Vishal Verma, Dave Jiang, Alison Schofield
  Cc: Andrew Morton, Joao Martins, nvdimm, linux-cxl, linux-kernel,
	Muchun Song, muchun.song

While working on the HugeTLB Vmemmap Optimization (HVO) generalization,
Sashiko reported that memmap_init_zone_device() could be asked to
initialize struct pages with a large-page order for a physical range
that was not naturally aligned to that order.

Following the Device DAX call path confirmed that the condition was
reachable. Device DAX range validation checks the range size, but not
its start address. An unaligned range can therefore reach
memmap_init_zone_device() after the device binds, and a subsequent write
to a userspace mapping may trigger a kernel panic. With the help of an
LLM, I was able to reproduce the failure.

The automatic resize path has a related problem. It can split an aligned
size request across arbitrary free gaps, consume an unaligned fragment,
and leave the resize partially applied when a later allocation fails.

This series first fixes the mapping sysfs attribute to propagate
validation failures. It then validates both the start and size of every
Device DAX range and makes automatic resize account only for usable
aligned space.

The changes were tested by booting the kernel in a VM with a fragmented
dynamic DAX region. Misaligned mappings were rejected with -EINVAL,
aligned allocation and multi-range mmap read/write succeeded, and an
allocation exceeding the usable aligned space returned -ENOSPC without
leaving a partial allocation.

v3:
- Collect Reviewed-by from Dave Jiang
- Serialize size alignment validation with alignment updates to avoid a
  partial shrink after a concurrent alignment change (reported by Sashiko)
- Document the size validation serialization in the commit message

v2: https://lore.kernel.org/all/20260922082551.874901-1-songmuchun@bytedance.com/
- Return explicit errors before Device DAX range allocation
  (suggested by Dave Jiang)
- Move the mapping error reporting fix before the range alignment
  validation fix for independent backports (suggested by Dave Jiang)
- Keep the alloc_is_aligned() name to avoid unrelated helper renaming
  (suggested by Dave Jiang)

v1: https://lore.kernel.org/all/20260915095621.3744167-1-songmuchun@bytedance.com/

Muchun Song (2):
  dax/bus: fix mapping attribute error reporting
  dax/bus: fix Device DAX range alignment validation

 drivers/dax/bus.c | 152 +++++++++++++++++++++++++++++++++++-----------
 1 file changed, 115 insertions(+), 37 deletions(-)


base-commit: 93f51579e7df248780214094418f205253383cc5
-- 
2.54.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v3 1/2] dax/bus: fix mapping attribute error reporting
  2026-09-24  2:50 [PATCH v3 0/2] dax: Fix Device DAX range allocation validation Muchun Song
@ 2026-09-24  2:50 ` Muchun Song
  2026-10-13  0:13   ` Alison Schofield
  2026-10-13  2:31   ` jianyungao89
  2026-09-24  2:50 ` [PATCH v3 2/2] dax/bus: fix Device DAX range alignment validation Muchun Song
  1 sibling, 2 replies; 7+ messages in thread
From: Muchun Song @ 2026-09-24  2:50 UTC (permalink / raw)
  To: Dan Williams, Vishal Verma, Dave Jiang, Alison Schofield
  Cc: Andrew Morton, Joao Martins, nvdimm, linux-cxl, linux-kernel,
	Muchun Song, muchun.song

After the DAX configuration locking was converted to rwsems, successful
lock acquisition leaves rc set to zero in mapping_store(). Two error
paths can return this stale value: an unbound region driver and a
misaligned range size. The sysfs write therefore reports success without
allocating the requested range.

Return -ENXIO when the region driver is not bound and -EINVAL when the
range size is misaligned.

Fixes: c05ae9d85b47 ("dax/bus.c: replace driver-core lock usage by a local rwsem")
Assisted-by: LLM
Signed-off-by: Muchun Song <songmuchun@bytedance.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
---
v3:
- Collect Reviewed-by from Dave Jiang

v2:
- Return explicit errors before Device DAX range allocation
  (suggested by Dave Jiang)
- Move the patch before range alignment validation for independent
  backports (suggested by Dave Jiang)
---
 drivers/dax/bus.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/dax/bus.c b/drivers/dax/bus.c
index b809e1a264af..e40c25401cf0 100644
--- a/drivers/dax/bus.c
+++ b/drivers/dax/bus.c
@@ -1192,7 +1192,7 @@ static ssize_t mapping_store(struct device *dev, struct device_attribute *attr,
 		return rc;
 	if (!dax_region->dev->driver) {
 		up_write(&dax_region_rwsem);
-		return rc;
+		return -ENXIO;
 	}
 	rc = down_write_killable(&dax_dev_rwsem);
 	if (rc) {
@@ -1201,8 +1201,12 @@ static ssize_t mapping_store(struct device *dev, struct device_attribute *attr,
 	}
 
 	to_alloc = range_len(&r);
-	if (alloc_is_aligned(dev_dax, to_alloc))
+	if (!alloc_is_aligned(dev_dax, to_alloc)) {
+		dev_dbg(dev, "%s: size: %zu misaligned\n", __func__, to_alloc);
+		rc = -EINVAL;
+	} else {
 		rc = alloc_dev_dax_range(dev_dax, r.start, to_alloc);
+	}
 	up_write(&dax_dev_rwsem);
 	up_write(&dax_region_rwsem);
 
-- 
2.54.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v3 2/2] dax/bus: fix Device DAX range alignment validation
  2026-09-24  2:50 [PATCH v3 0/2] dax: Fix Device DAX range allocation validation Muchun Song
  2026-09-24  2:50 ` [PATCH v3 1/2] dax/bus: fix mapping attribute error reporting Muchun Song
@ 2026-09-24  2:50 ` Muchun Song
  2026-10-13  0:20   ` Alison Schofield
  1 sibling, 1 reply; 7+ messages in thread
From: Muchun Song @ 2026-09-24  2:50 UTC (permalink / raw)
  To: Dan Williams, Vishal Verma, Dave Jiang, Alison Schofield
  Cc: Andrew Morton, Joao Martins, nvdimm, linux-cxl, linux-kernel,
	Muchun Song, muchun.song

dev_dax->align describes the page size used by a Device DAX mapping.
Both the start and size of every range must therefore be aligned to it;
otherwise the starting PFN cannot represent a naturally aligned page of
that size.

Only range sizes are currently validated. A dynamic device can therefore
select a large-page alignment and allocate a range whose start is not
naturally aligned to that page size. The device binds successfully, but a
subsequent write to a userspace mapping may trigger a kernel panic.

The automatic resize path can also split a size-aligned request across
arbitrary free gaps. When devices with different alignments fragment a
region, this can extend a range by less than its alignment. A later
allocation then fails, leaving the failed resize partially applied.

Validate both the start and size of allocated and adjusted ranges. Make
the resize path account only for usable aligned space before changing any
ranges, and skip gaps that cannot satisfy the device alignment. Initialize
the device alignment before allocating its initial range so that all
allocations use the same validation. Perform size validation under the
same locks as alignment updates so the alignment cannot change before
resizing begins.

A mapping with an unaligned start is now rejected with -EINVAL, while a
naturally aligned mapping still binds successfully.

Fixes: 6d82120f4156 ("device-dax: add an 'align' attribute")
Assisted-by: LLM
Signed-off-by: Muchun Song <songmuchun@bytedance.com>
---
v3:
- Serialize size alignment validation with alignment updates to avoid a
  partial shrink after a concurrent alignment change (reported by Sashiko)
- Document the size validation serialization in the commit message

v2:
- Keep the alloc_is_aligned() name to avoid unrelated helper renaming
  (suggested by Dave Jiang)
- Move this patch after the mapping error reporting fix for independent
  backports (suggested by Dave Jiang)
---
 drivers/dax/bus.c | 144 +++++++++++++++++++++++++++++++++++-----------
 1 file changed, 109 insertions(+), 35 deletions(-)

diff --git a/drivers/dax/bus.c b/drivers/dax/bus.c
index e40c25401cf0..8616527656d8 100644
--- a/drivers/dax/bus.c
+++ b/drivers/dax/bus.c
@@ -848,6 +848,44 @@ static int devm_register_dax_mapping(struct dev_dax *dev_dax, int range_id)
 	return 0;
 }
 
+static inline unsigned long dev_dax_min_align(struct dev_dax *dev_dax)
+{
+	return max_t(unsigned long, dev_dax->align, memremap_compat_align());
+}
+
+static inline bool alloc_is_aligned(struct dev_dax *dev_dax, resource_size_t size)
+{
+	/*
+	 * The minimum mapping granularity for a device instance is a
+	 * single subsection, unless the arch says otherwise.
+	 */
+	return IS_ALIGNED(size, dev_dax_min_align(dev_dax));
+}
+
+static inline bool range_is_aligned(struct dev_dax *dev_dax, u64 start,
+				    resource_size_t size)
+{
+	return IS_ALIGNED(start | size, dev_dax_min_align(dev_dax));
+}
+
+static resource_size_t
+aligned_gap_size(struct dev_dax *dev_dax, resource_size_t *start,
+		 resource_size_t end)
+{
+	resource_size_t aligned_start = ALIGN(*start, dev_dax_min_align(dev_dax));
+	resource_size_t size;
+
+	if (aligned_start < *start || aligned_start > end)
+		return 0;
+
+	size = ALIGN_DOWN(end - aligned_start + 1, dev_dax_min_align(dev_dax));
+	if (!size)
+		return 0;
+
+	*start = aligned_start;
+	return size;
+}
+
 static int alloc_dev_dax_range(struct dev_dax *dev_dax, u64 start,
 		resource_size_t size)
 {
@@ -870,6 +908,9 @@ static int alloc_dev_dax_range(struct dev_dax *dev_dax, u64 start,
 		return 0;
 	}
 
+	if (!range_is_aligned(dev_dax, start, size))
+		return -EINVAL;
+
 	alloc = __request_region(res, start, size, dev_name(dev), 0);
 	if (!alloc)
 		return -ENOMEM;
@@ -923,6 +964,9 @@ static int adjust_dev_dax_range(struct dev_dax *dev_dax, struct resource *res, r
 	if (dev_WARN_ONCE(dev, !size, "deletion is handled by dev_dax_shrink\n"))
 		return -EINVAL;
 
+	if (!range_is_aligned(dev_dax, range->start, size))
+		return -EINVAL;
+
 	rc = adjust_resource(res, range->start, size);
 	if (rc)
 		return rc;
@@ -955,15 +999,6 @@ static ssize_t size_show(struct device *dev,
 	return sysfs_emit(buf, "%llu\n", size);
 }
 
-static bool alloc_is_aligned(struct dev_dax *dev_dax, resource_size_t size)
-{
-	/*
-	 * The minimum mapping granularity for a device instance is a
-	 * single subsection, unless the arch says otherwise.
-	 */
-	return IS_ALIGNED(size, max_t(unsigned long, dev_dax->align, memremap_compat_align()));
-}
-
 static int dev_dax_shrink(struct dev_dax *dev_dax, resource_size_t size)
 {
 	resource_size_t to_shrink = dev_dax_size(dev_dax) - size;
@@ -1030,23 +1065,46 @@ static bool adjust_ok(struct dev_dax *dev_dax, struct resource *res)
 	return true;
 }
 
+static resource_size_t
+dax_region_aligned_avail_size(struct dax_region *dax_region,
+			      struct dev_dax *dev_dax)
+{
+	struct resource *region_res = &dax_region->res;
+	resource_size_t start = region_res->start;
+	resource_size_t avail = 0;
+	struct resource *res;
+
+	lockdep_assert_held_write(&dax_region_rwsem);
+
+	for_each_dax_region_resource(dax_region, res) {
+		if (res->start > start) {
+			resource_size_t gap_start = start;
+
+			avail += aligned_gap_size(dev_dax, &gap_start,
+					res->start - 1);
+		}
+		start = res->end + 1;
+	}
+	if (start <= region_res->end)
+		avail += aligned_gap_size(dev_dax, &start, region_res->end);
+
+	return avail;
+}
+
 static ssize_t dev_dax_resize(struct dax_region *dax_region,
 		struct dev_dax *dev_dax, resource_size_t size)
 {
-	resource_size_t avail = dax_region_avail_size(dax_region), to_alloc;
 	resource_size_t dev_size = dev_dax_size(dev_dax);
 	struct resource *region_res = &dax_region->res;
 	struct device *dev = &dev_dax->dev;
 	struct resource *res, *first;
-	resource_size_t alloc = 0;
+	resource_size_t alloc, to_alloc;
 	int rc;
 
 	if (dev->driver)
 		return -EBUSY;
 	if (size == dev_size)
 		return 0;
-	if (size > dev_size && size - dev_size > avail)
-		return -ENOSPC;
 	if (size < dev_size)
 		return dev_dax_shrink(dev_dax, size);
 
@@ -1054,6 +1112,8 @@ static ssize_t dev_dax_resize(struct dax_region *dax_region,
 	if (dev_WARN_ONCE(dev, !alloc_is_aligned(dev_dax, to_alloc),
 			"resize of %pa misaligned\n", &to_alloc))
 		return -ENXIO;
+	if (to_alloc > dax_region_aligned_avail_size(dax_region, dev_dax))
+		return -ENOSPC;
 
 	/*
 	 * Expand the device into the unused portion of the region. This
@@ -1062,37 +1122,51 @@ static ssize_t dev_dax_resize(struct dax_region *dax_region,
 	 */
 retry:
 	first = region_res->child;
-	if (!first)
-		return alloc_dev_dax_range(dev_dax, dax_region->res.start, to_alloc);
+	if (!first) {
+		resource_size_t start = region_res->start;
+
+		alloc = aligned_gap_size(dev_dax, &start, region_res->end);
+		return alloc_dev_dax_range(dev_dax, start, min(alloc, to_alloc));
+	}
 
 	rc = -ENOSPC;
 	for (res = first; res; res = res->sibling) {
 		struct resource *next = res->sibling;
+		resource_size_t start, end;
 
 		/* space at the beginning of the region */
 		if (res == first && res->start > dax_region->res.start) {
-			alloc = min(res->start - dax_region->res.start, to_alloc);
-			rc = alloc_dev_dax_range(dev_dax, dax_region->res.start, alloc);
-			break;
+			start = dax_region->res.start;
+			end = res->start - 1;
+			alloc = min(aligned_gap_size(dev_dax, &start, end), to_alloc);
+			if (alloc) {
+				rc = alloc_dev_dax_range(dev_dax, start, alloc);
+				break;
+			}
 		}
 
-		alloc = 0;
 		/* space between allocations */
-		if (next && next->start > res->end + 1)
-			alloc = min(next->start - (res->end + 1), to_alloc);
-
-		/* space at the end of the region */
-		if (!alloc && !next && res->end < region_res->end)
-			alloc = min(region_res->end - res->end, to_alloc);
+		if (next) {
+			if (next->start <= res->end + 1)
+				continue;
+			end = next->start - 1;
+		} else {
+			/* space at the end of the region */
+			if (res->end >= region_res->end)
+				continue;
+			end = region_res->end;
+		}
 
+		start = res->end + 1;
+		alloc = min(aligned_gap_size(dev_dax, &start, end), to_alloc);
 		if (!alloc)
 			continue;
 
-		if (adjust_ok(dev_dax, res)) {
+		if (start == res->end + 1 && adjust_ok(dev_dax, res)) {
 			rc = adjust_dev_dax_range(dev_dax, res, resource_size(res) + alloc);
 			break;
 		}
-		rc = alloc_dev_dax_range(dev_dax, res->end + 1, alloc);
+		rc = alloc_dev_dax_range(dev_dax, start, alloc);
 		break;
 	}
 	if (rc)
@@ -1115,11 +1189,6 @@ static ssize_t size_store(struct device *dev, struct device_attribute *attr,
 	if (rc)
 		return rc;
 
-	if (!alloc_is_aligned(dev_dax, val)) {
-		dev_dbg(dev, "%s: size: %lld misaligned\n", __func__, val);
-		return -EINVAL;
-	}
-
 	rc = down_write_killable(&dax_region_rwsem);
 	if (rc)
 		return rc;
@@ -1130,6 +1199,11 @@ static ssize_t size_store(struct device *dev, struct device_attribute *attr,
 	rc = down_write_killable(&dax_dev_rwsem);
 	if (rc)
 		goto err_dev;
+	if (!alloc_is_aligned(dev_dax, val)) {
+		dev_dbg(dev, "%s: size: %lld misaligned\n", __func__, val);
+		rc = -EINVAL;
+		goto err_dev;
+	}
 
 	rc = dev_dax_resize(dax_region, dev_dax, val);
 
@@ -1228,9 +1302,9 @@ static ssize_t dev_dax_validate_align(struct dev_dax *dev_dax)
 	int i;
 
 	for (i = 0; i < dev_dax->nr_range; i++) {
-		size_t len = range_len(&dev_dax->ranges[i].range);
+		struct range *range = &dev_dax->ranges[i].range;
 
-		if (!alloc_is_aligned(dev_dax, len)) {
+		if (!range_is_aligned(dev_dax, range->start, range_len(range))) {
 			dev_dbg(dev, "%s: align %u invalid for range %d\n",
 				__func__, dev_dax->align, i);
 			return -EINVAL;
@@ -1468,6 +1542,7 @@ static struct dev_dax *__devm_create_dev_dax(struct dev_dax_data *data)
 		return ERR_PTR(-ENOMEM);
 
 	dev_dax->region = dax_region;
+	dev_dax->align = dax_region->align;
 	if (is_static(dax_region)) {
 		if (dev_WARN_ONCE(parent, data->id < 0,
 				"dynamic id specified to static region\n")) {
@@ -1526,7 +1601,6 @@ static struct dev_dax *__devm_create_dev_dax(struct dev_dax_data *data)
 
 	dev_dax->dax_dev = dax_dev;
 	dev_dax->target_node = dax_region->target_node;
-	dev_dax->align = dax_region->align;
 	ida_init(&dev_dax->ida);
 
 	dev_dax->memmap_on_memory = data->memmap_on_memory;
-- 
2.54.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 1/2] dax/bus: fix mapping attribute error reporting
  2026-09-24  2:50 ` [PATCH v3 1/2] dax/bus: fix mapping attribute error reporting Muchun Song
@ 2026-10-13  0:13   ` Alison Schofield
  2026-10-13  6:27     ` Muchun Song
  2026-10-13  2:31   ` jianyungao89
  1 sibling, 1 reply; 7+ messages in thread
From: Alison Schofield @ 2026-10-13  0:13 UTC (permalink / raw)
  To: Muchun Song
  Cc: Dan Williams, Vishal Verma, Dave Jiang, Andrew Morton,
	Joao Martins, nvdimm, linux-cxl, linux-kernel, muchun.song

On Thu, Sep 24, 2026 at 10:50:34AM +0800, Muchun Song wrote:
> After the DAX configuration locking was converted to rwsems, successful
> lock acquisition leaves rc set to zero in mapping_store(). Two error
> paths can return this stale value: an unbound region driver and a
> misaligned range size. The sysfs write therefore reports success without
> allocating the requested range.
> 
> Return -ENXIO when the region driver is not bound and -EINVAL when the
> range size is misaligned.

Reviewed-by: Alison Schofield <alison.schofield@intel.com>

Will modify subject line upon applying like so:
dax/bus: Return errors for invalid mapping requests

> 
> Fixes: c05ae9d85b47 ("dax/bus.c: replace driver-core lock usage by a local rwsem")
> Assisted-by: LLM
> Signed-off-by: Muchun Song <songmuchun@bytedance.com>
> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> ---
> v3:
> - Collect Reviewed-by from Dave Jiang
> 
> v2:
> - Return explicit errors before Device DAX range allocation
>   (suggested by Dave Jiang)
> - Move the patch before range alignment validation for independent
>   backports (suggested by Dave Jiang)
> ---
>  drivers/dax/bus.c | 8 ++++++--
>  1 file changed, 6 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/dax/bus.c b/drivers/dax/bus.c
> index b809e1a264af..e40c25401cf0 100644
> --- a/drivers/dax/bus.c
> +++ b/drivers/dax/bus.c
> @@ -1192,7 +1192,7 @@ static ssize_t mapping_store(struct device *dev, struct device_attribute *attr,
>  		return rc;
>  	if (!dax_region->dev->driver) {
>  		up_write(&dax_region_rwsem);
> -		return rc;
> +		return -ENXIO;
>  	}
>  	rc = down_write_killable(&dax_dev_rwsem);
>  	if (rc) {
> @@ -1201,8 +1201,12 @@ static ssize_t mapping_store(struct device *dev, struct device_attribute *attr,
>  	}
>  
>  	to_alloc = range_len(&r);
> -	if (alloc_is_aligned(dev_dax, to_alloc))
> +	if (!alloc_is_aligned(dev_dax, to_alloc)) {
> +		dev_dbg(dev, "%s: size: %zu misaligned\n", __func__, to_alloc);
> +		rc = -EINVAL;
> +	} else {
>  		rc = alloc_dev_dax_range(dev_dax, r.start, to_alloc);
> +	}
>  	up_write(&dax_dev_rwsem);
>  	up_write(&dax_region_rwsem);
>  
> -- 
> 2.54.0
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 2/2] dax/bus: fix Device DAX range alignment validation
  2026-09-24  2:50 ` [PATCH v3 2/2] dax/bus: fix Device DAX range alignment validation Muchun Song
@ 2026-10-13  0:20   ` Alison Schofield
  0 siblings, 0 replies; 7+ messages in thread
From: Alison Schofield @ 2026-10-13  0:20 UTC (permalink / raw)
  To: Muchun Song
  Cc: Dan Williams, Vishal Verma, Dave Jiang, Andrew Morton,
	Joao Martins, nvdimm, linux-cxl, linux-kernel, muchun.song

On Thu, Sep 24, 2026 at 10:50:35AM +0800, Muchun Song wrote:
> dev_dax->align describes the page size used by a Device DAX mapping.
> Both the start and size of every range must therefore be aligned to it;
> otherwise the starting PFN cannot represent a naturally aligned page of
> that size.
> 
> Only range sizes are currently validated. A dynamic device can therefore
> select a large-page alignment and allocate a range whose start is not
> naturally aligned to that page size. The device binds successfully, but a
> subsequent write to a userspace mapping may trigger a kernel panic.
> 
> The automatic resize path can also split a size-aligned request across
> arbitrary free gaps. When devices with different alignments fragment a
> region, this can extend a range by less than its alignment. A later
> allocation then fails, leaving the failed resize partially applied.
> 
> Validate both the start and size of allocated and adjusted ranges. Make
> the resize path account only for usable aligned space before changing any
> ranges, and skip gaps that cannot satisfy the device alignment. Initialize
> the device alignment before allocating its initial range so that all
> allocations use the same validation. Perform size validation under the
> same locks as alignment updates so the alignment cannot change before
> resizing begins.
> 
> A mapping with an unaligned start is now rejected with -EINVAL, while a
> naturally aligned mapping still binds successfully.

Hi Muchun,

The commit message could be condensed. I think the two failure scenarios and
the changes needed to address them are sufficient.Implementation details
are excessive.

But before that, need to address something else, see below-

> 
> Fixes: 6d82120f4156 ("device-dax: add an 'align' attribute")
> Assisted-by: LLM
> Signed-off-by: Muchun Song <songmuchun@bytedance.com>
> ---
> v3:
> - Serialize size alignment validation with alignment updates to avoid a
>   partial shrink after a concurrent alignment change (reported by Sashiko)
> - Document the size validation serialization in the commit message
> 
> v2:
> - Keep the alloc_is_aligned() name to avoid unrelated helper renaming
>   (suggested by Dave Jiang)
> - Move this patch after the mapping error reporting fix for independent
>   backports (suggested by Dave Jiang)
> ---
>  drivers/dax/bus.c | 144 +++++++++++++++++++++++++++++++++++-----------
>  1 file changed, 109 insertions(+), 35 deletions(-)
> 
> diff --git a/drivers/dax/bus.c b/drivers/dax/bus.c

snip


> @@ -1468,6 +1542,7 @@ static struct dev_dax *__devm_create_dev_dax(struct dev_dax_data *data)
>  		return ERR_PTR(-ENOMEM);
>  
>  	dev_dax->region = dax_region;
> +	dev_dax->align = dax_region->align;


Moving this assignment means that initial allocations for static
pmem regions now go through the new range_is_aligned() check.

I'm concerned this may reject existing namespaces with 4K alignment.
nd_pfn_validate() doesn't require the data offset to be aligned to
memremap_compat_align(), and older namespace formats may have offsets
that don't meet that requirement.

Can you check whether an existing namespace with such an offset
would still probe successfully after this change?

I'm also wondering whether the initial range needs to satisfy
memremap_compat_align(), or whether checking dev_dax->align is
sufficient here.

Have you also tested the static pmem Device DAX path, particularly
with namespaces created by older kernels? The reproducer described
in the cover letter addresses the alignment failure, but I'd like
to make sure we aren't introducing a regression for existing
namespaces.

-- Alison



>  	if (is_static(dax_region)) {
>  		if (dev_WARN_ONCE(parent, data->id < 0,
>  				"dynamic id specified to static region\n")) {
> @@ -1526,7 +1601,6 @@ static struct dev_dax *__devm_create_dev_dax(struct dev_dax_data *data)
>  
>  	dev_dax->dax_dev = dax_dev;
>  	dev_dax->target_node = dax_region->target_node;
> -	dev_dax->align = dax_region->align;
>  	ida_init(&dev_dax->ida);
>  
>  	dev_dax->memmap_on_memory = data->memmap_on_memory;
> -- 
> 2.54.0
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 1/2] dax/bus: fix mapping attribute error reporting
  2026-09-24  2:50 ` [PATCH v3 1/2] dax/bus: fix mapping attribute error reporting Muchun Song
  2026-10-13  0:13   ` Alison Schofield
@ 2026-10-13  2:31   ` jianyungao89
  1 sibling, 0 replies; 7+ messages in thread
From: jianyungao89 @ 2026-10-13  2:31 UTC (permalink / raw)
  To: songmuchun
  Cc: akpm, alison.schofield, dave.jiang, djbw, joao.m.martins,
	linux-cxl, linux-kernel, muchun.song, nvdimm, vishal.l.verma,
	Jianyun Gao

From: Jianyun Gao <jianyungao89@gmail.com>

This patch also fixes the mapping_store() error return issue I reported.
The fix looks correct to me.

Reviewed-by: Jianyun Gao <jianyungao89@gmail.com>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 1/2] dax/bus: fix mapping attribute error reporting
  2026-10-13  0:13   ` Alison Schofield
@ 2026-10-13  6:27     ` Muchun Song
  0 siblings, 0 replies; 7+ messages in thread
From: Muchun Song @ 2026-10-13  6:27 UTC (permalink / raw)
  To: Alison Schofield
  Cc: Muchun Song, Dan Williams, Vishal Verma, Dave Jiang,
	Andrew Morton, Joao Martins, nvdimm, linux-cxl, linux-kernel



> On Oct 13, 2026, at 08:13, Alison Schofield <alison.schofield@intel.com> wrote:
> 
> On Thu, Sep 24, 2026 at 10:50:34AM +0800, Muchun Song wrote:
>> After the DAX configuration locking was converted to rwsems, successful
>> lock acquisition leaves rc set to zero in mapping_store(). Two error
>> paths can return this stale value: an unbound region driver and a
>> misaligned range size. The sysfs write therefore reports success without
>> allocating the requested range.
>> 
>> Return -ENXIO when the region driver is not bound and -EINVAL when the
>> range size is misaligned.
> 
> Reviewed-by: Alison Schofield <alison.schofield@intel.com>

Thanks.

> 
> Will modify subject line upon applying like so:
> dax/bus: Return errors for invalid mapping requests

No problem.

Thanks,
Muchun

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-10-13  6:27 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-24  2:50 [PATCH v3 0/2] dax: Fix Device DAX range allocation validation Muchun Song
2026-09-24  2:50 ` [PATCH v3 1/2] dax/bus: fix mapping attribute error reporting Muchun Song
2026-10-13  0:13   ` Alison Schofield
2026-10-13  6:27     ` Muchun Song
2026-10-13  2:31   ` jianyungao89
2026-09-24  2:50 ` [PATCH v3 2/2] dax/bus: fix Device DAX range alignment validation Muchun Song
2026-10-13  0:20   ` Alison Schofield

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®