Re: [PATCH v11 16/31] cxl/extent: Validate DC extent partition

Dave Jiang <[email protected]>
Newsgroups dev.linux.lists.nvdimm,org.kernel.vger.linux-cxl,org.kernel.vger.linux-kernel
Message-ID <[email protected]>

On 6/25/26 4:04 AM, Anisa Su wrote:
> From: Ira Weiny <[email protected]>
> 
> Extend cxl_validate_extent() — the per-extent check of the add pipeline
> to check partition membership.
> 
> Resolves an extent's DPA to its containing DC partition.  Sharability is
> a property of the partition (part->shareable), taken from its CDAT DSMAS
> entry.
> 
> An extent from a sharable partition must carry a non-null tag, since hosts
> sharing the allocation key on that tag.  A null tag there is a device
> firmware bug; reject the extent.
> 
> shared_extn_seq validation is checked in cxl_check_group_seq() once the
> whole tag group is collected.
> 
> Based on patches by John Groves.
> 
> Signed-off-by: Ira Weiny <[email protected]>
> Signed-off-by: John Groves <[email protected]>
> Signed-off-by: Anisa Su <[email protected]>

Reviewed-by: Dave Jiang <[email protected]>

> 
> ---
> Changes:
> 1. cxl_extent_dc_partition() declared static — it is only called
>  from extent.c at this point.  A subsequent commit ("cxl/mem: Enforce
>  tag-group semantics") drops static and adds the declaration to core.h
>  when mbox.c starts calling it.
> 2. In cxl_validate_extent(), declare the local uuid as a struct
>  (uuid_t uuid) and fill it via import_uuid(&uuid, extent->uuid) instead
>  of casting (uuid_t *)extent->uuid.
> ---
>  drivers/cxl/core/extent.c | 85 +++++++++++++++++++++++++++++++++++++--
>  1 file changed, 82 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/cxl/core/extent.c b/drivers/cxl/core/extent.c
> index 6e67e787d14d..2e770c5279c2 100644
> --- a/drivers/cxl/core/extent.c
> +++ b/drivers/cxl/core/extent.c
> @@ -76,11 +76,67 @@ alloc_tag_group(struct cxl_dax_region *cxlr_dax, uuid_t *uuid)
>  	return no_free_ptr(group);
>  }
>  
> +/*
> + * Find the DC (Dynamic Capacity) partition that fully contains @ext_range,
> + * or NULL if the extent falls outside every DC partition on this memdev.
> + * The returned pointer is owned by mds->cxlds.part[] and lives for the
> + * lifetime of the memdev.
> + */
> +static const struct cxl_dpa_partition *
> +cxl_extent_dc_partition(struct cxl_memdev_state *mds,
> +			struct cxl_extent *extent,
> +			struct range *ext_range)
> +{
> +	struct cxl_dev_state *cxlds = &mds->cxlds;
> +	struct device *dev = mds->cxlds.dev;
> +
> +	/*
> +	 * A device-side error could cause end < start, which range_contains()
> +	 * would treat as contained in any partition.
> +	 */
> +	if (ext_range->end < ext_range->start) {
> +		dev_err_ratelimited(dev,
> +				    "DC extent DPA %pra (%pU) has invalid length (firmware bug)\n",
> +				    ext_range, extent->uuid);
> +		return NULL;
> +	}
> +
> +	for (int i = 0; i < cxlds->nr_partitions; i++) {
> +		struct cxl_dpa_partition *part = &cxlds->part[i];
> +		struct range partition_range = {
> +			.start = part->res.start,
> +			.end = part->res.end,
> +		};
> +
> +		if (part->mode != CXL_PARTMODE_DYNAMIC_RAM_1)
> +			continue;
> +
> +		if (range_contains(&partition_range, ext_range)) {
> +			dev_dbg(dev, "DC extent DPA %pra (DCR:%pra)(%pU)\n",
> +				ext_range, &partition_range, extent->uuid);
> +			return part;
> +		}
> +	}
> +
> +	dev_err_ratelimited(dev,
> +			    "DC extent DPA %pra (%pU) is not in a valid DC partition\n",
> +			    ext_range, extent->uuid);
> +	return NULL;
> +}
> +
>  /*
>   * Stage 1 of the add pipeline: pure, no allocation.  Resolve the extent
> - * to its region/endpoint decoder and ext_range, and verify the range
> - * fits in the resolved endpoint decoder's DPA resource.  Further
> - * per-extent invariants layer into this function in subsequent commits.
> + * to its region/endpoint decoder and ext_range, and enforce every
> + * per-extent invariant the device must satisfy:
> + *
> + *   - DPA falls inside a Dynamic Capacity partition (cxl_extent_dc_partition).
> + *   - Sharability is a property of the partition (part->shareable), not of
> + *     the shared_extn_seq value: a sharable-partition extent must carry a
> + *     non-null tag, and a non-sharable-partition extent must leave
> + *     shared_extn_seq reserved (zero).  The dense 0..n-1 numbering within a
> + *     sharable tag group is validated separately (cxl_check_group_seq()).
> + *   - DPA resolves to an endpoint decoder attached to a region.
> + *   - The extent's range is fully contained in that ED's DPA resource.
>   *
>   * Caller must hold cxl_rwsem.region for read (cxl_dpa_to_region()).
>   * On success, @out_cxled / @out_cxlr_dax / @out_ext_range carry the
> @@ -94,6 +150,8 @@ static int cxl_validate_extent(struct cxl_memdev_state *mds,
>  {
>  	u64 start_dpa = le64_to_cpu(extent->start_dpa);
>  	struct cxl_memdev *cxlmd = mds->cxlds.cxlmd;
> +	struct device *dev = mds->cxlds.dev;
> +	const struct cxl_dpa_partition *part;
>  	struct cxl_endpoint_decoder *cxled;
>  	struct cxl_region *cxlr;
>  	struct range ext_range = (struct range) {
> @@ -101,6 +159,27 @@ static int cxl_validate_extent(struct cxl_memdev_state *mds,
>  		.end = start_dpa + le64_to_cpu(extent->length) - 1,
>  	};
>  	struct range ed_range;
> +	uuid_t uuid;
> +
> +	import_uuid(&uuid, extent->uuid);
> +
> +	part = cxl_extent_dc_partition(mds, extent, &ext_range);
> +	if (!part)
> +		return -ENXIO;
> +
> +	if (part->shareable) {
> +		if (uuid_is_null(&uuid)) {
> +			dev_err_ratelimited(dev,
> +				"DC extent DPA %pra: sharable-partition extent has null tag (firmware bug)\n",
> +				&ext_range);
> +			return -ENXIO;
> +		}
> +	} else if (le16_to_cpu(extent->shared_extn_seq)) {
> +		dev_err_ratelimited(dev,
> +			"DC extent DPA %pra (%pU): non-sharable partition but shared_extn_seq=%u (firmware bug)\n",
> +			&ext_range, &uuid, le16_to_cpu(extent->shared_extn_seq));
> +		return -ENXIO;
> +	}
>  
>  	cxlr = cxl_dpa_to_region(cxlmd, start_dpa, &cxled);
>  	if (!cxlr || !cxlr->cxlr_dax)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.