NVMf target reports copy command support if all bdevs in the subsystem support copy IO type. Maximum copy size is reported for each namespace independently in namespace identify data. For now we support just one source range. Note, that command support in the controller is initialized once on controller create. If another namespace which doesn't support copy command is added to the subsystem later, it will not be reflected in the controller data structure and will not be communicated to the initiator. Attempt to execute copy command on such namespace will fail. This issue is not specific to copy command and applies also to write zeroes and unmap (dataset management) commands. Signed-off-by: Evgeniy Kochetov <evgeniik@nvidia.com> Change-Id: I5f06564eb43d66d2852bf7eeda8b17830c53c9bc Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/14350 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Shuhei Matsumoto <smatsumoto@nvidia.com> Reviewed-by: Aleksey Marchuk <alexeymar@nvidia.com>
334 lines
9.7 KiB
Bash
Executable File
334 lines
9.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# SPDX-License-Identifier: BSD-3-Clause
|
|
# Copyright (C) 2019 Intel Corporation
|
|
# All rights reserved.
|
|
#
|
|
shopt -s extglob
|
|
git_repo_abi="https://github.com/spdk/spdk-abi.git"
|
|
|
|
function get_spdk_abi() {
|
|
local dest=$1
|
|
mkdir -p $dest
|
|
if [[ -d $SPDK_ABI_DIR ]]; then
|
|
echo "spdk-abi found at $SPDK_ABI_DIR"
|
|
cp -r "$SPDK_ABI_DIR"/* "$dest/"
|
|
else
|
|
# In case that someone run test manually and did not set existing
|
|
# spdk-abi directory via SPDK_ABI_DIR
|
|
echo "spdk-abi has not been found at $SPDK_ABI_DIR, cloning"
|
|
git clone $git_repo_abi "$dest"
|
|
fi
|
|
}
|
|
|
|
function get_release_branch() {
|
|
tag=$(git describe --tags --abbrev=0 --exclude=LTS --exclude=*-pre)
|
|
branch="${tag:0:6}.x"
|
|
echo "$branch"
|
|
}
|
|
|
|
if [ "$(uname -s)" = "FreeBSD" ]; then
|
|
echo "Not testing for shared object dependencies on FreeBSD."
|
|
exit 0
|
|
fi
|
|
|
|
rootdir=$(readlink -f $(dirname $0)/../..)
|
|
|
|
if [[ ! -f $1 ]]; then
|
|
echo "ERROR: SPDK test configuration not specified"
|
|
exit 1
|
|
fi
|
|
|
|
source $1
|
|
source "$rootdir/test/common/autotest_common.sh"
|
|
|
|
libdir="$rootdir/build/lib"
|
|
libdeps_file="$rootdir/mk/spdk.lib_deps.mk"
|
|
suppression_file="$HOME/abigail_suppressions.ini"
|
|
|
|
function check_header_filenames() {
|
|
local dups_found=0
|
|
|
|
xtrace_disable
|
|
|
|
include_headers=$(git ls-files -- include/spdk include/spdk_internal | xargs -n 1 basename)
|
|
dups=
|
|
for file in $include_headers; do
|
|
if [[ $(git ls-files "lib/**/$file" "module/**/$file" --error-unmatch 2> /dev/null) ]]; then
|
|
dups+=" $file"
|
|
dups_found=1
|
|
fi
|
|
done
|
|
|
|
xtrace_restore
|
|
|
|
if ((dups_found == 1)); then
|
|
echo "Private header file(s) found with same name as public header file."
|
|
echo "This is not allowed since it can confuse abidiff when determining if"
|
|
echo "data structure changes impact ABI."
|
|
echo $dups
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
function confirm_abi_deps() {
|
|
local processed_so=0
|
|
local abidiff_output
|
|
local release
|
|
local source_abi_dir="$rootdir/test/make/abi"
|
|
|
|
release=$(get_release_branch)
|
|
|
|
get_spdk_abi "$source_abi_dir"
|
|
echo "* Running ${FUNCNAME[0]} against the latest (${release%.*}) release" >&2
|
|
|
|
if ! hash abidiff; then
|
|
echo "Unable to check ABI compatibility. Please install abidiff."
|
|
return 1
|
|
fi
|
|
|
|
cat << EOF > ${suppression_file}
|
|
[suppress_type]
|
|
name = spdk_nvme_power_state
|
|
[suppress_type]
|
|
name = spdk_nvme_ctrlr_data
|
|
[suppress_type]
|
|
name = spdk_nvme_cdata_oacs
|
|
[suppress_type]
|
|
name = spdk_nvme_cdata_nvmf_specific
|
|
[suppress_type]
|
|
name = spdk_nvme_cmd
|
|
[suppress_type]
|
|
name = spdk_bs_opts
|
|
[suppress_type]
|
|
name = spdk_app_opts
|
|
EOF
|
|
|
|
for object in "$libdir"/libspdk_*.so; do
|
|
abidiff_output=0
|
|
|
|
so_file=$(basename $object)
|
|
if [ ! -f "$source_abi_dir/$release/$so_file" ]; then
|
|
echo "No corresponding object for $so_file in canonical directory. Skipping."
|
|
continue
|
|
fi
|
|
|
|
cmd_args=('abidiff'
|
|
$source_abi_dir/$release/$so_file "$libdir/$so_file"
|
|
'--headers-dir1' $source_abi_dir/$release/include
|
|
'--headers-dir2' $rootdir/include
|
|
'--leaf-changes-only' '--suppressions' $suppression_file)
|
|
|
|
if ! output=$("${cmd_args[@]}" --stat); then
|
|
# remove any filtered out variables.
|
|
output=$(sed "s/ [()][^)]*[)]//g" <<< "$output")
|
|
|
|
IFS="." read -r _ _ new_so_maj new_so_min < <(readlink "$libdir/$so_file")
|
|
IFS="." read -r _ _ old_so_maj old_so_min < <(readlink "$source_abi_dir/$release/$so_file")
|
|
|
|
found_abi_change=false
|
|
so_name_changed=no
|
|
|
|
if [[ $output == *"ELF SONAME changed"* ]]; then
|
|
so_name_changed=yes
|
|
fi
|
|
|
|
changed_leaf_types=0
|
|
if [[ $output =~ "leaf types summary: "([0-9]+) ]]; then
|
|
changed_leaf_types=${BASH_REMATCH[1]}
|
|
fi
|
|
|
|
removed_functions=0 changed_functions=0 added_functions=0
|
|
if [[ $output =~ "functions summary: "([0-9]+)" Removed, "([0-9]+)" Changed, "([0-9]+)" Added" ]]; then
|
|
removed_functions=${BASH_REMATCH[1]} changed_functions=${BASH_REMATCH[2]} added_functions=${BASH_REMATCH[3]}
|
|
fi
|
|
|
|
removed_vars=0 changed_vars=0 added_vars=0
|
|
if [[ $output =~ "variables summary: "([0-9]+)" Removed, "([0-9]+)" Changed, "([0-9]+)" Added" ]]; then
|
|
removed_vars=${BASH_REMATCH[1]} changed_vars=${BASH_REMATCH[2]} added_vars=${BASH_REMATCH[3]}
|
|
fi
|
|
|
|
if ((changed_leaf_types != 0)); then
|
|
if ((new_so_maj == old_so_maj)); then
|
|
abidiff_output=1
|
|
touch $fail_file
|
|
echo "Please update the major SO version for $so_file. A header accessible type has been modified since last release."
|
|
fi
|
|
found_abi_change=true
|
|
fi
|
|
|
|
if ((removed_functions != 0)) || ((removed_vars != 0)); then
|
|
if ((new_so_maj == old_so_maj)); then
|
|
abidiff_output=1
|
|
touch $fail_file
|
|
echo "Please update the major SO version for $so_file. API functions or variables have been removed since last release."
|
|
fi
|
|
found_abi_change=true
|
|
fi
|
|
|
|
if ((changed_functions != 0)) || ((changed_vars != 0)); then
|
|
if ((new_so_maj == old_so_maj)); then
|
|
abidiff_output=1
|
|
touch $fail_file
|
|
echo "Please update the major SO version for $so_file. API functions or variables have been changed since last release."
|
|
fi
|
|
found_abi_change=true
|
|
fi
|
|
|
|
if ((added_functions != 0)) || ((added_vars != 0)); then
|
|
if ((new_so_min == old_so_min && new_so_maj == old_so_maj)) && ! $found_abi_change; then
|
|
abidiff_output=1
|
|
touch $fail_file
|
|
echo "Please update the minor SO version for $so_file. API functions or variables have been added since last release."
|
|
fi
|
|
found_abi_change=true
|
|
fi
|
|
|
|
if [[ $so_name_changed == yes ]]; then
|
|
# After 22.01 LTS all SO major versions were intentionally increased. Disable this check until SPDK 22.05 release.
|
|
found_abi_change=true
|
|
if ! $found_abi_change; then
|
|
echo "SO name for $so_file changed without a change to abi. please revert that change."
|
|
touch $fail_file
|
|
fi
|
|
|
|
if ((new_so_maj != old_so_maj && new_so_min != 0)); then
|
|
echo "SO major version for $so_file was bumped. Please reset the minor version to 0."
|
|
touch $fail_file
|
|
fi
|
|
|
|
if ((new_so_min > old_so_min + 1)); then
|
|
echo "SO minor version for $so_file was incremented more than once. Please revert minor version to $((old_so_min + 1))."
|
|
touch $fail_file
|
|
fi
|
|
|
|
if ((new_so_maj > old_so_maj + 1)); then
|
|
echo "SO major version for $so_file was incremented more than once. Please revert major version to $((old_so_maj + 1))."
|
|
touch $fail_file
|
|
fi
|
|
fi
|
|
|
|
if ((abidiff_output == 1)); then
|
|
"${cmd_args[@]}" --impacted-interfaces || :
|
|
fi
|
|
fi
|
|
processed_so=$((processed_so + 1))
|
|
done
|
|
rm -f $suppression_file
|
|
echo "Processed $processed_so objects."
|
|
rm -rf "$source_abi_dir"
|
|
}
|
|
|
|
function get_lib_shortname() {
|
|
local lib=${1##*/}
|
|
echo "${lib//@(libspdk_|.so)/}"
|
|
}
|
|
|
|
function import_libs_deps_mk() {
|
|
local var_mk val_mk dep_mk fun_mk
|
|
while read -r var_mk _ val_mk; do
|
|
if [[ $var_mk == "#"* || ! $var_mk =~ (DEPDIRS-|_DEPS|_LIBS) ]]; then
|
|
continue
|
|
fi
|
|
var_mk=${var_mk#*-}
|
|
for dep_mk in $val_mk; do
|
|
fun_mk=${dep_mk//@('$('|')')/}
|
|
if [[ $fun_mk != "$dep_mk" ]]; then
|
|
eval "${fun_mk}() { echo \$$fun_mk ; }"
|
|
# Ignore any event_* dependencies. Those are based on the subsystem configuration and not readelf.
|
|
elif ((IGNORED_LIBS["$dep_mk"] == 1)) || [[ $dep_mk =~ event_ ]]; then
|
|
continue
|
|
fi
|
|
eval "$var_mk=\${$var_mk:+\$$var_mk }$dep_mk"
|
|
done
|
|
done < "$libdeps_file"
|
|
}
|
|
|
|
function confirm_deps() {
|
|
local lib=$1 deplib lib_shortname
|
|
|
|
lib_shortname=$(get_lib_shortname "$lib")
|
|
lib_make_deps=(${!lib_shortname})
|
|
|
|
symbols=($(readelf -s --wide "$lib" | grep -E "NOTYPE.*GLOBAL.*UND" | awk '{print $8}' | sort -u))
|
|
symbols_regx=$(
|
|
IFS="|"
|
|
echo "(${symbols[*]})"
|
|
)
|
|
|
|
if ((${#symbols[@]} > 0)); then
|
|
for deplib in "$libdir/"libspdk_!("$lib_shortname").so; do
|
|
readelf -s --wide "$deplib" | grep -m1 -qE "DEFAULT\s+[0-9]+\s$symbols_regx$" || continue
|
|
found_symbol_lib=$(get_lib_shortname "$deplib")
|
|
# Ignore the env_dpdk readelf dependency. We don't want people explicitly linking against it.
|
|
if [[ $found_symbol_lib != *env_dpdk* ]]; then
|
|
dep_names+=("$found_symbol_lib")
|
|
fi
|
|
done
|
|
fi
|
|
|
|
diff=$(echo "${dep_names[@]}" "${lib_make_deps[@]}" | tr ' ' '\n' | sort | uniq -u)
|
|
if [ "$diff" != "" ]; then
|
|
touch $fail_file
|
|
echo "there was a dependency mismatch in the library $lib_shortname"
|
|
echo "The makefile (spdk.lib_deps.mk) lists: '${lib_make_deps[*]}'"
|
|
echo "readelf outputs : '${dep_names[*]}'"
|
|
echo "---------------------------------------------------------------------"
|
|
fi
|
|
}
|
|
|
|
function confirm_makefile_deps() {
|
|
echo "---------------------------------------------------------------------"
|
|
# Exclude libspdk_env_dpdk.so from the library list. We don't link against this one so that
|
|
# users can define their own environment abstraction. However we do want to still check it
|
|
# for dependencies to avoid printing out a bunch of confusing symbols under the missing
|
|
# symbols section.
|
|
SPDK_LIBS=("$libdir/"libspdk_!(env_dpdk).so)
|
|
|
|
declare -A IGNORED_LIBS=()
|
|
if grep -q 'CONFIG_RDMA?=n' $rootdir/mk/config.mk; then
|
|
IGNORED_LIBS["rdma"]=1
|
|
fi
|
|
|
|
(
|
|
import_libs_deps_mk
|
|
for lib in "${SPDK_LIBS[@]}"; do confirm_deps "$lib" & done
|
|
wait
|
|
)
|
|
}
|
|
|
|
run_test "check_header_filenames" check_header_filenames
|
|
|
|
config_params=$(get_config_params)
|
|
if [ "$SPDK_TEST_OCF" -eq 1 ]; then
|
|
config_params="$config_params --with-ocf=$rootdir/ocf.a"
|
|
fi
|
|
|
|
if [[ -f $rootdir/mk/spdk.common.mk ]]; then
|
|
$MAKE $MAKEFLAGS clean
|
|
fi
|
|
|
|
./configure $config_params --with-shared
|
|
# By setting SPDK_NO_LIB_DEPS=1, we ensure that we won't create any link dependencies.
|
|
# Then we can be sure we get a valid accounting of the symbol dependencies we have.
|
|
SPDK_NO_LIB_DEPS=1 $MAKE $MAKEFLAGS
|
|
|
|
xtrace_disable
|
|
|
|
fail_file=$output_dir/check_so_deps_fail
|
|
|
|
rm -f $fail_file
|
|
|
|
run_test "confirm_abi_deps" confirm_abi_deps
|
|
|
|
run_test "confirm_makefile_deps" confirm_makefile_deps
|
|
|
|
$MAKE $MAKEFLAGS clean
|
|
|
|
if [ -f $fail_file ]; then
|
|
rm -f $fail_file
|
|
echo "shared object test failed"
|
|
exit 1
|
|
fi
|
|
|
|
xtrace_restore
|