Dave Jiang wrote:
>
>
> On 11/4/24 7:10 PM, Ira Weiny wrote:
> > 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 the event processing function directly.
> >
> > 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 in
> > cxl_test.
> >
> > Signed-off-by: Ira Weiny <[email protected]>
>
> Would things look cleaner if the multiple test cases are organized into
> individual bash functions?
Perhaps. But many of the initial tests borrow state from the previous
test. For example the cxl-test pre-existing extents are used to test
extent removal. Later on those dependencies lessoned.
Let me see if I can clean up the testing now that things are settling out.
Ira
>
> > ---
> > test/cxl-dcd.sh | 656
> > +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > test/meson.build | 2 +
> > 2 files changed, 658 insertions(+)
> >
> > diff --git a/test/cxl-dcd.sh b/test/cxl-dcd.sh
> > new file mode 100644
> > index
> > 0000000000000000000000000000000000000000..f5248fce4f3899acdf646ace4f0eb531ea2286d3
> > --- /dev/null
> > +++ b/test/cxl-dcd.sh
> > @@ -0,0 +1,656 @@
> > +#!/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"
> > +
> > +modprobe -r cxl_test
> > +modprobe cxl_test
> > +rc=1
> > +
> > +dev_path="/sys/bus/platform/devices"
> > +cxl_path="/sys/bus/cxl/devices"
> > +
> > +# a test extent tag
> > +test_tag=dc-test-tag
> > +
> > +#
> > +# 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-existing. The other is created within this script alone
> > called
> > +# base.
> > +
> > +#
> > +# | 2G non- | DC region (1G) |
> > +# | DC cap | |
> > +# | ... |-------------------------------------------------------|
> > +# | |--------| |----------| |----------| |
> > +# | | (base) | | (pre)- | | (pre2)- | |
> > +# | | | | existing | | existing | |
> > +
> > +dcsize=""
> > +
> > +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=""
> > +
> > +create_dcd_region()
> > +{
> > + mem="$1"
> > + decoder="$2"
> > + reg_size_string=""
> > + if [ "$3" != "" ]; then
> > + reg_size_string="-s $3"
> > + fi
> > + dcd_partition="dc0"
> > + if [ "$4" != "" ]; then
> > + dcd_partition="$4"
> > + fi
> > +
> > + # create region
> > + rc=$($CXL create-region -t ${dcd_partition} -d "$decoder" -m "$mem"
> > ${reg_size_string} | jq -r ".region")
> > +
> > + if [[ ! $rc ]]; then
> > + echo "create-region failed for $decoder / $mem"
> > + err "$LINENO"
> > + fi
> > +
> > + echo ${rc}
> > +}
> > +
> > +check_region()
> > +{
> > + search=$1
> > + region_size=$2
> > +
> > + 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()
> > +{
> > + search=$1
> > +
> > + 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()
> > +{
> > + device="$1"
> > + dpa="$2"
> > + length="$3"
> > + tag="$4"
> > +
> > + more="0"
> > + if [ "$5" != "" ]; then
> > + more="1"
> > + fi
> > +
> > + echo ${dpa}:${length}:${tag}:${more} >
> > "${dev_path}/${device}/dc_inject_extent"
> > +}
> > +
> > +remove_extent()
> > +{
> > + device="$1"
> > + dpa="$2"
> > + length="$3"
> > +
> > + echo ${dpa}:${length} > "${dev_path}/${device}/dc_del_extent"
> > +}
> > +
> > +create_dax_dev()
> > +{
> > + reg="$1"
> > +
> > + dax_dev=$($DAXCTL create-device -r $reg | jq -er '.[].chardev')
> > +
> > + echo ${dax_dev}
> > +}
> > +
> > +fail_create_dax_dev()
> > +{
> > + reg="$1"
> > +
> > + set +e
> > + result=$($DAXCTL create-device -r $reg)
> > + set -e
> > + if [ "$result" == "0" ]; then
> > + echo "FAIL device created"
> > + err "$LINENO"
> > + fi
> > +}
> > +
> > +shrink_dax_dev()
> > +{
> > + dev="$1"
> > + new_size="$2"
> > +
> > + $DAXCTL disable-device $dev
> > + $DAXCTL reconfigure-device $dev -s $new_size
> > + $DAXCTL enable-device $dev
> > +}
> > +
> > +destroy_dax_dev()
> > +{
> > + dev="$1"
> > +
> > + $DAXCTL disable-device $dev
> > + $DAXCTL destroy-device $dev
> > +}
> > +
> > +check_dax_dev()
> > +{
> > + search="$1"
> > + size="$2"
> > +
> > + 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()
> > +{
> > + reg="$1"
> > + search="$2"
> > + result=$($DAXCTL list -r $reg -D | jq -er '.[].chardev')
> > + if [ "$result" == "$search" ]; then
> > + echo "FAIL found $search"
> > + err "$LINENO"
> > + fi
> > +}
> > +
> > +check_extent()
> > +{
> > + region=$1
> > + offset=$(($2))
> > + length=$(($3))
> > +
> > + 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()
> > +{
> > + region=$1
> > + count=$(($2))
> > +
> > + 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
> > +}
> > +
> > +readarray -t memdevs < <("$CXL" list -b cxl_test -Mi | jq -r '.[].memdev')
> > +
> > +for mem in ${memdevs[@]}; do
> > + dcsize=$($CXL list -m $mem | jq -r '.[].dc0_size')
> > + if [ "$dcsize" == "null" ]; then
> > + continue
> > + fi
> > + decoder=$($CXL list -b cxl_test -D -d root -m "$mem" |
> > + jq -r ".[] |
> > + select(.dc0_capable == true) |
> > + select(.nr_targets == 1) |
> > + select(.max_available_extent >= ${dcsize}) |
> > + .decoder")
> > + if [[ $decoder ]]; then
> > + bus=`"$CXL" list -b cxl_test -m ${mem} | jq -r '.[].bus'`
> > + device=$($CXL list -m $mem | jq -r '.[].host')
> > + break
> > + fi
> > +done
> > +
> > +echo "TEST: DCD test device bus:${bus} decoder:${decoder} mem:${mem}
> > device:${device} size:${dcsize}"
> > +
> > +if [ "$decoder" == "" ] || [ "$device" == "" ] || [ "$dcsize" == "" ]; then
> > + echo "No mem device/decoder found with DCD support"
> > + exit 77
> > +fi
> > +
> > +echo ""
> > +echo "Test: pre-existing extent"
> > +echo ""
> > +region=$(create_dcd_region ${mem} ${decoder})
> > +check_region ${region} ${dcsize}
> > +# should contain pre-created extents
> > +check_extent ${region} ${pre_ext_offset} ${pre_ext_length}
> > +check_extent ${region} ${pre2_ext_offset} ${pre2_ext_length}
> > +
> > +
> > +# | 2G non- | DC region |
> > +# | DC cap | |
> > +# | ... |-------------------------------------------------------|
> > +# | | |----------| |----------| |
> > +# | | | (pre)- | | (pre2)- | |
> > +# | | | existing | | existing | |
> > +
> > +# 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 ""
> > +dax_dev=$(create_dax_dev ${region})
> > +check_extent_cnt ${region} 2
> > +remove_extent ${device} $pre_ext_dpa $pre_ext_length
> > +length="$(($pre_ext_length + $pre2_ext_length))"
> > +check_dax_dev ${dax_dev} $length
> > +check_extent_cnt ${region} 2
> > +destroy_dax_dev ${dax_dev}
> > +check_not_dax_dev ${region} ${dax_dev}
> > +
> > +# In-use extents are not released. Remove after use.
> > +check_extent_cnt ${region} 2
> > +remove_extent ${device} $pre_ext_dpa $pre_ext_length
> > +remove_extent ${device} $pre2_ext_dpa $pre2_ext_length
> > +check_extent_cnt ${region} 0
> > +
> > +echo ""
> > +echo "Test: Create dax device spanning 2 extents"
> > +echo ""
> > +inject_extent ${device} $pre_ext_dpa $pre_ext_length ""
> > +check_extent ${region} ${pre_ext_offset} ${pre_ext_length}
> > +inject_extent ${device} $base_ext_dpa $base_ext_length ""
> > +check_extent ${region} ${base_ext_offset} ${base_ext_length}
> > +
> > +# | 2G non- | DC region |
> > +# | DC cap | |
> > +# | ... |-------------------------------------------------------|
> > +# | |--------| |----------| |
> > +# | | (base) | | (pre)- | |
> > +# | | | | existing | |
> > +
> > +check_extent_cnt ${region} 2
> > +dax_dev=$(create_dax_dev ${region})
> > +
> > +echo ""
> > +echo "Test: dev dax is spanning sparse extents"
> > +echo ""
> > +ext_sum_length="$(($base_ext_length + $pre_ext_length))"
> > +check_dax_dev ${dax_dev} $ext_sum_length
> > +
> > +
> > +echo ""
> > +echo "Test: Remove extents under sparse dax device"
> > +echo ""
> > +remove_extent ${device} $base_ext_dpa $base_ext_length
> > +check_extent_cnt ${region} 2
> > +remove_extent ${device} $pre_ext_dpa $pre_ext_length
> > +check_extent_cnt ${region} 2
> > +destroy_dax_dev ${dax_dev}
> > +check_not_dax_dev ${region} ${dax_dev}
> > +
> > +# In-use extents are not released. Remove after use.
> > +check_extent_cnt ${region} 2
> > +remove_extent ${device} $base_ext_dpa $base_ext_length
> > +remove_extent ${device} $pre_ext_dpa $pre_ext_length
> > +check_extent_cnt ${region} 0
> > +
> > +echo ""
> > +echo "Test: inject without/with tag"
> > +echo ""
> > +inject_extent ${device} $pre_ext_dpa $pre_ext_length ""
> > +check_extent ${region} ${pre_ext_offset} ${pre_ext_length}
> > +inject_extent ${device} $base_ext_dpa $base_ext_length ""
> > +check_extent ${region} ${base_ext_offset} ${base_ext_length}
> > +remove_extent ${device} $base_ext_dpa $base_ext_length
> > +remove_extent ${device} $pre_ext_dpa $pre_ext_length
> > +check_extent_cnt ${region} 0
> > +
> > +
> > +echo ""
> > +echo "Test: partial extent remove"
> > +echo ""
> > +inject_extent ${device} $base_ext_dpa $base_ext_length ""
> > +dax_dev=$(create_dax_dev ${region})
> > +
> > +# | 2G non- | DC region |
> > +# | DC cap | |
> > +# | ... |-------------------------------------------------------|
> > +# | |--------| |
> > +# | | (base) | |
> > +# | | |---| |
> > +# Partial
> > +
> > +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"
> > +remove_extent ${device} $partial_ext_dpa $partial_ext_length
> > +check_extent_cnt ${region} 1
> > +destroy_dax_dev ${dax_dev}
> > +check_not_dax_dev ${region} ${dax_dev}
> > +
> > +# In-use extents are not released. Remove after use.
> > +check_extent_cnt ${region} 1
> > +remove_extent ${device} $partial_ext_dpa $partial_ext_length
> > +check_extent_cnt ${region} 0
> > +
> > +# Test multiple extent remove
> > +echo ""
> > +echo "Test: multiple extent remove with single extent remove command"
> > +echo ""
> > +inject_extent ${device} $pre_ext_dpa $pre_ext_length ""
> > +inject_extent ${device} $base_ext_dpa $base_ext_length ""
> > +check_extent_cnt ${region} 2
> > +dax_dev=$(create_dax_dev ${region})
> > +
> > +# | 2G non- | DC region |
> > +# | DC cap | |
> > +# | ... |-------------------------------------------------------|
> > +# | |--------| |-------------------| |
> > +# | | (base) | | (pre)-existing | |
> > +# |------------------|
> > +# Partial
> > +
> > +partial_ext_dpa="$(($base_ext_dpa + ($base_ext_length / 2)))"
> > +partial_ext_length="$(($pre_ext_dpa - $base_ext_dpa))"
> > +echo "Removing multiple in span : $partial_ext_dpa $partial_ext_length"
> > +remove_extent ${device} $partial_ext_dpa $partial_ext_length
> > +check_extent_cnt ${region} 2
> > +destroy_dax_dev ${dax_dev}
> > +check_not_dax_dev ${region} ${dax_dev}
> > +
> > +
> > +echo ""
> > +echo "Test: Destroy region without extent removal"
> > +echo ""
> > +
> > +# In-use extents are not released.
> > +check_extent_cnt ${region} 2
> > +destroy_region ${region}
> > +check_not_region ${region}
> > +
> > +
> > +echo ""
> > +echo "Test: Destroy region with extents and dax devices"
> > +echo ""
> > +region=$(create_dcd_region ${mem} ${decoder})
> > +check_region ${region} ${dcsize}
> > +check_extent_cnt ${region} 0
> > +inject_extent ${device} $pre_ext_dpa $pre_ext_length ""
> > +
> > +# | 2G non- | DC region |
> > +# | DC cap | |
> > +# | ... |-------------------------------------------------------|
> > +# | | |----------| |
> > +# | | | (pre)- | |
> > +# | | | existing | |
> > +
> > +check_extent_cnt ${region} 1
> > +dax_dev=$(create_dax_dev ${region})
> > +destroy_region ${region}
> > +check_not_region ${region}
> > +
> > +echo ""
> > +echo "Test: Fail sparse dax dev creation without space"
> > +echo ""
> > +region=$(create_dcd_region ${mem} ${decoder})
> > +check_region ${region} ${dcsize}
> > +inject_extent ${device} $pre_ext_dpa $pre_ext_length ""
> > +
> > +# | 2G non- | DC region |
> > +# | DC cap | |
> > +# | ... |-------------------------------------------------------|
> > +# | | |-------------------| |
> > +# | | | (pre)-existing | |
> > +
> > +check_extent_cnt ${region} 1
> > +
> > +# | | | dax0.1 | |
> > +
> > +dax_dev=$(create_dax_dev ${region})
> > +check_dax_dev ${dax_dev} $pre_ext_length
> > +fail_create_dax_dev ${region}
> > +
> > +echo ""
> > +echo "Test: Resize sparse dax device"
> > +echo ""
> > +
> > +# Shrink
> > +# | | | dax0.1 | |
> > +resize_ext_length=$(($pre_ext_length / 2))
> > +shrink_dax_dev ${dax_dev} $resize_ext_length
> > +check_dax_dev ${dax_dev} $resize_ext_length
> > +
> > +# Fill
> > +# | | | dax0.1 | dax0.2 | |
> > +dax_dev=$(create_dax_dev ${region})
> > +check_dax_dev ${dax_dev} $resize_ext_length
> > +destroy_region ${region}
> > +check_not_region ${region}
> > +
> > +
> > +# 2 extent
> > +# create dax dev
> > +# resize into 1st extent
> > +# create dev on rest of 1st and all of second
> > +# Ensure both devices are correct
> > +
> > +echo ""
> > +echo "Test: Resize sparse dax device across extents"
> > +echo ""
> > +region=$(create_dcd_region ${mem} ${decoder})
> > +check_region ${region} ${dcsize}
> > +inject_extent ${device} $pre_ext_dpa $pre_ext_length ""
> > +inject_extent ${device} $base_ext_dpa $base_ext_length ""
> > +
> > +# | 2G non- | DC region |
> > +# | DC cap | |
> > +# | ... |-------------------------------------------------------|
> > +# | |--------| |-------------------| |
> > +# | | (base) | | (pre)-existing | |
> > +
> > +check_extent_cnt ${region} 2
> > +dax_dev=$(create_dax_dev ${region})
> > +ext_sum_length="$(($base_ext_length + $pre_ext_length))"
> > +
> > +# | | dax0.1 | | dax0.1 | |
> > +
> > +check_dax_dev ${dax_dev} $ext_sum_length
> > +resize_ext_length=33554432 # 32MB
> > +
> > +# | | D1 | |
> > +
> > +shrink_dax_dev ${dax_dev} $resize_ext_length
> > +check_dax_dev ${dax_dev} $resize_ext_length
> > +
> > +# | | D1 | D2| | dax0.2 | |
> > +
> > +dax_dev=$(create_dax_dev ${region})
> > +remainder_length=$((ext_sum_length - $resize_ext_length))
> > +check_dax_dev ${dax_dev} $remainder_length
> > +
> > +# | | D1 | D2| | dax0.2 | |
> > +
> > +remainder_length=$((remainder_length / 2))
> > +shrink_dax_dev ${dax_dev} $remainder_length
> > +check_dax_dev ${dax_dev} $remainder_length
> > +
> > +# | | D1 | D2| | dax0.2 | dax0.3 | |
> > +
> > +dax_dev=$(create_dax_dev ${region})
> > +check_dax_dev ${dax_dev} $remainder_length
> > +destroy_region ${region}
> > +check_not_region ${region}
> > +
> > +
> > +echo ""
> > +echo "Test: Rejecting overlapping extents"
> > +echo ""
> > +
> > +region=$(create_dcd_region ${mem} ${decoder})
> > +check_region ${region} ${dcsize}
> > +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
> > +#
> > +# | | |-----------------| |
> > +# | | | overlapping | |
> > +
> > +partial_ext_dpa="$(($base_ext_dpa + ($pre_ext_dpa / 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}
> > +
> > +
> > +echo ""
> > +echo "Test: create 2 regions in the same DC partition"
> > +echo ""
> > +region_size=$(($dcsize / 2))
> > +region=$(create_dcd_region ${mem} ${decoder} ${region_size} dc1)
> > +check_region ${region} ${region_size}
> > +
> > +region_two=$(create_dcd_region ${mem} ${decoder} ${region_size} dc1)
> > +check_region ${region_two} ${region_size}
> > +
> > +destroy_region ${region_two}
> > +check_not_region ${region_two}
> > +destroy_region ${region}
> > +check_not_region ${region}
> > +
> > +
> > +echo ""
> > +echo "Test: More bit"
> > +echo ""
> > +region=$(create_dcd_region ${mem} ${decoder})
> > +check_region ${region} ${dcsize}
> > +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}
> > +
> > +
> > +# Create a new region for driver tests
> > +region=$(create_dcd_region ${mem} ${decoder})
> > +
> > +echo ""
> > +echo "Test: driver remove tear down"
> > +echo ""
> > +check_region ${region} ${dcsize}
> > +inject_extent ${device} $pre_ext_dpa $pre_ext_length ""
> > +check_extent ${region} ${pre_ext_offset} ${pre_ext_length}
> > +dax_dev=$(create_dax_dev ${region})
> > +# remove driver releases extents
> > +modprobe -r dax_cxl
> > +check_extent_cnt ${region} 0
> > +
> > +# leave region up, driver removed.
> > +echo ""
> > +echo "Test: no driver inject ok"
> > +echo ""
> > +check_region ${region} ${dcsize}
> > +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 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
> > +
> > +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
> > +
> > +modprobe -r cxl_test
> > +
> > +check_dmesg "$LINENO"
> > +
> > +exit 0
> > diff --git a/test/meson.build b/test/meson.build
> > index
> > d871e28e17ce512cd1e7b43f3ec081729fe5e03a..1cfcb60d16e05272893ae1c67820aa8614281505
> > 100644
> > --- a/test/meson.build
> > +++ b/test/meson.build
> > @@ -161,6 +161,7 @@ cxl_sanitize = find_program('cxl-sanitize.sh')
> > cxl_destroy_region = find_program('cxl-destroy-region.sh')
> > cxl_qos_class = find_program('cxl-qos-class.sh')
> > cxl_poison = find_program('cxl-poison.sh')
> > +cxl_dcd = find_program('cxl-dcd.sh')
> >
> > tests = [
> > [ 'libndctl', libndctl, 'ndctl' ],
> > @@ -194,6 +195,7 @@ tests = [
> > [ 'cxl-destroy-region.sh', cxl_destroy_region, 'cxl' ],
> > [ 'cxl-qos-class.sh', cxl_qos_class, 'cxl' ],
> > [ 'cxl-poison.sh', cxl_poison, 'cxl' ],
> > + [ 'cxl-dcd.sh', cxl_dcd, 'cxl' ],
> > ]
> >
> > if get_option('destructive').enabled()
> >
>