On 5/23/26 2:50 AM, Anisa Su wrote:
> From: Ira Weiny <[email protected]>
> 
> cxl_test provides a good way to ensure quick smoke and regression
> testing.  The complexity of DCD and the new sparse DAX regions
> required to use them benefits greatly with a series of smoke tests.
> 
> The only part of the kernel stack which must be bypassed is the actual
> irq of DCD events.  However, the event processing itself can be tested
> via cxl_test calling directly into the event processing.
> 
> In this way the rest of the stack; management of sparse regions, the
> extent device lifetimes, and the dax device operations can be tested.
> 
> Add Dynamic Capacity Device tests for kernels which have DCD support.
> 
> Signed-off-by: Ira Weiny <[email protected]>
> Signed-off-by: Anisa Su <[email protected]>

A nit below. Otherwise

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


> 
> ---
> Changes:
> [anisa: align tests with kernel DCD redesign + add sharable coverage]
> 
> Rewrite tests against the post-redesign kernel (uuid sysfs claim,
> sparse size-grow rejection, tag-group atomic release, cross-More
> uniqueness):
> 
>   - Use real UUID strings; route untagged claims via --uuid "0" so
>     daxctl exercises the kernel uuid_store path end to end.
>   - Pre-existing-extent test handles the tagged pre2_ext (deadbeef)
>     separately from the untagged pre_ext.
>   - Spanning / aggregation tests drive both extents in one More-chain:
>     cross-event tagged adds are dropped by the cross-More uniqueness
>     gate, and untagged events become independent dax_resources so
>     only one is claimed per --uuid "0".
>   - test_dax_device_ops asserts that sparse size grow returns
>     -EOPNOTSUPP after a shrink (real grow path is --uuid only).
>   - test_reject_overlapping math now produces an actual overlap
>     inside the DC region (the prior arithmetic landed past the end).
> 
> Add coverage for new validators:
>   - test_uuid_no_match / test_uuid_no_match_seed_intact
>   - test_uuid_show (reads back the dax-dev uuid sysfs attribute)
>   - test_cross_more_uniqueness (rejects tag reuse across More-chains)
>   - test_alignment_rejection (rejects misaligned extents)
> 
> Sharable-partition coverage (test_shared_extent_inject,
> test_seq_integrity_gap) is routed at runtime to a dedicated mock
> memdev that tools/testing/cxl stamps with serial 0xDCDC; the script
> enumerates both regimes from one cxl_test module load.
> 
> Localize positional-arg assignments in every helper so functions
> no longer clobber caller globals (the previous behavior leaked
> the sharable memdev into later tests).
> 
> Update inject_extent to optionally pass shared_extn_seq (5th arg)
> and remove_extent to carry the tag (now required by the mock's
> delete sysfs).  Add inject_shared_extent for dc_inject_shared_extent.
> ---
>  test/cxl-dcd.sh  | 1267 ++++++++++++++++++++++++++++++++++++++++++++++
>  test/meson.build |    2 +
>  2 files changed, 1269 insertions(+)
>  create mode 100644 test/cxl-dcd.sh
> 
> diff --git a/test/cxl-dcd.sh b/test/cxl-dcd.sh
> new file mode 100644
> index 0000000..3194b00
> --- /dev/null
> +++ b/test/cxl-dcd.sh
> @@ -0,0 +1,1267 @@
> +#!/bin/bash
> +# SPDX-License-Identifier: GPL-2.0
> +# Copyright (C) 2024 Intel Corporation. All rights reserved.
> +
> +. "$(dirname "$0")/common"
> +
> +rc=77
> +set -ex
> +
> +trap 'err $LINENO' ERR
> +
> +check_prereq "jq"
> +
> +rc=1
> +
> +dev_path="/sys/bus/platform/devices"
> +cxl_path="/sys/bus/cxl/devices"
> +
> +# test extent tags (UUIDs).  pre_ext_tag matches the second pre-injected
> +# extent tag in the kernel mock (tools/testing/cxl/test/mem.c).
> +pre_ext_tag="deadbeef-cafe-baad-f00d-fedcba987654"
> +test_tag_a="11111111-1111-1111-1111-111111111111"
> +test_tag_b="22222222-2222-2222-2222-222222222222"
> +unknown_tag="33333333-3333-3333-3333-333333333333"
> +
> +#
> +# The test devices have 2G of non DC capacity.  A single DC reagion of 1G is
> +# added beyond that.
> +#
> +# The testing centers around 3 extents.  Two are "pre-existing" on test load
> +# called pre-ext and pre2-ext.  The other is created within this script alone
> +# called base.
> +
> +#
> +# | 2G non- |      DC region (1G)                                   |
> +# |  DC cap |                                                       |
> +# |  ...    |-------------------------------------------------------|
> +# |         |--------|       |----------|      |----------|         |
> +# |         | (base) |       |(pre-ext) |      |(pre2-ext)|         |
> +
> +dra_size=""
> +
> +base_dpa=0x80000000
> +
> +# base extent at dpa 2G - 64M long
> +base_ext_offset=0x0
> +base_ext_dpa=$(($base_dpa + $base_ext_offset))
> +base_ext_length=0x4000000
> +
> +# pre existing extent base + 128M, 64M length
> +# 0x00000088000000-0x0000008bffffff
> +pre_ext_offset=0x8000000
> +pre_ext_dpa=$(($base_dpa + $pre_ext_offset))
> +pre_ext_length=0x4000000
> +
> +# pre2 existing extent base + 256M, 64M length
> +# 0x00000090000000-0x00000093ffffff
> +pre2_ext_offset=0x10000000
> +pre2_ext_dpa=$(($base_dpa + $pre2_ext_offset))
> +pre2_ext_length=0x4000000
> +
> +mem=""
> +bus=""
> +device=""
> +decoder=""
> +
> +# ========================================================================
> +# Support functions
> +# ========================================================================
> +
> +create_dcd_region()
> +{
> +     local mem="$1"
> +     local decoder="$2"
> +     local reg_size_string=""
> +     local region
> +     if [ "$3" != "" ]; then
> +             reg_size_string="-s $3"
> +     fi
> +
> +     # create region
> +     region=$($CXL create-region -t dynamic_ram_a -d "$decoder" -m "$mem" 
> ${reg_size_string} | jq -r ".region")
> +
> +     if [[ ! $region ]]; then
> +             echo "create-region failed for $decoder / $mem"
> +             err "$LINENO"
> +     fi
> +
> +     echo ${region}
> +}
> +
> +check_region()
> +{
> +     local search=$1
> +     local region_size=$2
> +     local result
> +
> +     result=$($CXL list -r "$search" | jq -r ".[].region")
> +     if [ "$result" != "$search" ]; then
> +             echo "check region failed to find $search"
> +             err "$LINENO"
> +     fi
> +
> +     result=$($CXL list -r "$search" | jq -r ".[].size")
> +     if [ "$result" != "$region_size" ]; then
> +             echo "check region failed invalid size $result != $region_size"
> +             err "$LINENO"
> +     fi
> +}
> +
> +check_not_region()
> +{
> +     local search=$1
> +     local result
> +
> +     result=$($CXL list -r "$search" | jq -r ".[].region")
> +     if [ "$result" == "$search" ]; then
> +             echo "check not region failed; $search found"
> +             err "$LINENO"
> +     fi
> +}
> +
> +destroy_region()
> +{
> +     local region=$1
> +     $CXL disable-region $region
> +     $CXL destroy-region $region
> +}
> +
> +inject_extent()
> +{
> +     local device="$1"
> +     local dpa="$2"
> +     local length="$3"
> +     local tag="$4"
> +     local seq="$6"
> +     local more="0"
> +     local cmd
> +
> +     if [ "$5" != "" ]; then
> +             more="1"
> +     fi
> +
> +     cmd="${dpa}:${length}:${tag}:${more}"
> +     if [ -n "$seq" ]; then
> +             cmd="${cmd}:${seq}"
> +     fi
> +     echo ${cmd} > "${dev_path}/${device}/dc_inject_extent"
> +}
> +
> +# Shared-extent inject targets a *sharable* DC partition.  The mock
> +# stamps the sentinel serial onto a single cxl_mem instance, and the
> +# script routes shared-extent tests to that memdev via $sharable_device.
> +inject_shared_extent()
> +{
> +     local device="$1"
> +     local dpa="$2"
> +     local length="$3"
> +     local tag="$4"
> +     local seq="$6"
> +     local more="0"
> +     local cmd
> +
> +     if [ "$5" != "" ]; then
> +             more="1"
> +     fi
> +
> +     cmd="${dpa}:${length}:${tag}:${more}"
> +     if [ -n "$seq" ]; then
> +             cmd="${cmd}:${seq}"
> +     fi
> +     echo ${cmd} > "${dev_path}/${device}/dc_inject_shared_extent"
> +}
> +
> +remove_extent()
> +{
> +     local device="$1"
> +     local dpa="$2"
> +     local length="$3"
> +     local tag="$4"
> +
> +     echo ${dpa}:${length}:${tag} > "${dev_path}/${device}/dc_del_extent"
> +}
> +
> +create_dax_dev()
> +{
> +     local reg="$1"
> +     local dax_dev
> +
> +     dax_dev=$($DAXCTL create-device -r $reg | jq -er '.[].chardev')
> +
> +     echo ${dax_dev}
> +}
> +
> +create_dax_dev_with_uuid()
> +{
> +     local reg="$1"
> +     local uuid="$2"
> +     local dax_dev
> +
> +     dax_dev=$($DAXCTL create-device -r $reg --uuid "$uuid" \
> +                     | jq -er '.[].chardev')
> +
> +     echo ${dax_dev}
> +}
> +
> +fail_create_dax_dev_with_uuid()
> +{
> +     local reg="$1"
> +     local uuid="$2"
> +     local create_rc
> +
> +     set +e
> +     $DAXCTL create-device -r $reg --uuid "$uuid"
> +     create_rc=$?
> +     set -e
> +     if [ $create_rc -eq 0 ]; then
> +             echo "FAIL create-device with uuid $uuid unexpectedly succeeded"
> +             err "$LINENO"
> +     fi
> +}
> +
> +fail_create_dax_dev()
> +{
> +     local reg="$1"
> +     local result
> +
> +     set +e
> +     result=$($DAXCTL create-device -r $reg)
> +     set -e
> +     if [ "$result" == "0" ]; then
> +             echo "FAIL device created"
> +             err "$LINENO"
> +     fi
> +}
> +
> +# Try to resize a sparse dax device via reconfigure -s; must fail because
> +# the kernel rejects any non-zero size_store on a dynamic dax region with
> +# -EOPNOTSUPP (drivers/dax/bus.c:dev_dax_resize).  The only valid resize is
> +# to size 0, which is the path `daxctl destroy-device` takes.
> +fail_resize_dax_dev()
> +{
> +     local dev="$1"
> +     local new_size="$2"
> +     local resize_rc
> +
> +     $DAXCTL disable-device $dev
> +     set +e
> +     $DAXCTL reconfigure-device $dev -s $new_size
> +     resize_rc=$?
> +     set -e
> +     # Re-enable regardless so subsequent checks/cleanup work.
> +     $DAXCTL enable-device $dev
> +     if [ $resize_rc -eq 0 ]; then
> +             echo "FAIL resize of $dev to $new_size unexpectedly succeeded"
> +             err "$LINENO"
> +     fi
> +}
> +
> +# Read /sys/bus/dax/devices/<dax>/uuid and compare to $expected.  "0"
> +# matches the null UUID (kernel emits "0\n" when the resource is empty,
> +# untagged, or non-DCD).
> +check_dax_uuid()
> +{
> +     local dax_dev="$1"
> +     local expected="$2"
> +     local uuid_path got want
> +
> +     uuid_path="/sys/bus/dax/devices/${dax_dev}/uuid"
> +     if [ ! -e "$uuid_path" ]; then
> +             echo "FAIL no uuid attribute at $uuid_path"
> +             err "$LINENO"
> +     fi
> +     got=$(cat "$uuid_path" | tr -d '[:space:]')
> +     want=$(echo "$expected" | tr -d '[:space:]')
> +     if [ "$got" != "$want" ]; then
> +             echo "FAIL uuid show on $dax_dev: got '$got' want '$want'"
> +             err "$LINENO"
> +     fi
> +}
> +
> +destroy_dax_dev()
> +{
> +     local dev="$1"
> +
> +     $DAXCTL disable-device $dev
> +     $DAXCTL destroy-device $dev
> +}
> +
> +check_dax_dev()
> +{
> +     local search="$1"
> +     local size=$(($2))
> +     local result
> +
> +     result=$($DAXCTL list -d $search | jq -er '.[].chardev')
> +     if [ "$result" != "$search" ]; then
> +             echo "check dax device failed to find $search"
> +             err "$LINENO"
> +     fi
> +     result=$($DAXCTL list -d $search | jq -er '.[].size')
> +     if [ "$result" -ne "$size" ]; then
> +             echo "check dax device failed incorrect size $result; exp $size"
> +             err "$LINENO"
> +     fi
> +}
> +
> +# check that the dax device is not there.
> +check_not_dax_dev()
> +{
> +     local reg="$1"
> +     local search="$2"
> +     local result
> +     result=$($DAXCTL list -r $reg -D | jq -r '.[].chardev')
> +     if [ "$result" == "$search" ]; then
> +             echo "FAIL found $search"
> +             err "$LINENO"
> +     fi
> +}
> +
> +check_extent()
> +{
> +     local region=$1
> +     local offset=$(($2))
> +     local length=$(($3))
> +     local result
> +
> +     result=$($CXL list -r "$region" -N | jq -r ".[].extents[] | 
> select(.offset == ${offset}) | .length")
> +     if [[ $result != $length ]]; then
> +             echo "FAIL region $1 could not find extent @ $offset ($length)"
> +             err "$LINENO"
> +     fi
> +}
> +
> +check_extent_cnt()
> +{
> +     local region=$1
> +     local count=$(($2))
> +     local result
> +
> +     result=$($CXL list -r $region -N | jq -r '.[].extents[].offset' | wc -l)
> +     if [[ $result != $count ]]; then
> +             echo "FAIL region $1: found wrong number of extents $result; 
> expect $count"
> +             err "$LINENO"
> +     fi
> +}
> +
> +
> +# ========================================================================
> +# Tests
> +# ========================================================================
> +
> +# testing pre existing extents must be called first as the extents were 
> created
> +# by cxl-test being loaded.  The mock fixture is one untagged extent at
> +# pre_ext_dpa and one tagged (pre_ext_tag) extent at pre2_ext_dpa, so the
> +# untagged extent is claimed via --uuid "0" and the tagged one via its UUID.
> +test_pre_existing_extents()
> +{
> +     echo ""
> +     echo "Test: pre-existing extents (untagged + tagged)"
> +     echo ""
> +     region=$(create_dcd_region ${mem} ${decoder})
> +
> +     # | 2G non- |      DC region                                        |
> +     # |  DC cap |                                                       |
> +     # |  ...    |-------------------------------------------------------|
> +     # |         |                   |----------|         |----------|   |
> +     # |         |                   |(pre-ext) |         |(pre2-ext)|   |
> +     # |         |                   | untagged |         | tagged   |   |
> +     check_region ${region} ${dra_size}
> +     check_extent ${region} ${pre_ext_offset} ${pre_ext_length}
> +     check_extent ${region} ${pre2_ext_offset} ${pre2_ext_length}
> +
> +     # Untagged claim picks up the untagged pre-extent only
> +     dax_dev_u=$(create_dax_dev_with_uuid ${region} "0")
> +     check_dax_dev ${dax_dev_u} $pre_ext_length
> +
> +     # Tagged claim picks up the tagged pre2-extent
> +     dax_dev_t=$(create_dax_dev_with_uuid ${region} "$pre_ext_tag")
> +     check_dax_dev ${dax_dev_t} $pre2_ext_length
> +
> +     destroy_dax_dev ${dax_dev_u}
> +     destroy_dax_dev ${dax_dev_t}
> +
> +     # Release events must carry the tag identity so cxl_rm_extent's
> +     # uuid_equal lookup matches the right region_extent.
> +     remove_extent ${device} $pre_ext_dpa $pre_ext_length ""
> +     remove_extent ${device} $pre2_ext_dpa $pre2_ext_length "$pre_ext_tag"
> +     check_extent_cnt ${region} 0
> +     destroy_region ${region}
> +     check_not_region ${region}
> +}
> +
> +test_remove_extent_under_dax_device()
> +{
> +     # Remove the pre-created test extent out from under dax device
> +     # stack should hold ref until dax device deleted
> +     echo ""
> +     echo "Test: Remove extent from under DAX dev"
> +     echo ""
> +
> +     region=$(create_dcd_region ${mem} ${decoder})
> +     check_region ${region} ${dra_size}
> +     # | 2G non- |      DC region                                        |
> +     # |  DC cap |                                                       |
> +     # |  ...    |-------------------------------------------------------|
> +     # |         |                                                       |
> +     # |         |                                                       |
> +
> +     
> +     inject_extent ${device} $pre_ext_dpa $pre_ext_length ""
> +     # |         |                   |----------|                        |
> +     # |         |                   |(pre-ext) |                        |
> +     check_extent ${region} ${pre_ext_offset} ${pre_ext_length}
> +
> +     # Sparse seed starts at size 0; --uuid "0" is the only sizing path.
> +     dax_dev=$(create_dax_dev_with_uuid ${region} "0")
> +     # |         |                   |----------|                        |
> +     # |         |                   |(pre-ext) |                        |
> +     # |         |                   | daxX.1   |                        |
> +     check_extent_cnt ${region} 1
> +     remove_extent ${device} $pre_ext_dpa $pre_ext_length ""
> +     # In-use extents are not released (dax-layer EBUSY defers release).
> +     check_dax_dev ${dax_dev} $pre_ext_length
> +
> +     check_extent_cnt ${region} 1
> +     destroy_dax_dev ${dax_dev}
> +     # |         |                   |----------|                        |
> +     # |         |                   |(pre-ext) |                        |
> +     check_not_dax_dev ${region} ${dax_dev}
> +
> +     check_extent_cnt ${region} 1
> +     # Re-issuing the release after the dax device dropped its hold
> +     # completes the deferred release.
> +     remove_extent ${device} $pre_ext_dpa $pre_ext_length ""
> +     # |         |                                                       |
> +     # |         |                                                       |
> +     check_extent_cnt ${region} 0
> +     destroy_region ${region}
> +     check_not_region ${region}
> +}
> +
> +test_remove_extents_in_use()
> +{
> +     echo ""
> +     echo "Test: Remove extents under sparse dax device"
> +     echo ""
> +     # Tagged release events are deferred while a dax device pins the
> +     # tag group; extent count stays at 2.
> +     remove_extent ${device} $base_ext_dpa $base_ext_length "$test_tag_a"
> +     check_extent_cnt ${region} 2
> +     remove_extent ${device} $pre_ext_dpa $pre_ext_length "$test_tag_a"
> +     check_extent_cnt ${region} 2
> +}
> +
> +test_create_dax_dev_spanning_two_extents()
> +{
> +     echo ""
> +     echo "Test: Create dax device spanning 2 extents in a tagged group"
> +     echo ""
> +
> +     region=$(create_dcd_region ${mem} ${decoder})
> +     check_region ${region} ${dra_size}
> +     # | 2G non- |      DC region                                        |
> +     # |  DC cap |                                                       |
> +     # |  ...    |-------------------------------------------------------|
> +     #
> +     # A single dax device spanning two extents is only possible when
> +     # both extents belong to the same tagged More-chain.  Cross-event
> +     # tagged adds are rejected by the cross-More uniqueness gate;
> +     # untagged adds become independent dax_resources and only one is
> +     # claimed per --uuid "0".  Drive both extents in one More-chain:
> +     inject_extent ${device} $pre_ext_dpa $pre_ext_length "$test_tag_a" 1
> +     check_extent_cnt ${region} 0   # held off until More=0 closes chain
> +     inject_extent ${device} $base_ext_dpa $base_ext_length "$test_tag_a"
> +     check_extent ${region} ${pre_ext_offset} ${pre_ext_length}
> +     check_extent ${region} ${base_ext_offset} ${base_ext_length}
> +     # |         |--------|          |----------|                        |
> +     # |         | (base) |          |(pre-ext) |     tag_a              |
> +
> +     check_extent_cnt ${region} 2
> +     dax_dev=$(create_dax_dev_with_uuid ${region} "$test_tag_a")
> +     # |         |--------|          |----------|                        |
> +     # |         | (base) |          |(pre-ext) |                        |
> +     # |         | daxX.1 |          | daxX.1   |                        |
> +
> +     echo "Checking if dev dax is spanning sparse extents"
> +     ext_sum_length="$(($base_ext_length + $pre_ext_length))"
> +     check_dax_dev ${dax_dev} $ext_sum_length
> +
> +     test_remove_extents_in_use
> +
> +     destroy_dax_dev ${dax_dev}
> +     check_not_dax_dev ${region} ${dax_dev}
> +
> +     # In-use extents were not released.  Check they can be removed after
> +     # the dax device is removed.
> +     check_extent_cnt ${region} 2
> +     remove_extent ${device} $base_ext_dpa $base_ext_length "$test_tag_a"
> +     remove_extent ${device} $pre_ext_dpa $pre_ext_length "$test_tag_a"
> +     check_extent_cnt ${region} 0
> +     destroy_region ${region}
> +     check_not_region ${region}
> +}
> +
> +test_inject_tag_support()
> +{
> +     echo ""
> +     echo "Test: inject untagged + tagged extents, claim each via --uuid"
> +     echo ""
> +
> +     region=$(create_dcd_region ${mem} ${decoder})
> +     check_region ${region} ${dra_size}
> +
> +     # untagged extent
> +     inject_extent ${device} $pre_ext_dpa $pre_ext_length ""
> +     check_extent ${region} ${pre_ext_offset} ${pre_ext_length}
> +     # tagged extent (different DPA so both can land)
> +     inject_extent ${device} $base_ext_dpa $base_ext_length "$test_tag_a"
> +
> +     # both extents should be accepted
> +     check_extent_cnt ${region} 2
> +
> +     # claim the tagged extent into one dax device
> +     dax_dev_a=$(create_dax_dev_with_uuid ${region} "$test_tag_a")
> +     check_dax_dev ${dax_dev_a} $base_ext_length
> +
> +     # claim the untagged extent into a second dax device via "0"
> +     dax_dev_0=$(create_dax_dev_with_uuid ${region} "0")
> +     check_dax_dev ${dax_dev_0} $pre_ext_length
> +
> +     destroy_dax_dev ${dax_dev_a}
> +     destroy_dax_dev ${dax_dev_0}
> +     remove_extent ${device} $pre_ext_dpa $pre_ext_length ""
> +     remove_extent ${device} $base_ext_dpa $base_ext_length "$test_tag_a"
> +     check_extent_cnt ${region} 0
> +
> +     destroy_region ${region}
> +     check_not_region ${region}
> +}
> +
> +test_uuid_no_match()
> +{
> +     echo ""
> +     echo "Test: daxctl create-device --uuid with no matching extent fails"
> +     echo ""
> +
> +     region=$(create_dcd_region ${mem} ${decoder})
> +     check_region ${region} ${dra_size}
> +
> +     # inject only one tagged extent; ask daxctl to claim a different uuid
> +     inject_extent ${device} $pre_ext_dpa $pre_ext_length "$test_tag_a"
> +     check_extent_cnt ${region} 1
> +
> +     fail_create_dax_dev_with_uuid ${region} "$unknown_tag"
> +
> +     # the extent should still be claimable via its real tag
> +     dax_dev=$(create_dax_dev_with_uuid ${region} "$test_tag_a")
> +     check_dax_dev ${dax_dev} $pre_ext_length
> +     destroy_dax_dev ${dax_dev}
> +
> +     remove_extent ${device} $pre_ext_dpa $pre_ext_length "$test_tag_a"
> +     check_extent_cnt ${region} 0
> +     destroy_region ${region}
> +     check_not_region ${region}
> +}
> +
> +test_uuid_aggregation()
> +{
> +     echo ""
> +     echo "Test: multiple extents in a single More-chain aggregate under one 
> tag"
> +     echo ""
> +
> +     region=$(create_dcd_region ${mem} ${decoder})
> +     check_region ${region} ${dra_size}
> +
> +     # Both extents must arrive in the same More-chain to land in the
> +     # same tag group.  Re-using a tag across More-chains hits the
> +     # cross-More uniqueness gate and the second event would be dropped.
> +     inject_extent ${device} $base_ext_dpa $base_ext_length "$test_tag_a" 1
> +     check_extent_cnt ${region} 0
> +     inject_extent ${device} $pre_ext_dpa $pre_ext_length "$test_tag_a"
> +     check_extent_cnt ${region} 2
> +
> +     # a single --uuid claim should pick up both extents
> +     dax_dev=$(create_dax_dev_with_uuid ${region} "$test_tag_a")
> +     expected=$(($base_ext_length + $pre_ext_length))
> +     check_dax_dev ${dax_dev} $expected
> +
> +     destroy_dax_dev ${dax_dev}
> +     remove_extent ${device} $base_ext_dpa $base_ext_length "$test_tag_a"
> +     remove_extent ${device} $pre_ext_dpa $pre_ext_length "$test_tag_a"
> +     destroy_region ${region}
> +     check_not_region ${region}
> +}
> +
> +
> +test_partial_extent_remove ()
> +{
> +     echo ""
> +     echo "Test: partial extent remove"
> +     echo ""
> +
> +     region=$(create_dcd_region ${mem} ${decoder})
> +     check_region ${region} ${dra_size}
> +
> +     # | 2G non- |      DC region                                        |
> +     # |  DC cap |                                                       |
> +     # |  ...    |-------------------------------------------------------|
> +
> +     inject_extent ${device} $base_ext_dpa $base_ext_length ""
> +     # |  ...    |-------------------------------------------------------|
> +     # |         |--------|                                              |
> +     # |         | (base) |                                              |
> +
> +     dax_dev=$(create_dax_dev_with_uuid ${region} "0")
> +
> +     # |  ...    |-------------------------------------------------------|
> +     # |         |--------|                                              |
> +     # |         | (base) |                                              |
> +     # |         | daxX.1 |                                              |
> +
> +     partial_ext_dpa="$(($base_ext_dpa + ($base_ext_length / 2)))"
> +     partial_ext_length="$(($base_ext_length / 2))"
> +     echo "Removing Partial : $partial_ext_dpa $partial_ext_length"
> +
> +     # |         |    |---|                                              |
> +     #                  Partial
> +
> +     remove_extent ${device} $partial_ext_dpa $partial_ext_length ""
> +     # In-use extents are not released.
> +     check_extent_cnt ${region} 1
> +
> +     # |  ...    |-------------------------------------------------------|
> +     # |         |--------|                                              |
> +     # |         | (base) |                                              |
> +     # |         | daxX.1 |                                              |
> +
> +     destroy_dax_dev ${dax_dev}
> +     check_not_dax_dev ${region} ${dax_dev}
> +
> +     # |  ...    |-------------------------------------------------------|
> +     # |         |--------|                                              |
> +     # |         | (base) |                                              |
> +
> +     # Partial release event re-targets the whole containing region_extent.
> +     check_extent_cnt ${region} 1
> +     remove_extent ${device} $partial_ext_dpa $partial_ext_length ""
> +     # |         |    |---|                                              |
> +     #                  Partial
> +     check_extent_cnt ${region} 0
> +
> +     # |  ...    |-------------------------------------------------------|
> +     destroy_region ${region}
> +     check_not_region ${region}
> +}
> +
> +test_multiple_extent_remove ()
> +{
> +     # Per-tag-group release: a release event whose DPA range straddles
> +     # multiple region_extents in the same tag group should target them
> +     # atomically.  Set up two extents in one tagged More-chain.
> +     echo ""
> +     echo "Test: per-group release event covering two extents"
> +     echo ""
> +
> +     region=$(create_dcd_region ${mem} ${decoder})
> +     check_region ${region} ${dra_size}
> +
> +     # | 2G non- |      DC region                                        |
> +     # |  DC cap |                                                       |
> +     # |  ...    |-------------------------------------------------------|
> +
> +     inject_extent ${device} $base_ext_dpa $base_ext_length "$test_tag_a" 1
> +     inject_extent ${device} $pre_ext_dpa $pre_ext_length "$test_tag_a"
> +     # |  ...    |-------------------------------------------------------|
> +     # |         |--------|          |-------------------|               |
> +     # |         | (base) |          | (pre)-existing    |   tag_a       |
> +
> +     check_extent_cnt ${region} 2
> +     dax_dev=$(create_dax_dev_with_uuid ${region} "$test_tag_a")
> +
> +     # |         | daxX.1 |          | daxX.1            |   tag_a       |
> +
> +     # A release event addressed at any DPA inside the tag group releases
> +     # the whole group atomically.  Use base_ext_dpa so the kernel finds
> +     # the tag group's region_extent on that DPA.
> +     echo "Issuing tag-group release at $base_ext_dpa"
> +     remove_extent ${device} $base_ext_dpa $base_ext_length "$test_tag_a"
> +
> +     # In-use extents are not released (dax-layer EBUSY defer).
> +     check_extent_cnt ${region} 2
> +
> +     destroy_dax_dev ${dax_dev}
> +     check_not_dax_dev ${region} ${dax_dev}
> +
> +     # |  ...    |-------------------------------------------------------|
> +     # |         |--------|          |-------------------|               |
> +     # |         | (base) |          | (pre)-existing    |               |
> +
> +     # Now that the dax dev is gone, re-issue the release(s) for each
> +     # extent.  Each release event targets the containing region_extent.
> +     remove_extent ${device} $base_ext_dpa $base_ext_length "$test_tag_a"
> +     remove_extent ${device} $pre_ext_dpa $pre_ext_length "$test_tag_a"
> +     check_extent_cnt ${region} 0
> +
> +     destroy_region ${region}
> +     check_not_region ${region}
> +}
> +
> +test_destroy_region_without_extent_removal ()
> +{
> +     echo ""
> +     echo "Test: Destroy region without extent removal"
> +     echo ""
> +     
> +     region=$(create_dcd_region ${mem} ${decoder})
> +     check_region ${region} ${dra_size}
> +     inject_extent ${device} $pre_ext_dpa $pre_ext_length ""
> +     inject_extent ${device} $base_ext_dpa $base_ext_length ""
> +     check_extent_cnt ${region} 2
> +     destroy_region ${region}
> +     check_not_region ${region}
> +}
> +
> +test_destroy_with_extent_and_dax ()
> +{
> +     echo ""
> +     echo "Test: Destroy region with extents and dax devices"
> +     echo ""
> +     region=$(create_dcd_region ${mem} ${decoder})
> +     check_region ${region} ${dra_size}
> +     check_extent_cnt ${region} 0
> +     inject_extent ${device} $pre_ext_dpa $pre_ext_length ""
> +     
> +     # | 2G non- |      DC region                                        |
> +     # |  DC cap |                                                       |
> +     # |  ...    |-------------------------------------------------------|
> +     # |         |                   |----------|                        |
> +     # |         |                   |(pre-ext) |                        |
> +
> +     check_extent_cnt ${region} 1
> +     dax_dev=$(create_dax_dev_with_uuid ${region} "0")
> +     # |         |                   |<dax_dev> |                        |
> +     check_dax_dev ${dax_dev} ${pre_ext_length}
> +     destroy_region ${region}
> +     check_not_region ${region}
> +
> +     # | 2G non- |      DC region                                        |
> +     # |  DC cap |                                                       |
> +     # |  ...    |-------------------------------------------------------|
> +     # |         |                                                       |
> +
> +     region=$(create_dcd_region ${mem} ${decoder})
> +     check_region ${region} ${dra_size}
> +     check_extent_cnt ${region} 0
> +     destroy_region ${region}
> +     check_not_region ${region}
> +}
> +
> +test_dax_device_ops ()
> +{
> +     echo ""
> +     echo "Test: Fail sparse dax dev creation without space"
> +     echo ""
> +     region=$(create_dcd_region ${mem} ${decoder})
> +     check_region ${region} ${dra_size}
> +     inject_extent ${device} $pre_ext_dpa $pre_ext_length ""
> +
> +     # | 2G non- |      DC region                                        |
> +     # |  DC cap |                                                       |
> +     # |  ...    |-------------------------------------------------------|
> +     # |         |                   |-------------------|               |
> +     # |         |                   | (pre)-existing    |               |
> +
> +     check_extent_cnt ${region} 1
> +
> +     # |         |                   | daxX.1            |               |
> +
> +     dax_dev=$(create_dax_dev_with_uuid ${region} "0")
> +     check_dax_dev ${dax_dev} $pre_ext_length
> +     # No more untagged dax_resource avail: untagged claim returns -ENOENT
> +     fail_create_dax_dev_with_uuid ${region} "0"
> +     # Plain create-device on sparse: size grow is -EOPNOTSUPP
> +     fail_create_dax_dev ${region}
> +
> +     # DC dax devices cannot be resized to a non-zero size.  The
> +     # kernel rejects any size_store with -EOPNOTSUPP unless size == 0,
> +     # in which case dev_dax_shrink releases every range -- the same path
> +     # `daxctl destroy-device` takes.
> +     echo ""
> +     echo "Test: Resize of sparse dax device to non-zero is rejected"
> +     echo ""
> +     half=$(($pre_ext_length / 2))
> +     fail_resize_dax_dev ${dax_dev} $half
> +     check_dax_dev ${dax_dev} $pre_ext_length
> +
> +     # Destroy (size=0) is the only valid resize.  After it the
> +     # dax_resource has avail again, so --uuid "0" can claim it back
> +     # into a new dax device.
> +     # |         |                   | daxX.2            |               |
> +     echo ""
> +     echo "Test: Destroy (size=0) of sparse dax device releases the resource"
> +     echo ""
> +     destroy_dax_dev ${dax_dev}
> +     check_not_dax_dev ${region} ${dax_dev}
> +     dax_dev2=$(create_dax_dev_with_uuid ${region} "0")
> +     check_dax_dev ${dax_dev2} $pre_ext_length
> +
> +     destroy_region ${region}
> +     check_not_region ${region}
> +
> +     # Multi-extent device must come from a single tagged group; cross-
> +     # event untagged adds land in independent dax_resources and cannot
> +     # be claimed as one dax device.  The no-resize rule applies equally
> +     # across the tagged group.
> +     echo ""
> +     echo "Test: Resize of tagged multi-extent dax device is rejected"
> +     echo ""
> +     region=$(create_dcd_region ${mem} ${decoder})
> +     check_region ${region} ${dra_size}
> +     inject_extent ${device} $pre_ext_dpa $pre_ext_length "$test_tag_a" 1
> +     inject_extent ${device} $base_ext_dpa $base_ext_length "$test_tag_a"
> +
> +     # | 2G non- |      DC region                                        |
> +     # |  DC cap |                                                       |
> +     # |  ...    |-------------------------------------------------------|
> +     # |         |--------|          |-------------------|               |
> +     # |         | (base) |          | (pre)-existing    |    tag_a      |
> +
> +     check_extent_cnt ${region} 2
> +     dax_dev=$(create_dax_dev_with_uuid ${region} "$test_tag_a")
> +     ext_sum_length="$(($base_ext_length + $pre_ext_length))"
> +     check_dax_dev ${dax_dev} $ext_sum_length
> +
> +     # Any non-zero resize (here a shrink to 32M, which would sit inside
> +     # the first extent of the group) is rejected.
> +     fail_resize_dax_dev ${dax_dev} 33554432 # 32MB
> +     check_dax_dev ${dax_dev} $ext_sum_length
> +
> +     # Only size=0 / destroy is valid for the tagged group too.
> +     destroy_dax_dev ${dax_dev}
> +     check_not_dax_dev ${region} ${dax_dev}
> +
> +     destroy_region ${region}
> +     check_not_region ${region}
> +}
> +
> +test_reject_overlapping ()
> +{
> +     echo ""
> +     echo "Test: Rejecting overlapping extents"
> +     echo ""
> +
> +     region=$(create_dcd_region ${mem} ${decoder})
> +     check_region ${region} ${dra_size}
> +     inject_extent ${device} $pre_ext_dpa $pre_ext_length ""
> +
> +     # | 2G non- |      DC region                                        |
> +     # |  DC cap |                                                       |
> +     # |  ...    |-------------------------------------------------------|
> +     # |         |                   |-------------------|               |
> +     # |         |                   | (pre)-existing    |               |
> +
> +     check_extent_cnt ${region} 1
> +
> +     # Attempt overlapping extent: start halfway through pre_ext, same
> +     # length so it straddles the end of pre_ext.
> +     #
> +     # |         |                   |---------|---------|               |
> +     # |         |                   |(pre-ext)| overlap |               |
> +
> +     partial_ext_dpa="$(($pre_ext_dpa + ($pre_ext_length / 2)))"
> +     partial_ext_length=$pre_ext_length
> +     inject_extent ${device} $partial_ext_dpa $partial_ext_length ""
> +
> +     # Should only see the original ext
> +     check_extent_cnt ${region} 1
> +     destroy_region ${region}
> +     check_not_region ${region}
> +}
> +
> +test_two_regions()
> +{
> +     echo ""
> +     echo "Test: create 2 regions in the same DC partition"
> +     echo ""
> +     region_size=$(($dra_size / 2))
> +     region=$(create_dcd_region ${mem} ${decoder} ${region_size})
> +     check_region ${region} ${region_size}
> +     
> +     region_two=$(create_dcd_region ${mem} ${decoder} ${region_size})
> +     check_region ${region_two} ${region_size}
> +     
> +     destroy_region ${region_two}
> +     check_not_region ${region_two}
> +     destroy_region ${region}
> +     check_not_region ${region}
> +}
> +
> +test_more_bit()
> +{
> +     echo ""
> +     echo "Test: More bit"
> +     echo ""
> +     region=$(create_dcd_region ${mem} ${decoder})
> +     check_region ${region} ${dra_size}
> +     inject_extent ${device} $pre_ext_dpa $pre_ext_length "" 1
> +     # More bit should hold off surfacing extent until the more bit is 0
> +     check_extent_cnt ${region} 0
> +     inject_extent ${device} $base_ext_dpa $base_ext_length ""
> +     check_extent_cnt ${region} 2
> +     destroy_region ${region}
> +     check_not_region ${region}
> +}
> +
> +test_driver_tear_down()
> +{
> +     echo ""
> +     echo "Test: driver remove tear down"
> +     echo ""
> +     region=$(create_dcd_region ${mem} ${decoder})
> +     check_region ${region} ${dra_size}
> +     inject_extent ${device} $pre_ext_dpa $pre_ext_length ""
> +     check_extent ${region} ${pre_ext_offset} ${pre_ext_length}
> +     dax_dev=$(create_dax_dev_with_uuid ${region} "0")
> +     # remove driver releases extents
> +     modprobe -r dax_cxl
> +     check_extent_cnt ${region} 0
> +}
> +
> +test_driver_bring_up()
> +{
> +     # leave region up, driver removed.
> +     echo ""
> +     echo "Test: no driver inject ok"
> +     echo ""
> +     check_region ${region} ${dra_size}
> +     inject_extent ${device} $pre_ext_dpa $pre_ext_length ""
> +     check_extent_cnt ${region} 1
> +
> +     modprobe dax_cxl
> +     check_extent_cnt ${region} 1
> +
> +     destroy_region ${region}
> +     check_not_region ${region}
> +}
> +
> +test_driver_reload()
> +{
> +     test_driver_tear_down
> +     test_driver_bring_up
> +}
> +
> +# Verify the dax dev's uuid sysfs attribute reflects the claim source:
> +# "0" for untagged seed/claim, the tag string for tagged claims.
> +test_uuid_show()
> +{
> +     echo ""
> +     echo "Test: dax dev uuid attribute reflects the claim source"
> +     echo ""
> +
> +     region=$(create_dcd_region ${mem} ${decoder})
> +     check_region ${region} ${dra_size}
> +
> +     # Pre-claim the seed device's uuid (before any extent injected)
> +     # must read back as "0".  -i includes the idle seed at size 0.
> +     seed=$($DAXCTL list -r ${region} -D -i | jq -r '.[].chardev')
> +     check_dax_uuid ${seed} "0"
> +
> +     # Untagged extent + claim: uuid stays "0"
> +     inject_extent ${device} $pre_ext_dpa $pre_ext_length ""
> +     dax_u=$(create_dax_dev_with_uuid ${region} "0")
> +     check_dax_uuid ${dax_u} "0"
> +
> +     # Tagged extent + claim: uuid reads back as the tag
> +     inject_extent ${device} $base_ext_dpa $base_ext_length "$test_tag_a"
> +     dax_t=$(create_dax_dev_with_uuid ${region} "$test_tag_a")
> +     check_dax_uuid ${dax_t} "$test_tag_a"
> +
> +     destroy_dax_dev ${dax_u}
> +     destroy_dax_dev ${dax_t}
> +     remove_extent ${device} $pre_ext_dpa $pre_ext_length ""
> +     remove_extent ${device} $base_ext_dpa $base_ext_length "$test_tag_a"
> +     destroy_region ${region}
> +     check_not_region ${region}
> +}
> +
> +# --uuid <unknown> on a sparse region must return -ENOENT before any
> +# size is committed.  The region's available_size must be unchanged and
> +# the underlying extent must still be claimable via its real tag.
> +test_uuid_no_match_seed_intact()
> +{
> +     echo ""
> +     echo "Test: --uuid mismatch does not consume any extent space"
> +     echo ""
> +
> +     region=$(create_dcd_region ${mem} ${decoder})
> +     check_region ${region} ${dra_size}
> +
> +     inject_extent ${device} $pre_ext_dpa $pre_ext_length "$test_tag_a"
> +     check_extent_cnt ${region} 1
> +
> +     # Capture region available size before the failed claim
> +     avail_before=$($DAXCTL list -r ${region} | jq -r '.[].available_size')
> +
> +     fail_create_dax_dev_with_uuid ${region} "$unknown_tag"
> +
> +     avail_after=$($DAXCTL list -r ${region} | jq -r '.[].available_size')
> +     if [ "$avail_before" != "$avail_after" ]; then
> +             echo "FAIL avail size changed by unmatched --uuid: 
> $avail_before -> $avail_after"
> +             err "$LINENO"
> +     fi
> +
> +     # The real tag still claims successfully
> +     dax_dev=$(create_dax_dev_with_uuid ${region} "$test_tag_a")
> +     check_dax_dev ${dax_dev} $pre_ext_length
> +
> +     destroy_dax_dev ${dax_dev}
> +     remove_extent ${device} $pre_ext_dpa $pre_ext_length "$test_tag_a"
> +     destroy_region ${region}
> +     check_not_region ${region}
> +}
> +
> +# A second tagged Add-event reusing a previously committed tag must be
> +# dropped by the cross-More uniqueness gate (firmware-bug path).  Skipped
> +# for the null UUID.
> +test_cross_more_uniqueness()
> +{
> +     echo ""
> +     echo "Test: cross-More uniqueness drops second event with same tag"
> +     echo ""
> +
> +     region=$(create_dcd_region ${mem} ${decoder})
> +     check_region ${region} ${dra_size}
> +
> +     # First Add-event (single extent) commits tag_a at base_ext_dpa.
> +     inject_extent ${device} $base_ext_dpa $base_ext_length "$test_tag_a"
> +     check_extent_cnt ${region} 1
> +
> +     # Second Add-event reuses tag_a at a different DPA: must be dropped.
> +     inject_extent ${device} $pre_ext_dpa $pre_ext_length "$test_tag_a"
> +     check_extent_cnt ${region} 1
> +
> +     # The original tag_a allocation is still usable.
> +     dax_dev=$(create_dax_dev_with_uuid ${region} "$test_tag_a")
> +     check_dax_dev ${dax_dev} $base_ext_length
> +
> +     destroy_dax_dev ${dax_dev}
> +     remove_extent ${device} $base_ext_dpa $base_ext_length "$test_tag_a"
> +     destroy_region ${region}
> +     check_not_region ${region}
> +}
> +
> +# Sharable-partition test: two extents in one tagged More-chain with
> +# device-stamped seq 1..2.  Uses the sharable memdev (serial 0xDCDC).
> +test_shared_extent_inject()
> +{
> +     echo ""
> +     echo "Test: shared extent inject on sharable partition"
> +     echo ""
> +
> +     region=$(create_dcd_region ${sharable_mem} ${sharable_decoder})
> +     check_region ${region} ${sharable_dra_size}
> +
> +     inject_shared_extent ${sharable_device} $base_ext_dpa $base_ext_length \
> +             "$test_tag_b" 1 1
> +     check_extent_cnt ${region} 0
> +     inject_shared_extent ${sharable_device} $pre_ext_dpa $pre_ext_length \
> +             "$test_tag_b" "" 2
> +     check_extent_cnt ${region} 2
> +
> +     dax_dev=$(create_dax_dev_with_uuid ${region} "$test_tag_b")
> +     expected=$(($base_ext_length + $pre_ext_length))
> +     check_dax_dev ${dax_dev} $expected
> +
> +     destroy_dax_dev ${dax_dev}
> +     remove_extent ${sharable_device} $base_ext_dpa $base_ext_length 
> "$test_tag_b"
> +     remove_extent ${sharable_device} $pre_ext_dpa $pre_ext_length 
> "$test_tag_b"
> +     destroy_region ${region}
> +     check_not_region ${region}
> +}
> +
> +# Sharable extents must arrive with a dense 1..n shared_extn_seq.  A gap
> +# (1, 3) lets the cxl side accept the extents but uuid_claim_tagged
> +# refuses the group on its density check.  Uses the sharable memdev.
> +test_seq_integrity_gap()
> +{
> +     echo ""
> +     echo "Test: sharable extents with seq gap (1,3) refused on claim"
> +     echo ""
> +
> +     region=$(create_dcd_region ${sharable_mem} ${sharable_decoder})
> +     check_region ${region} ${sharable_dra_size}
> +
> +     inject_shared_extent ${sharable_device} $base_ext_dpa $base_ext_length \
> +             "$test_tag_b" 1 1
> +     check_extent_cnt ${region} 0
> +     inject_shared_extent ${sharable_device} $pre_ext_dpa $pre_ext_length \
> +             "$test_tag_b" "" 3
> +
> +     if [ "$(jq -r '.[].extents | length' <($CXL list -r ${region} -N))" = 
> "2" ]; then
> +             fail_create_dax_dev_with_uuid ${region} "$test_tag_b"
> +             remove_extent ${sharable_device} $base_ext_dpa $base_ext_length 
> "$test_tag_b"
> +             remove_extent ${sharable_device} $pre_ext_dpa $pre_ext_length 
> "$test_tag_b"
> +     fi
> +     check_extent_cnt ${region} 0
> +     destroy_region ${region}
> +     check_not_region ${region}
> +}
> +
> +# CXL_DCD_EXTENT_ALIGN is 2M; an extent that is not 2M-aligned must drop
> +# the whole group.  Inject a 64M extent at a 1M-offset DPA.
> +test_alignment_rejection()
> +{
> +     echo ""
> +     echo "Test: misaligned extent drops the group"
> +     echo ""
> +
> +     region=$(create_dcd_region ${mem} ${decoder})
> +     check_region ${region} ${dra_size}
> +
> +     # 1M past base — not 2M aligned
> +     mis_dpa=$(($base_ext_dpa + 0x100000))
> +     inject_extent ${device} $mis_dpa $base_ext_length ""
> +     check_extent_cnt ${region} 0
> +
> +     destroy_region ${region}
> +     check_not_region ${region}
> +}
> +
> +test_event_reporting()
> +{
> +     # Test event reporting
> +     # results expected
> +     num_dcd_events_expected=2
> +
> +     echo "Test: Prep event trace"
> +     echo "" > /sys/kernel/tracing/trace
> +     echo 1 > /sys/kernel/tracing/events/cxl/enable
> +     echo 1 > /sys/kernel/tracing/tracing_on
> +
> +     inject_extent ${device} $base_ext_dpa $base_ext_length ""
> +     remove_extent ${device} $base_ext_dpa $base_ext_length

Missing the tag arg

DJ

> +
> +     echo 0 > /sys/kernel/tracing/tracing_on
> +
> +     echo "Test: Events seen"
> +     trace_out=$(cat /sys/kernel/tracing/trace)
> +
> +     # Look for DCD events
> +     num_dcd_events=$(grep -c "cxl_dynamic_capacity" <<< "${trace_out}")
> +     echo "     LOG     (Expected) : (Found)"
> +     echo "     DCD events    ($num_dcd_events_expected) : $num_dcd_events"
> +
> +     if [ "$num_dcd_events" -ne $num_dcd_events_expected ]; then
> +             err "$LINENO"
> +     fi
> +}
> +
> +
> +# ========================================================================
> +# main()
> +# ========================================================================
> +
> +modprobe -r cxl_test
> +modprobe cxl_test
> +
> +# The mock stamps a single cxl_mem instance with this serial (0xDCDC).
> +# That memdev's DC partition is advertised as sharable in CDAT and is
> +# the only one that can host the shared-extent tests.  All other DCD
> +# memdevs stay non-sharable and host the rest of the suite.
> +MOCK_DC_SHARABLE_SERIAL=56540
> +
> +readarray -t memdevs < <("$CXL" list -b cxl_test -Mi | jq -r '.[].memdev')
> +
> +sharable_mem=""
> +sharable_decoder=""
> +sharable_bus=""
> +sharable_device=""
> +sharable_dra_size=""
> +
> +for cand in ${memdevs[@]}; do
> +     cand_dra=$($CXL list -m $cand | jq -r '.[].dynamic_ram_a_size')
> +     if [ "$cand_dra" == "null" ]; then
> +             continue
> +     fi
> +     cand_decoder=$($CXL list -b cxl_test -D -d root -m "$cand" |
> +               jq -r ".[] |
> +               select(.volatile_capable == true) |
> +               select(.nr_targets == 1) |
> +               select(.max_available_extent >= ${cand_dra}) |
> +               .decoder")
> +     if [[ -z "$cand_decoder" ]]; then
> +             continue
> +     fi
> +     cand_serial=$($CXL list -m $cand | jq -r '.[].serial')
> +     cand_bus=`"$CXL" list -b cxl_test -m ${cand} | jq -r '.[].bus'`
> +     cand_device=$($CXL list -m $cand | jq -r '.[].host')
> +
> +     if [ "$cand_serial" == "$MOCK_DC_SHARABLE_SERIAL" ]; then
> +             if [ -z "$sharable_mem" ]; then
> +                     sharable_mem="$cand"
> +                     sharable_decoder="$cand_decoder"
> +                     sharable_bus="$cand_bus"
> +                     sharable_device="$cand_device"
> +                     sharable_dra_size="$cand_dra"
> +             fi
> +     else
> +             if [ -z "$mem" ]; then
> +                     mem="$cand"
> +                     decoder="$cand_decoder"
> +                     bus="$cand_bus"
> +                     device="$cand_device"
> +                     dra_size="$cand_dra"
> +             fi
> +     fi
> +
> +     if [ -n "$mem" ] && [ -n "$sharable_mem" ]; then
> +             break
> +     fi
> +done
> +
> +echo "TEST: non-sharable bus:${bus} decoder:${decoder} mem:${mem} 
> device:${device} size:${dra_size}"
> +echo "TEST: sharable     bus:${sharable_bus} decoder:${sharable_decoder} 
> mem:${sharable_mem} device:${sharable_device} size:${sharable_dra_size}"
> +
> +if [ "$decoder" == "" ] || [ "$device" == "" ] || [ "$dra_size" == "" ]; then
> +     echo "No non-sharable mem device/decoder found with DCD support"
> +     exit 77
> +fi
> +
> +if [ "$sharable_mem" == "" ]; then
> +     echo "No sharable mem device found (mock did not stamp 
> MOCK_DC_SHARABLE_SERIAL)"
> +     exit 77
> +fi
> +
> +# testing pre existing extents must be called first as the extents were 
> created
> +# by cxl-test being loaded
> +test_pre_existing_extents
> +test_remove_extent_under_dax_device
> +test_create_dax_dev_spanning_two_extents
> +test_inject_tag_support
> +test_uuid_no_match
> +test_uuid_no_match_seed_intact
> +test_uuid_aggregation
> +test_uuid_show
> +# These two run on the sharable memdev (serial $MOCK_DC_SHARABLE_SERIAL).
> +test_shared_extent_inject
> +test_seq_integrity_gap
> +test_cross_more_uniqueness
> +test_alignment_rejection
> +test_partial_extent_remove
> +test_multiple_extent_remove
> +test_destroy_region_without_extent_removal
> +test_destroy_with_extent_and_dax
> +test_dax_device_ops
> +test_reject_overlapping
> +test_two_regions
> +test_more_bit
> +test_driver_reload
> +test_event_reporting
> +
> +modprobe -r cxl_test
> +
> +check_dmesg "$LINENO"
> +
> +exit 0
> diff --git a/test/meson.build b/test/meson.build
> index e0e2193..cd06bf8 100644
> --- a/test/meson.build
> +++ b/test/meson.build
> @@ -171,6 +171,7 @@ cxl_translate = find_program('cxl-translate.sh')
>  cxl_elc = find_program('cxl-elc.sh')
>  cxl_dax_hmem = find_program('cxl-dax-hmem.sh')
>  cxl_region_replay = find_program('cxl-region-replay.sh')
> +cxl_dcd = find_program('cxl-dcd.sh')
>  
>  tests = [
>    [ 'libndctl',               libndctl,                'ndctl' ],
> @@ -207,6 +208,7 @@ tests = [
>    [ 'cxl-elc.sh',             cxl_elc,            'cxl'   ],
>    [ 'cxl-dax-hmem.sh',        cxl_dax_hmem,       'cxl'   ],
>    [ 'cxl-region-replay.sh',   cxl_region_replay,  'cxl'   ],
> +  [ 'cxl-dcd.sh',             cxl_dcd,            'cxl'   ],
>  ]
>  
>  if get_option('destructive').enabled()


Reply via email to