Compare commits
75 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
752ceb0c12 | ||
|
ca470ff844 | ||
|
10807f35f9 | ||
|
64b08f6ea3 | ||
|
e2025217a7 | ||
|
a1570edd1d | ||
|
cb37376ef6 | ||
|
6b740d2c10 | ||
|
5cf63f81be | ||
|
f94c640130 | ||
|
1ea7b29ff8 | ||
|
18936662df | ||
|
1cf67849c8 | ||
|
49e5142b3c | ||
|
91c22965cc | ||
|
73c1c75f23 | ||
|
8aafde8856 | ||
|
199f14e3fd | ||
|
93b2a5420a | ||
|
731887d713 | ||
|
6f6fced5a5 | ||
|
a56704a0e1 | ||
|
a37bb7d4a5 | ||
|
dc09422cd3 | ||
|
9b420e8c00 | ||
|
d28343f894 | ||
|
b7a6b5f559 | ||
|
fce34b065d | ||
|
023a6b0b0d | ||
|
d56a2b7214 | ||
|
99379a07f1 | ||
|
14c153e67f | ||
|
27acba1262 | ||
|
b0cdf76635 | ||
|
beb7cd3829 | ||
|
4d419d55b8 | ||
|
512fcf8e58 | ||
|
2879f9d2da | ||
|
06bceceac8 | ||
|
edf5f3de0e | ||
|
f04c67984b | ||
|
c8607790cb | ||
|
08b6e24735 | ||
|
a5b0bc0cd8 | ||
|
0896f85b59 | ||
|
94abf2d8c2 | ||
|
f4c28506d5 | ||
|
53603323e5 | ||
|
64f1ea8ea4 | ||
|
1f0dd58a43 | ||
|
049e9290cf | ||
|
82c0c8ca03 | ||
|
1cf1b00b1b | ||
|
1d839c1ac3 | ||
|
9bdc45693a | ||
|
c7a0275edf | ||
|
a5a51c7b56 | ||
|
f2a113d144 | ||
|
b4ed65d26f | ||
|
26e589c3a4 | ||
|
14eeeea669 | ||
|
3f732d80d3 | ||
|
e02a868dd3 | ||
|
d02ff4c422 | ||
|
4b87c7259a | ||
|
02f9f45524 | ||
|
84c4530e9b | ||
|
0811dda8bf | ||
|
9b37f63fe9 | ||
|
edb5cd988a | ||
|
68eb748759 | ||
|
bbe2ed83dc | ||
|
d53d7a5723 | ||
|
2a1fe02d98 | ||
|
081cd04ea2 |
39
CHANGELOG.md
39
CHANGELOG.md
@ -1,6 +1,39 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## v21.01: (Upcoming Release)
|
## v21.01.2: (Upcoming Release)
|
||||||
|
|
||||||
|
## v21.01.1:
|
||||||
|
|
||||||
|
### dpdk
|
||||||
|
|
||||||
|
Added `rte_ethdev` and `rte_net` dependencies for all builds with DPDK.
|
||||||
|
|
||||||
|
Fixed compatibility issues with DPDK 19.11.
|
||||||
|
|
||||||
|
### iscsi
|
||||||
|
|
||||||
|
A security vulnerability has been identified and fixed in the SPDK iSCSI target.
|
||||||
|
A TEXT PDU with no data, but CONTINUE flag set, would result in a NULL pointer dereference
|
||||||
|
and crash the SPDK iSCSI target process. All users of the SPDK iSCSI target
|
||||||
|
are recommended to update. All SPDK versions <= v21.01 are affected.
|
||||||
|
|
||||||
|
### nbd
|
||||||
|
|
||||||
|
Fixed kernel hang when bdev is removed by always setting NBD_SET_TIMEOUT.
|
||||||
|
|
||||||
|
### nvme
|
||||||
|
|
||||||
|
Fixed segfault when removing qpair when transport connection fails (issue #1777).
|
||||||
|
|
||||||
|
### ocssd
|
||||||
|
|
||||||
|
Fixed the bug that no media event is pushed to the target bdev.
|
||||||
|
|
||||||
|
### sock
|
||||||
|
|
||||||
|
Added `enable_quickack` and `enable_placement_id` when saving JSON configuration.
|
||||||
|
|
||||||
|
## v21.01: Dynamic scheduler, vfio-user, ZNS Zone Append
|
||||||
|
|
||||||
### bdev
|
### bdev
|
||||||
|
|
||||||
@ -75,6 +108,10 @@ The `--pci-blacklist` command line option has been deprecated, replaced with
|
|||||||
The `--pci-whitelist/-W` command line options have been deprecated, replaced with
|
The `--pci-whitelist/-W` command line options have been deprecated, replaced with
|
||||||
`--pci-allowed/-A`.
|
`--pci-allowed/-A`.
|
||||||
|
|
||||||
|
Added new experimental `dynamic` scheduler that rebalances idle threads, adjusts CPU frequency
|
||||||
|
using dpdk_governor and turns idle reactor cores to interrupt mode. Please see
|
||||||
|
[scheduler documentation](https://www.spdk.io/doc/scheduler.html) for details.
|
||||||
|
|
||||||
## ioat
|
## ioat
|
||||||
|
|
||||||
The PCI BDF whitelist option has been removed from the `ioat_scan_accel_engine` RPC.
|
The PCI BDF whitelist option has been removed from the `ioat_scan_accel_engine` RPC.
|
||||||
|
2
CONFIG
2
CONFIG
@ -121,7 +121,7 @@ CONFIG_VHOST=y
|
|||||||
CONFIG_VIRTIO=y
|
CONFIG_VIRTIO=y
|
||||||
|
|
||||||
# Build custom vfio-user transport for NVMf target and NVMe initiator.
|
# Build custom vfio-user transport for NVMf target and NVMe initiator.
|
||||||
CONFIG_VFIO_USER=y
|
CONFIG_VFIO_USER=n
|
||||||
|
|
||||||
# Build with PMDK backends
|
# Build with PMDK backends
|
||||||
CONFIG_PMDK=n
|
CONFIG_PMDK=n
|
||||||
|
@ -2027,6 +2027,7 @@ show_thread(uint8_t current_page)
|
|||||||
|
|
||||||
get_data();
|
get_data();
|
||||||
|
|
||||||
|
assert(thread_number < g_threads_stats.threads.threads_count);
|
||||||
for (i = 0; i < g_threads_stats.threads.threads_count; i++) {
|
for (i = 0; i < g_threads_stats.threads.threads_count; i++) {
|
||||||
thread_info[i] = &g_threads_stats.threads.thread_info[i];
|
thread_info[i] = &g_threads_stats.threads.thread_info[i];
|
||||||
}
|
}
|
||||||
@ -2067,6 +2068,7 @@ show_core(uint8_t current_page)
|
|||||||
|
|
||||||
get_data();
|
get_data();
|
||||||
|
|
||||||
|
assert(core_number < g_cores_stats.cores.cores_count);
|
||||||
for (i = 0; i < g_cores_stats.cores.cores_count; i++) {
|
for (i = 0; i < g_cores_stats.cores.cores_count; i++) {
|
||||||
core_info[i] = &g_cores_stats.cores.core[i];
|
core_info[i] = &g_cores_stats.cores.core[i];
|
||||||
}
|
}
|
||||||
@ -2178,6 +2180,7 @@ show_poller(uint8_t current_page)
|
|||||||
get_data();
|
get_data();
|
||||||
|
|
||||||
prepare_poller_data(current_page, pollers, &count, current_page);
|
prepare_poller_data(current_page, pollers, &count, current_page);
|
||||||
|
assert(poller_number < count);
|
||||||
|
|
||||||
poller_win = newwin(POLLER_WIN_HEIGHT, POLLER_WIN_WIDTH,
|
poller_win = newwin(POLLER_WIN_HEIGHT, POLLER_WIN_WIDTH,
|
||||||
(g_max_row - poller_counter) / 2, (g_max_col - POLLER_WIN_HOR_POS) / 2);
|
(g_max_row - poller_counter) / 2, (g_max_col - POLLER_WIN_HOR_POS) / 2);
|
||||||
@ -2300,6 +2303,7 @@ show_stats(void)
|
|||||||
} else {
|
} else {
|
||||||
active_tab = THREADS_TAB;
|
active_tab = THREADS_TAB;
|
||||||
}
|
}
|
||||||
|
g_selected_row = 0;
|
||||||
current_page = 0;
|
current_page = 0;
|
||||||
switch_tab(active_tab);
|
switch_tab(active_tab);
|
||||||
break;
|
break;
|
||||||
|
32
autobuild.sh
32
autobuild.sh
@ -12,6 +12,7 @@ rootdir=$(readlink -f $(dirname $0))
|
|||||||
|
|
||||||
source "$1"
|
source "$1"
|
||||||
source "$rootdir/test/common/autotest_common.sh"
|
source "$rootdir/test/common/autotest_common.sh"
|
||||||
|
source "$rootdir/scripts/common.sh"
|
||||||
|
|
||||||
out=$output_dir
|
out=$output_dir
|
||||||
if [ -n "$SPDK_TEST_NATIVE_DPDK" ]; then
|
if [ -n "$SPDK_TEST_NATIVE_DPDK" ]; then
|
||||||
@ -50,7 +51,10 @@ function ocf_precompile() {
|
|||||||
function build_native_dpdk() {
|
function build_native_dpdk() {
|
||||||
local external_dpdk_dir
|
local external_dpdk_dir
|
||||||
local external_dpdk_base_dir
|
local external_dpdk_base_dir
|
||||||
|
local gcc_version
|
||||||
|
|
||||||
|
gcc_version=$(gcc -dumpversion)
|
||||||
|
gcc_version=${gcc_version//./}
|
||||||
external_dpdk_dir="$SPDK_RUN_EXTERNAL_DPDK"
|
external_dpdk_dir="$SPDK_RUN_EXTERNAL_DPDK"
|
||||||
external_dpdk_base_dir="$(dirname $external_dpdk_dir)"
|
external_dpdk_base_dir="$(dirname $external_dpdk_dir)"
|
||||||
|
|
||||||
@ -64,9 +68,17 @@ function build_native_dpdk() {
|
|||||||
git clone --branch $SPDK_TEST_NATIVE_DPDK --depth 1 http://dpdk.org/git/dpdk "$external_dpdk_base_dir"
|
git clone --branch $SPDK_TEST_NATIVE_DPDK --depth 1 http://dpdk.org/git/dpdk "$external_dpdk_base_dir"
|
||||||
git -C "$external_dpdk_base_dir" log --oneline -n 5
|
git -C "$external_dpdk_base_dir" log --oneline -n 5
|
||||||
|
|
||||||
dpdk_cflags="-fPIC -g -Werror -fcommon"
|
dpdk_cflags="-fPIC -g -fcommon"
|
||||||
dpdk_ldflags=""
|
dpdk_ldflags=""
|
||||||
|
|
||||||
|
if [[ $gcc_version -ge 5 ]]; then
|
||||||
|
dpdk_cflags+=" -Werror"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $gcc_version -ge 10 ]]; then
|
||||||
|
dpdk_cflags+=" -Wno-stringop-overflow"
|
||||||
|
fi
|
||||||
|
|
||||||
# the drivers we use
|
# the drivers we use
|
||||||
# net/i40e driver is not really needed by us, but it's built as a workaround
|
# net/i40e driver is not really needed by us, but it's built as a workaround
|
||||||
# for DPDK issue: https://bugs.dpdk.org/show_bug.cgi?id=576
|
# for DPDK issue: https://bugs.dpdk.org/show_bug.cgi?id=576
|
||||||
@ -112,19 +124,22 @@ function build_native_dpdk() {
|
|||||||
|
|
||||||
cd $external_dpdk_base_dir
|
cd $external_dpdk_base_dir
|
||||||
if [ "$(uname -s)" = "Linux" ]; then
|
if [ "$(uname -s)" = "Linux" ]; then
|
||||||
dpdk_cflags+=" -Wno-stringop-overflow"
|
|
||||||
# Fix for freeing device if not kernel driver configured.
|
# Fix for freeing device if not kernel driver configured.
|
||||||
# TODO: Remove once this is merged in upstream DPDK
|
# TODO: Remove once this is merged in upstream DPDK
|
||||||
if grep "20.08.0" $external_dpdk_base_dir/VERSION; then
|
if grep "20.08.0" $external_dpdk_base_dir/VERSION; then
|
||||||
wget https://github.com/spdk/dpdk/commit/64f1ced13f974e8b3d46b87c361a09eca68126f9.patch -O dpdk-pci.patch
|
wget https://github.com/spdk/dpdk/commit/64f1ced13f974e8b3d46b87c361a09eca68126f9.patch -O dpdk-pci.patch
|
||||||
wget https://github.com/spdk/dpdk/commit/c2c273d5c8fbf673623b427f8f4ab5af5ddf0e08.patch -O dpdk-qat.patch
|
wget https://github.com/spdk/dpdk/commit/c2c273d5c8fbf673623b427f8f4ab5af5ddf0e08.patch -O dpdk-qat.patch
|
||||||
else
|
elif grep "20.11\|21.02" $external_dpdk_base_dir/VERSION; then
|
||||||
wget https://github.com/karlatec/dpdk/commit/3219c0cfc38803aec10c809dde16e013b370bda9.patch -O dpdk-pci.patch
|
wget https://github.com/karlatec/dpdk/commit/3219c0cfc38803aec10c809dde16e013b370bda9.patch -O dpdk-pci.patch
|
||||||
wget https://github.com/karlatec/dpdk/commit/adf8f7638de29bc4bf9ba3faf12bbdae73acda0c.patch -O dpdk-qat.patch
|
wget https://github.com/karlatec/dpdk/commit/adf8f7638de29bc4bf9ba3faf12bbdae73acda0c.patch -O dpdk-qat.patch
|
||||||
|
else
|
||||||
|
wget https://github.com/karlatec/dpdk/commit/6fd2fa906ffdcee04e6ce5da40e61cb841be9827.patch -O dpdk-qat.patch
|
||||||
fi
|
fi
|
||||||
git config --local user.name "spdk"
|
git config --local user.name "spdk"
|
||||||
git config --local user.email "nomail@all.com"
|
git config --local user.email "nomail@all.com"
|
||||||
git am dpdk-pci.patch
|
if [[ -f dpdk-pci.patch ]]; then
|
||||||
|
git am dpdk-pci.patch
|
||||||
|
fi
|
||||||
git am dpdk-qat.patch
|
git am dpdk-qat.patch
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -222,11 +237,15 @@ function test_make_uninstall() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function build_doc() {
|
function build_doc() {
|
||||||
|
local doxygenv
|
||||||
|
doxygenv=$(doxygen --version)
|
||||||
|
|
||||||
$MAKE -C "$rootdir"/doc --no-print-directory $MAKEFLAGS &> "$out"/doxygen.log
|
$MAKE -C "$rootdir"/doc --no-print-directory $MAKEFLAGS &> "$out"/doxygen.log
|
||||||
if [ -s "$out"/doxygen.log ]; then
|
if [ -s "$out"/doxygen.log ]; then
|
||||||
cat "$out"/doxygen.log
|
cat "$out"/doxygen.log
|
||||||
echo "Doxygen errors found!"
|
echo "Doxygen errors found!"
|
||||||
exit 1
|
eq "$doxygenv" 1.8.20 || exit 1
|
||||||
|
echo "Doxygen $doxygenv detected, all warnings are potentially false positives, continuing the test"
|
||||||
fi
|
fi
|
||||||
if hash pdflatex 2> /dev/null; then
|
if hash pdflatex 2> /dev/null; then
|
||||||
$MAKE -C "$rootdir"/doc/output/latex --no-print-directory $MAKEFLAGS &>> "$out"/doxygen.log
|
$MAKE -C "$rootdir"/doc/output/latex --no-print-directory $MAKEFLAGS &>> "$out"/doxygen.log
|
||||||
@ -238,7 +257,8 @@ function build_doc() {
|
|||||||
fi
|
fi
|
||||||
$MAKE -C "$rootdir"/doc --no-print-directory $MAKEFLAGS clean &>> "$out"/doxygen.log
|
$MAKE -C "$rootdir"/doc --no-print-directory $MAKEFLAGS clean &>> "$out"/doxygen.log
|
||||||
if [ -s "$out"/doxygen.log ]; then
|
if [ -s "$out"/doxygen.log ]; then
|
||||||
rm "$out"/doxygen.log
|
# Save the log as an artifact in case we are working with potentially broken version
|
||||||
|
eq "$doxygenv" 1.8.20 || rm "$out"/doxygen.log
|
||||||
fi
|
fi
|
||||||
rm -rf "$rootdir"/doc/output
|
rm -rf "$rootdir"/doc/output
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ if [ $(git status --porcelain --ignore-submodules | wc -l) -ne 0 ]; then
|
|||||||
fi
|
fi
|
||||||
timing_exit porcelain_check
|
timing_exit porcelain_check
|
||||||
|
|
||||||
if [[ $RUN_NIGHTLY -eq 0 && $SPDK_TEST_RELEASE_BUILD -eq 0 ]]; then
|
if [[ $RUN_NIGHTLY -eq 0 ]]; then
|
||||||
timing_finish
|
timing_finish
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
@ -4,7 +4,8 @@ set -e
|
|||||||
|
|
||||||
rootdir=$(readlink -f $(dirname $0))
|
rootdir=$(readlink -f $(dirname $0))
|
||||||
|
|
||||||
conf=~/autorun-spdk.conf
|
default_conf=~/autorun-spdk.conf
|
||||||
|
conf=${1:-${default_conf}}
|
||||||
|
|
||||||
# If the configuration of tests is not provided, no tests will be carried out.
|
# If the configuration of tests is not provided, no tests will be carried out.
|
||||||
if [[ ! -f $conf ]]; then
|
if [[ ! -f $conf ]]; then
|
||||||
|
33
autotest.sh
33
autotest.sh
@ -150,16 +150,7 @@ timing_enter afterboot
|
|||||||
./scripts/setup.sh
|
./scripts/setup.sh
|
||||||
timing_exit afterboot
|
timing_exit afterboot
|
||||||
|
|
||||||
timing_enter nvmf_setup
|
|
||||||
rdma_device_init
|
|
||||||
timing_exit nvmf_setup
|
|
||||||
|
|
||||||
if [[ $SPDK_TEST_CRYPTO -eq 1 || $SPDK_TEST_REDUCE -eq 1 ]]; then
|
if [[ $SPDK_TEST_CRYPTO -eq 1 || $SPDK_TEST_REDUCE -eq 1 ]]; then
|
||||||
# Make sure that memory is distributed across all NUMA nodes - by default, all goes to
|
|
||||||
# node0, but if QAT devices are attached to a different node, all of their VFs will end
|
|
||||||
# up under that node too and memory needs to be available there for the tests.
|
|
||||||
CLEAR_HUGE=yes HUGE_EVEN_ALLOC=yes ./scripts/setup.sh
|
|
||||||
./scripts/setup.sh status
|
|
||||||
if [[ $SPDK_TEST_USE_IGB_UIO -eq 1 ]]; then
|
if [[ $SPDK_TEST_USE_IGB_UIO -eq 1 ]]; then
|
||||||
./scripts/qat_setup.sh igb_uio
|
./scripts/qat_setup.sh igb_uio
|
||||||
else
|
else
|
||||||
@ -196,8 +187,18 @@ if [ $SPDK_RUN_FUNCTIONAL_TEST -eq 1 ]; then
|
|||||||
run_test "blockdev_general" test/bdev/blockdev.sh
|
run_test "blockdev_general" test/bdev/blockdev.sh
|
||||||
run_test "bdev_raid" test/bdev/bdev_raid.sh
|
run_test "bdev_raid" test/bdev/bdev_raid.sh
|
||||||
run_test "bdevperf_config" test/bdev/bdevperf/test_config.sh
|
run_test "bdevperf_config" test/bdev/bdevperf/test_config.sh
|
||||||
if [[ $(uname -s) == Linux ]]; then
|
fi
|
||||||
run_test "spdk_dd" test/dd/dd.sh
|
|
||||||
|
if [[ $(uname -s) == Linux ]]; then
|
||||||
|
if [[ $SPDK_TEST_BLOCKDEV -eq 1 || $SPDK_TEST_URING -eq 1 ]]; then
|
||||||
|
# The crypto job also includes the SPDK_TEST_BLOCKDEV in its configuration hence the
|
||||||
|
# dd tests are executed there as well. However, these tests can take a significant
|
||||||
|
# amount of time to complete (up to 4min) on a physical system leading to a potential
|
||||||
|
# job timeout. Avoid that by skipping these tests - this should not affect the coverage
|
||||||
|
# since dd tests are still run as part of the vg jobs.
|
||||||
|
if [[ $SPDK_TEST_CRYPTO -eq 0 ]]; then
|
||||||
|
run_test "spdk_dd" test/dd/dd.sh
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -247,11 +248,17 @@ if [ $SPDK_RUN_FUNCTIONAL_TEST -eq 1 ]; then
|
|||||||
# The NVMe-oF run test cases are split out like this so that the parser that compiles the
|
# The NVMe-oF run test cases are split out like this so that the parser that compiles the
|
||||||
# list of all tests can properly differentiate them. Please do not merge them into one line.
|
# list of all tests can properly differentiate them. Please do not merge them into one line.
|
||||||
if [ "$SPDK_TEST_NVMF_TRANSPORT" = "rdma" ]; then
|
if [ "$SPDK_TEST_NVMF_TRANSPORT" = "rdma" ]; then
|
||||||
|
timing_enter rdma_setup
|
||||||
|
rdma_device_init
|
||||||
|
timing_exit rdma_setup
|
||||||
run_test "nvmf_rdma" ./test/nvmf/nvmf.sh --transport=$SPDK_TEST_NVMF_TRANSPORT
|
run_test "nvmf_rdma" ./test/nvmf/nvmf.sh --transport=$SPDK_TEST_NVMF_TRANSPORT
|
||||||
run_test "spdkcli_nvmf_rdma" ./test/spdkcli/nvmf.sh
|
run_test "spdkcli_nvmf_rdma" ./test/spdkcli/nvmf.sh --transport=$SPDK_TEST_NVMF_TRANSPORT
|
||||||
elif [ "$SPDK_TEST_NVMF_TRANSPORT" = "tcp" ]; then
|
elif [ "$SPDK_TEST_NVMF_TRANSPORT" = "tcp" ]; then
|
||||||
|
timing_enter tcp_setup
|
||||||
|
tcp_device_init
|
||||||
|
timing_exit tcp_setup
|
||||||
run_test "nvmf_tcp" ./test/nvmf/nvmf.sh --transport=$SPDK_TEST_NVMF_TRANSPORT
|
run_test "nvmf_tcp" ./test/nvmf/nvmf.sh --transport=$SPDK_TEST_NVMF_TRANSPORT
|
||||||
run_test "spdkcli_nvmf_tcp" ./test/spdkcli/nvmf.sh
|
run_test "spdkcli_nvmf_tcp" ./test/spdkcli/nvmf.sh --transport=$SPDK_TEST_NVMF_TRANSPORT
|
||||||
run_test "nvmf_identify_passthru" test/nvmf/target/identify_passthru.sh --transport=$SPDK_TEST_NVMF_TRANSPORT
|
run_test "nvmf_identify_passthru" test/nvmf/target/identify_passthru.sh --transport=$SPDK_TEST_NVMF_TRANSPORT
|
||||||
run_test "nvmf_dif" test/nvmf/target/dif.sh
|
run_test "nvmf_dif" test/nvmf/target/dif.sh
|
||||||
elif [ "$SPDK_TEST_NVMF_TRANSPORT" = "fc" ]; then
|
elif [ "$SPDK_TEST_NVMF_TRANSPORT" = "fc" ]; then
|
||||||
|
42
configure
vendored
42
configure
vendored
@ -454,36 +454,22 @@ else
|
|||||||
fi
|
fi
|
||||||
BUILD_CMD+=(-I/usr/local/include -L/usr/local/lib)
|
BUILD_CMD+=(-I/usr/local/include -L/usr/local/lib)
|
||||||
|
|
||||||
function set_os_id_version() {
|
|
||||||
if [[ -f /etc/os-release ]]; then
|
|
||||||
source /etc/os-release
|
|
||||||
fi
|
|
||||||
|
|
||||||
OSID=$ID
|
|
||||||
OSVERSION=$VERSION_ID
|
|
||||||
|
|
||||||
echo "OS-ID: $OSID | OS-Version: $OSVERSION"
|
|
||||||
}
|
|
||||||
|
|
||||||
if [[ "${CONFIG[VFIO_USER]}" = "y" ]]; then
|
if [[ "${CONFIG[VFIO_USER]}" = "y" ]]; then
|
||||||
set_os_id_version
|
|
||||||
|
|
||||||
if [[ $arch != x86_64* ]] || [[ $sys_name == "FreeBSD" ]]; then
|
if ! hash cmake; then
|
||||||
echo "Non x86_64 and Linux platform, disable CONFIG_VFIO_USER"
|
echo "ERROR: --with-vfio-user requires cmake"
|
||||||
CONFIG[VFIO_USER]="n"
|
echo "Please install then re-run this script"
|
||||||
# disable tests on ubuntu16 due to lack of macro definition in pci_regs.h
|
exit 1
|
||||||
elif [[ $OSID == "ubuntu" ]] && [[ $OSVERSION == "16.04" ]]; then
|
fi
|
||||||
echo "ubuntu16 OS, disable CONFIG_VFIO_USER"
|
if [[ ! -d /usr/include/json-c ]] && [[ ! -d /usr/local/include/json-c ]]; then
|
||||||
CONFIG[VFIO_USER]="n"
|
echo "ERROR: --with-vfio-user requires json-c-devel"
|
||||||
elif ! hash cmake; then
|
echo "Please install then re-run this script"
|
||||||
echo "cmake not installed, disable CONFIG_VFIO_USER"
|
exit 1
|
||||||
CONFIG[VFIO_USER]="n"
|
fi
|
||||||
elif [[ ! -d /usr/include/json-c ]] && [[ ! -d /usr/local/include/json-c ]]; then
|
if [[ ! -e /usr/include/cmocka.h ]] && [[ ! -e /usr/local/include/cmocka.h ]]; then
|
||||||
echo "json-c-devel not installed, disable CONFIG_VFIO_USER"
|
echo "ERROR: --with-vfio-user requires libcmocka-devel"
|
||||||
CONFIG[VFIO_USER]="n"
|
echo "Please install then re-run this script"
|
||||||
elif [[ ! -e /usr/include/cmocka.h ]] && [[ ! -e /usr/local/include/cmocka.h ]]; then
|
exit 1
|
||||||
echo "libcmocka-devel not installed, disable CONFIG_VFIO_USER"
|
|
||||||
CONFIG[VFIO_USER]="n"
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -835,6 +835,7 @@ INPUT += \
|
|||||||
peer_2_peer.md \
|
peer_2_peer.md \
|
||||||
pkgconfig.md \
|
pkgconfig.md \
|
||||||
porting.md \
|
porting.md \
|
||||||
|
scheduler.md \
|
||||||
shfmt.md \
|
shfmt.md \
|
||||||
spdkcli.md \
|
spdkcli.md \
|
||||||
spdk_top.md \
|
spdk_top.md \
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
# General Information {#general}
|
# General Information {#general}
|
||||||
|
|
||||||
- @subpage event
|
- @subpage event
|
||||||
|
- @subpage scheduler
|
||||||
- @subpage logical_volumes
|
- @subpage logical_volumes
|
||||||
- @subpage accel_fw
|
- @subpage accel_fw
|
||||||
|
@ -78,7 +78,7 @@ A detailed description of each RPC method and its parameters is also available.
|
|||||||
scripts/rpc.py bdev_nvme_attach_controller --help
|
scripts/rpc.py bdev_nvme_attach_controller --help
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
### Generate JSON-RPC methods for current configuration
|
### Generate JSON-RPC methods for current configuration {#jsonrpc_generate}
|
||||||
|
|
||||||
An initial configuration can be specified for an SPDK application via the '-c' command line parameter.
|
An initial configuration can be specified for an SPDK application via the '-c' command line parameter.
|
||||||
The configuration file is a JSON file containing all of the JSON-RPC method invocations necessary
|
The configuration file is a JSON file containing all of the JSON-RPC method invocations necessary
|
||||||
@ -206,6 +206,18 @@ Finally, call the rpc.py script with '--plugin' parameter to provide above pytho
|
|||||||
./scripts/rpc.py --plugin rpc_plugin bdev_example_create 10 4096
|
./scripts/rpc.py --plugin rpc_plugin bdev_example_create 10 4096
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
|
### Converting from legacy configuration {#jsonrpc_convert}
|
||||||
|
|
||||||
|
Starting with SPDK 20.10, legacy configuration file support has been removed.
|
||||||
|
Users with extensive configuration files already running in SPDK application,
|
||||||
|
can [generate JSON-RPC for current configuration](@ref jsonrpc_generate).
|
||||||
|
|
||||||
|
If binary for deploying the application is unavailable, the legacy configuration
|
||||||
|
file can be converted to JSON-RPC using python tool:
|
||||||
|
~~~
|
||||||
|
./scripts/config_converter.py < config.ini > config.json
|
||||||
|
~~~
|
||||||
|
|
||||||
# App Framework {#jsonrpc_components_app}
|
# App Framework {#jsonrpc_components_app}
|
||||||
|
|
||||||
## spdk_kill_instance {#rpc_spdk_kill_instance}
|
## spdk_kill_instance {#rpc_spdk_kill_instance}
|
||||||
|
@ -116,10 +116,6 @@ An NVMe over Fabrics target can be configured using JSON RPCs.
|
|||||||
The basic RPCs needed to configure the NVMe-oF subsystem are detailed below. More information about
|
The basic RPCs needed to configure the NVMe-oF subsystem are detailed below. More information about
|
||||||
working with NVMe over Fabrics specific RPCs can be found on the @ref jsonrpc_components_nvmf_tgt RPC page.
|
working with NVMe over Fabrics specific RPCs can be found on the @ref jsonrpc_components_nvmf_tgt RPC page.
|
||||||
|
|
||||||
Using .ini style configuration files for configuration of the NVMe-oF target is deprecated and should
|
|
||||||
be replaced with JSON based RPCs. .ini style configuration files can be converted to json format by way
|
|
||||||
of the new script `scripts/config_converter.py`.
|
|
||||||
|
|
||||||
## FC transport support {#nvmf_fc_transport}
|
## FC transport support {#nvmf_fc_transport}
|
||||||
|
|
||||||
To build nvmf_tgt with the FC transport, there is an additional FC LLD (Low Level Driver) code dependency.
|
To build nvmf_tgt with the FC transport, there is an additional FC LLD (Low Level Driver) code dependency.
|
||||||
|
82
doc/scheduler.md
Normal file
82
doc/scheduler.md
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
# Scheduler {#scheduler}
|
||||||
|
|
||||||
|
SPDK's event/application framework (`lib/event`) now supports scheduling of
|
||||||
|
lightweight threads. Schedulers are provided as plugins, called
|
||||||
|
implementations. A default implementation is provided, but users may wish to
|
||||||
|
write their own scheduler to integrate into broader code frameworks or meet
|
||||||
|
their performance needs.
|
||||||
|
|
||||||
|
This feature should be considered experimental and is disabled by default. When
|
||||||
|
enabled, the scheduler framework gathers data for each spdk thread and reactor
|
||||||
|
and passes it to a scheduler implementation to perform one of the following
|
||||||
|
actions.
|
||||||
|
|
||||||
|
## Actions
|
||||||
|
|
||||||
|
### Move a thread
|
||||||
|
|
||||||
|
`spdk_thread`s can be moved to another reactor. Schedulers can examine the
|
||||||
|
suggested cpu_mask value for each lightweight thread to see if the user has
|
||||||
|
requested specific reactors, or choose a reactor using whatever algorithm they
|
||||||
|
deem fit.
|
||||||
|
|
||||||
|
### Switch reactor mode
|
||||||
|
|
||||||
|
Reactors by default run in a mode that constantly polls for new actions for the
|
||||||
|
most efficient processing. Schedulers can switch a reactor into a mode that
|
||||||
|
instead waits for an event on a file descriptor. On Linux, this is implemented
|
||||||
|
using epoll. This results in reduced CPU usage but may be less responsive when
|
||||||
|
events occur. A reactor cannot enter this mode if any `spdk_threads` are
|
||||||
|
currently scheduled to it. This limitation is expected to be lifted in the
|
||||||
|
future, allowing `spdk_threads` to enter interrupt mode.
|
||||||
|
|
||||||
|
### Set frequency of CPU core
|
||||||
|
|
||||||
|
The frequency of CPU cores can be modified by the scheduler in response to
|
||||||
|
load. Only CPU cores that match the application cpu_mask may be modified. The
|
||||||
|
mechanism for controlling CPU frequency is pluggable and the default provided
|
||||||
|
implementation is called `dpdk_governor`, based on the `rte_power` library from
|
||||||
|
DPDK.
|
||||||
|
|
||||||
|
#### Known limitation
|
||||||
|
|
||||||
|
When SMT (Hyperthreading) is enabled the two logical CPU cores sharing a single
|
||||||
|
physical CPU core must run at the same frequency. If one of two of such logical
|
||||||
|
CPU cores is outside the application cpu_mask, the policy and frequency on that
|
||||||
|
core has to be managed by the administrator.
|
||||||
|
|
||||||
|
## Scheduler implementations
|
||||||
|
|
||||||
|
The scheduler in use may be controlled by JSON-RPC. Please use the
|
||||||
|
[framework_set_scheduler](jsonrpc.md/#rpc_framework_set_scheduler) RPC to
|
||||||
|
switch between schedulers or change their options.
|
||||||
|
|
||||||
|
[spdk_top](spdk_top.md#spdk_top) is a useful tool to observe the behavior of
|
||||||
|
schedulers in different scenarios and workloads.
|
||||||
|
|
||||||
|
### static [default]
|
||||||
|
|
||||||
|
The `static` scheduler is the default scheduler and does no dynamic scheduling.
|
||||||
|
Lightweight threads are distributed round-robin among reactors, respecting
|
||||||
|
their requested cpu_mask, and then they are never moved. This is equivalent to
|
||||||
|
the previous behavior of the SPDK event/application framework.
|
||||||
|
|
||||||
|
### dynamic
|
||||||
|
|
||||||
|
The `dynamic` scheduler is designed for power saving and reduction of CPU
|
||||||
|
utilization, especially in cases where workloads show large variations over
|
||||||
|
time.
|
||||||
|
|
||||||
|
Active threads are distributed equally among reactors, taking cpu_mask into
|
||||||
|
account. All idle threads are moved to the main core. Once an idle thread becomes
|
||||||
|
active, it is redistributed again.
|
||||||
|
|
||||||
|
When a reactor has no scheduled `spdk_thread`s it is switched into interrupt
|
||||||
|
mode and stops actively polling. After enough threads become active, the
|
||||||
|
reactor is switched back into poll mode and threads are assigned to it again.
|
||||||
|
|
||||||
|
The main core can contain active threads only when their execution time does
|
||||||
|
not exceed the sum of all idle threads. When no active threads are present on
|
||||||
|
the main core, the frequency of that CPU core will decrease as the load
|
||||||
|
decreases. All CPU cores corresponding to the other reactors remain at maximum
|
||||||
|
frequency.
|
@ -1088,13 +1088,11 @@ spdk_fio_get_zoned_model(struct thread_data *td, struct fio_file *f, enum zbd_zo
|
|||||||
struct spdk_fio_qpair *fio_qpair = NULL;
|
struct spdk_fio_qpair *fio_qpair = NULL;
|
||||||
const struct spdk_nvme_zns_ns_data *zns_data = NULL;
|
const struct spdk_nvme_zns_ns_data *zns_data = NULL;
|
||||||
|
|
||||||
*model = ZBD_IGNORE;
|
|
||||||
|
|
||||||
if (f->filetype != FIO_TYPE_FILE && \
|
if (f->filetype != FIO_TYPE_FILE && \
|
||||||
f->filetype != FIO_TYPE_BLOCK && \
|
f->filetype != FIO_TYPE_BLOCK && \
|
||||||
f->filetype != FIO_TYPE_CHAR) {
|
f->filetype != FIO_TYPE_CHAR) {
|
||||||
log_info("spdk/nvme: ignoring filetype: %d\n", f->filetype);
|
log_info("spdk/nvme: unsupported filetype: %d\n", f->filetype);
|
||||||
return 0;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
fio_qpair = get_fio_qpair(fio_thread, f);
|
fio_qpair = get_fio_qpair(fio_thread, f);
|
||||||
|
@ -39,6 +39,6 @@ APP = led
|
|||||||
|
|
||||||
C_SRCS := led.c
|
C_SRCS := led.c
|
||||||
|
|
||||||
SPDK_LIB_LIST = vmd log
|
SPDK_LIB_LIST = vmd log util
|
||||||
|
|
||||||
include $(SPDK_ROOT_DIR)/mk/spdk.app.mk
|
include $(SPDK_ROOT_DIR)/mk/spdk.app.mk
|
||||||
|
@ -39,6 +39,6 @@ APP = lsvmd
|
|||||||
|
|
||||||
C_SRCS := lsvmd.c
|
C_SRCS := lsvmd.c
|
||||||
|
|
||||||
SPDK_LIB_LIST = vmd log
|
SPDK_LIB_LIST = vmd log util
|
||||||
|
|
||||||
include $(SPDK_ROOT_DIR)/mk/spdk.app.mk
|
include $(SPDK_ROOT_DIR)/mk/spdk.app.mk
|
||||||
|
@ -52,6 +52,7 @@ extern "C" {
|
|||||||
#define SPDK_PCI_VID_VIRTIO 0x1af4
|
#define SPDK_PCI_VID_VIRTIO 0x1af4
|
||||||
#define SPDK_PCI_VID_CNEXLABS 0x1d1d
|
#define SPDK_PCI_VID_CNEXLABS 0x1d1d
|
||||||
#define SPDK_PCI_VID_VMWARE 0x15ad
|
#define SPDK_PCI_VID_VMWARE 0x15ad
|
||||||
|
#define SPDK_PCI_VID_REDHAT 0x1b36
|
||||||
|
|
||||||
#define SPDK_PCI_CLASS_ANY_ID 0xffffff
|
#define SPDK_PCI_CLASS_ANY_ID 0xffffff
|
||||||
/**
|
/**
|
||||||
|
@ -54,7 +54,7 @@
|
|||||||
* Patch level is incremented on maintenance branch releases and reset to 0 for each
|
* Patch level is incremented on maintenance branch releases and reset to 0 for each
|
||||||
* new major.minor release.
|
* new major.minor release.
|
||||||
*/
|
*/
|
||||||
#define SPDK_VERSION_PATCH 0
|
#define SPDK_VERSION_PATCH 2
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Version string suffix.
|
* Version string suffix.
|
||||||
|
@ -1765,7 +1765,7 @@ blob_persist_clear_clusters(spdk_bs_sequence_t *seq, struct spdk_blob_persist_ct
|
|||||||
spdk_bs_batch_t *batch;
|
spdk_bs_batch_t *batch;
|
||||||
size_t i;
|
size_t i;
|
||||||
uint64_t lba;
|
uint64_t lba;
|
||||||
uint32_t lba_count;
|
uint64_t lba_count;
|
||||||
|
|
||||||
/* Clusters don't move around in blobs. The list shrinks or grows
|
/* Clusters don't move around in blobs. The list shrinks or grows
|
||||||
* at the end, but no changes ever occur in the middle of the list.
|
* at the end, but no changes ever occur in the middle of the list.
|
||||||
@ -1778,9 +1778,10 @@ blob_persist_clear_clusters(spdk_bs_sequence_t *seq, struct spdk_blob_persist_ct
|
|||||||
lba_count = 0;
|
lba_count = 0;
|
||||||
for (i = blob->active.num_clusters; i < blob->active.cluster_array_size; i++) {
|
for (i = blob->active.num_clusters; i < blob->active.cluster_array_size; i++) {
|
||||||
uint64_t next_lba = blob->active.clusters[i];
|
uint64_t next_lba = blob->active.clusters[i];
|
||||||
uint32_t next_lba_count = bs_cluster_to_lba(bs, 1);
|
uint64_t next_lba_count = bs_cluster_to_lba(bs, 1);
|
||||||
|
|
||||||
if (next_lba > 0 && (lba + lba_count) == next_lba) {
|
if (next_lba > 0 && (lba + lba_count) == next_lba &&
|
||||||
|
(lba_count + next_lba_count <= UINT32_MAX)) {
|
||||||
/* This cluster is contiguous with the previous one. */
|
/* This cluster is contiguous with the previous one. */
|
||||||
lba_count += next_lba_count;
|
lba_count += next_lba_count;
|
||||||
continue;
|
continue;
|
||||||
@ -4340,6 +4341,12 @@ bs_load_super_cpl(spdk_bs_sequence_t *seq, void *cb_arg, int bserrno)
|
|||||||
}
|
}
|
||||||
ctx->bs->md_start = ctx->super->md_start;
|
ctx->bs->md_start = ctx->super->md_start;
|
||||||
ctx->bs->md_len = ctx->super->md_len;
|
ctx->bs->md_len = ctx->super->md_len;
|
||||||
|
rc = spdk_bit_array_resize(&ctx->bs->open_blobids, ctx->bs->md_len);
|
||||||
|
if (rc < 0) {
|
||||||
|
bs_load_ctx_fail(ctx, -ENOMEM);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ctx->bs->total_data_clusters = ctx->bs->total_clusters - spdk_divide_round_up(
|
ctx->bs->total_data_clusters = ctx->bs->total_clusters - spdk_divide_round_up(
|
||||||
ctx->bs->md_start + ctx->bs->md_len, ctx->bs->pages_per_cluster);
|
ctx->bs->md_start + ctx->bs->md_len, ctx->bs->pages_per_cluster);
|
||||||
ctx->bs->super_blob = ctx->super->super_blob;
|
ctx->bs->super_blob = ctx->super->super_blob;
|
||||||
@ -4911,7 +4918,7 @@ spdk_bs_init(struct spdk_bs_dev *dev, struct spdk_bs_opts *o,
|
|||||||
|
|
||||||
lba = num_md_lba;
|
lba = num_md_lba;
|
||||||
while (lba < ctx->bs->dev->blockcnt) {
|
while (lba < ctx->bs->dev->blockcnt) {
|
||||||
lba_count = spdk_min(UINT32_MAX, ctx->bs->dev->blockcnt - lba);
|
lba_count = spdk_min(UINT32_MAX - 127, ctx->bs->dev->blockcnt - lba);
|
||||||
switch (opts.clear_method) {
|
switch (opts.clear_method) {
|
||||||
case BS_CLEAR_WITH_UNMAP:
|
case BS_CLEAR_WITH_UNMAP:
|
||||||
/* Trim data clusters */
|
/* Trim data clusters */
|
||||||
|
@ -51,7 +51,7 @@ DPDK_INC := -I$(DPDK_INC_DIR)
|
|||||||
DPDK_LIB_LIST = rte_eal rte_mempool rte_ring rte_mbuf rte_pci rte_bus_pci rte_mempool_ring
|
DPDK_LIB_LIST = rte_eal rte_mempool rte_ring rte_mbuf rte_pci rte_bus_pci rte_mempool_ring
|
||||||
|
|
||||||
ifeq ($(OS),Linux)
|
ifeq ($(OS),Linux)
|
||||||
DPDK_LIB_LIST += rte_power
|
DPDK_LIB_LIST += rte_power rte_ethdev rte_net
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# DPDK 20.05 eal dependency
|
# DPDK 20.05 eal dependency
|
||||||
@ -101,7 +101,7 @@ endif
|
|||||||
LINK_HASH=n
|
LINK_HASH=n
|
||||||
|
|
||||||
ifeq ($(CONFIG_VHOST),y)
|
ifeq ($(CONFIG_VHOST),y)
|
||||||
DPDK_LIB_LIST += rte_vhost rte_net
|
DPDK_LIB_LIST += rte_vhost
|
||||||
LINK_HASH=y
|
LINK_HASH=y
|
||||||
ifneq ($(DPDK_FRAMEWORK),y)
|
ifneq ($(DPDK_FRAMEWORK),y)
|
||||||
DPDK_LIB_LIST += rte_cryptodev
|
DPDK_LIB_LIST += rte_cryptodev
|
||||||
|
@ -1238,7 +1238,11 @@ vtophys_iommu_device_event(const char *device_name,
|
|||||||
RTE_DEV_FOREACH(dev, "bus=pci", &dev_iter) {
|
RTE_DEV_FOREACH(dev, "bus=pci", &dev_iter) {
|
||||||
if (strcmp(dev->name, device_name) == 0) {
|
if (strcmp(dev->name, device_name) == 0) {
|
||||||
struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(dev);
|
struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(dev);
|
||||||
|
#if RTE_VERSION < RTE_VERSION_NUM(20, 11, 0, 0)
|
||||||
|
if (pci_dev->kdrv == RTE_KDRV_VFIO) {
|
||||||
|
#else
|
||||||
if (pci_dev->kdrv == RTE_PCI_KDRV_VFIO) {
|
if (pci_dev->kdrv == RTE_PCI_KDRV_VFIO) {
|
||||||
|
#endif
|
||||||
/* This is a new PCI device using vfio */
|
/* This is a new PCI device using vfio */
|
||||||
g_vfio.device_ref++;
|
g_vfio.device_ref++;
|
||||||
}
|
}
|
||||||
@ -1267,7 +1271,11 @@ vtophys_iommu_device_event(const char *device_name,
|
|||||||
RTE_DEV_FOREACH(dev, "bus=pci", &dev_iter) {
|
RTE_DEV_FOREACH(dev, "bus=pci", &dev_iter) {
|
||||||
if (strcmp(dev->name, device_name) == 0) {
|
if (strcmp(dev->name, device_name) == 0) {
|
||||||
struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(dev);
|
struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(dev);
|
||||||
|
#if RTE_VERSION < RTE_VERSION_NUM(20, 11, 0, 0)
|
||||||
|
if (pci_dev->kdrv == RTE_KDRV_VFIO) {
|
||||||
|
#else
|
||||||
if (pci_dev->kdrv == RTE_PCI_KDRV_VFIO) {
|
if (pci_dev->kdrv == RTE_PCI_KDRV_VFIO) {
|
||||||
|
#endif
|
||||||
/* This is a PCI device using vfio */
|
/* This is a PCI device using vfio */
|
||||||
g_vfio.device_ref--;
|
g_vfio.device_ref--;
|
||||||
}
|
}
|
||||||
@ -1362,7 +1370,11 @@ vtophys_iommu_init(void)
|
|||||||
RTE_DEV_FOREACH(dev, "bus=pci", &dev_iter) {
|
RTE_DEV_FOREACH(dev, "bus=pci", &dev_iter) {
|
||||||
struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(dev);
|
struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(dev);
|
||||||
|
|
||||||
|
#if RTE_VERSION < RTE_VERSION_NUM(20, 11, 0, 0)
|
||||||
|
if (pci_dev->kdrv == RTE_KDRV_VFIO) {
|
||||||
|
#else
|
||||||
if (pci_dev->kdrv == RTE_PCI_KDRV_VFIO) {
|
if (pci_dev->kdrv == RTE_PCI_KDRV_VFIO) {
|
||||||
|
#endif
|
||||||
/* This is a PCI device using vfio */
|
/* This is a PCI device using vfio */
|
||||||
g_vfio.device_ref++;
|
g_vfio.device_ref++;
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include <rte_devargs.h>
|
#include <rte_devargs.h>
|
||||||
#include "spdk/env.h"
|
#include "spdk/env.h"
|
||||||
#include "spdk/log.h"
|
#include "spdk/log.h"
|
||||||
|
#include "spdk/string.h"
|
||||||
|
|
||||||
#define SYSFS_PCI_DRIVERS "/sys/bus/pci/drivers"
|
#define SYSFS_PCI_DRIVERS "/sys/bus/pci/drivers"
|
||||||
|
|
||||||
@ -63,6 +64,28 @@ static TAILQ_HEAD(, spdk_pci_device) g_pci_hotplugged_devices =
|
|||||||
TAILQ_HEAD_INITIALIZER(g_pci_hotplugged_devices);
|
TAILQ_HEAD_INITIALIZER(g_pci_hotplugged_devices);
|
||||||
static TAILQ_HEAD(, spdk_pci_driver) g_pci_drivers = TAILQ_HEAD_INITIALIZER(g_pci_drivers);
|
static TAILQ_HEAD(, spdk_pci_driver) g_pci_drivers = TAILQ_HEAD_INITIALIZER(g_pci_drivers);
|
||||||
|
|
||||||
|
struct env_devargs {
|
||||||
|
struct rte_bus *bus;
|
||||||
|
char name[128];
|
||||||
|
uint64_t allowed_at;
|
||||||
|
TAILQ_ENTRY(env_devargs) link;
|
||||||
|
};
|
||||||
|
static TAILQ_HEAD(, env_devargs) g_env_devargs = TAILQ_HEAD_INITIALIZER(g_env_devargs);
|
||||||
|
|
||||||
|
static struct env_devargs *
|
||||||
|
find_env_devargs(struct rte_bus *bus, const char *name)
|
||||||
|
{
|
||||||
|
struct env_devargs *da;
|
||||||
|
|
||||||
|
TAILQ_FOREACH(da, &g_env_devargs, link) {
|
||||||
|
if (bus == da->bus && !strcmp(name, da->name)) {
|
||||||
|
return da;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
map_bar_rte(struct spdk_pci_device *device, uint32_t bar,
|
map_bar_rte(struct spdk_pci_device *device, uint32_t bar,
|
||||||
void **mapped_addr, uint64_t *phys_addr, uint64_t *size)
|
void **mapped_addr, uint64_t *phys_addr, uint64_t *size)
|
||||||
@ -448,6 +471,39 @@ pci_device_init(struct rte_pci_driver *_drv,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_allowed_at(struct rte_devargs *rte_da, uint64_t tsc)
|
||||||
|
{
|
||||||
|
struct env_devargs *env_da;
|
||||||
|
|
||||||
|
env_da = find_env_devargs(rte_da->bus, rte_da->name);
|
||||||
|
if (env_da == NULL) {
|
||||||
|
env_da = calloc(1, sizeof(*env_da));
|
||||||
|
if (env_da == NULL) {
|
||||||
|
SPDK_ERRLOG("could not set_allowed_at for device %s\n", rte_da->name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
env_da->bus = rte_da->bus;
|
||||||
|
spdk_strcpy_pad(env_da->name, rte_da->name, sizeof(env_da->name), 0);
|
||||||
|
TAILQ_INSERT_TAIL(&g_env_devargs, env_da, link);
|
||||||
|
}
|
||||||
|
|
||||||
|
env_da->allowed_at = tsc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t
|
||||||
|
get_allowed_at(struct rte_devargs *rte_da)
|
||||||
|
{
|
||||||
|
struct env_devargs *env_da;
|
||||||
|
|
||||||
|
env_da = find_env_devargs(rte_da->bus, rte_da->name);
|
||||||
|
if (env_da) {
|
||||||
|
return env_da->allowed_at;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
pci_device_fini(struct rte_pci_device *_dev)
|
pci_device_fini(struct rte_pci_device *_dev)
|
||||||
{
|
{
|
||||||
@ -468,7 +524,7 @@ pci_device_fini(struct rte_pci_device *_dev)
|
|||||||
|
|
||||||
/* remove our allowed_at option */
|
/* remove our allowed_at option */
|
||||||
if (_dev->device.devargs) {
|
if (_dev->device.devargs) {
|
||||||
_dev->device.devargs->data = NULL;
|
set_allowed_at(_dev->device.devargs, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(!dev->internal.removed);
|
assert(!dev->internal.removed);
|
||||||
@ -541,8 +597,8 @@ scan_pci_bus(bool delay_init)
|
|||||||
rte_dev->device.devargs = da;
|
rte_dev->device.devargs = da;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (da->data) {
|
if (get_allowed_at(da)) {
|
||||||
uint64_t allowed_at = (uint64_t)(uintptr_t)da->data;
|
uint64_t allowed_at = get_allowed_at(da);
|
||||||
|
|
||||||
/* this device was seen by spdk before... */
|
/* this device was seen by spdk before... */
|
||||||
if (da->policy == RTE_DEV_BLOCKED && allowed_at <= now) {
|
if (da->policy == RTE_DEV_BLOCKED && allowed_at <= now) {
|
||||||
@ -554,10 +610,10 @@ scan_pci_bus(bool delay_init)
|
|||||||
|
|
||||||
if (delay_init) {
|
if (delay_init) {
|
||||||
da->policy = RTE_DEV_BLOCKED;
|
da->policy = RTE_DEV_BLOCKED;
|
||||||
da->data = (void *)(now + 2 * spdk_get_ticks_hz());
|
set_allowed_at(da, now + 2 * spdk_get_ticks_hz());
|
||||||
} else {
|
} else {
|
||||||
da->policy = RTE_DEV_ALLOWED;
|
da->policy = RTE_DEV_ALLOWED;
|
||||||
da->data = (void *)(uintptr_t)now;
|
set_allowed_at(da, now);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -638,8 +694,8 @@ spdk_pci_device_attach(struct spdk_pci_driver *driver,
|
|||||||
|
|
||||||
rte_dev = dev->dev_handle;
|
rte_dev = dev->dev_handle;
|
||||||
da = rte_dev->device.devargs;
|
da = rte_dev->device.devargs;
|
||||||
if (da && da->data) {
|
if (da && get_allowed_at(da)) {
|
||||||
da->data = (void *)(uintptr_t)spdk_get_ticks();
|
set_allowed_at(da, spdk_get_ticks());
|
||||||
da->policy = RTE_DEV_ALLOWED;
|
da->policy = RTE_DEV_ALLOWED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1010,8 +1010,10 @@ void
|
|||||||
spdk_reactors_start(void)
|
spdk_reactors_start(void)
|
||||||
{
|
{
|
||||||
struct spdk_reactor *reactor;
|
struct spdk_reactor *reactor;
|
||||||
|
struct spdk_cpuset tmp_cpumask = {};
|
||||||
uint32_t i, current_core;
|
uint32_t i, current_core;
|
||||||
int rc;
|
int rc;
|
||||||
|
char thread_name[32];
|
||||||
|
|
||||||
g_rusage_period = (CONTEXT_SWITCH_MONITOR_PERIOD * spdk_get_ticks_hz()) / SPDK_SEC_TO_USEC;
|
g_rusage_period = (CONTEXT_SWITCH_MONITOR_PERIOD * spdk_get_ticks_hz()) / SPDK_SEC_TO_USEC;
|
||||||
g_reactor_state = SPDK_REACTOR_STATE_RUNNING;
|
g_reactor_state = SPDK_REACTOR_STATE_RUNNING;
|
||||||
@ -1030,6 +1032,14 @@ spdk_reactors_start(void)
|
|||||||
assert(false);
|
assert(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* For now, for each reactor spawn one thread. */
|
||||||
|
snprintf(thread_name, sizeof(thread_name), "reactor_%u", reactor->lcore);
|
||||||
|
|
||||||
|
spdk_cpuset_zero(&tmp_cpumask);
|
||||||
|
spdk_cpuset_set_cpu(&tmp_cpumask, i, true);
|
||||||
|
|
||||||
|
spdk_thread_create(thread_name, &tmp_cpumask);
|
||||||
}
|
}
|
||||||
spdk_cpuset_set_cpu(&g_reactor_core_mask, i, true);
|
spdk_cpuset_set_cpu(&g_reactor_core_mask, i, true);
|
||||||
}
|
}
|
||||||
|
@ -315,6 +315,16 @@ iscsi_parse_params(struct iscsi_param **params, const uint8_t *data,
|
|||||||
char *p;
|
char *p;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
/* Spec does not disallow TEXT PDUs with zero length, just return
|
||||||
|
* immediately in that case, since there is no param data to parse
|
||||||
|
* and any existing partial parameter would remain as-is.
|
||||||
|
*/
|
||||||
|
if (len == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(data != NULL);
|
||||||
|
|
||||||
/* strip the partial text parameters if previous PDU have C enabled */
|
/* strip the partial text parameters if previous PDU have C enabled */
|
||||||
if (partial_parameter && *partial_parameter) {
|
if (partial_parameter && *partial_parameter) {
|
||||||
for (i = 0; i < len && data[i] != '\0'; i++) {
|
for (i = 0; i < len && data[i] != '\0'; i++) {
|
||||||
|
@ -50,6 +50,7 @@
|
|||||||
#define GET_IO_LOOP_COUNT 16
|
#define GET_IO_LOOP_COUNT 16
|
||||||
#define NBD_BUSY_WAITING_MS 1000
|
#define NBD_BUSY_WAITING_MS 1000
|
||||||
#define NBD_BUSY_POLLING_INTERVAL_US 20000
|
#define NBD_BUSY_POLLING_INTERVAL_US 20000
|
||||||
|
#define NBD_IO_TIMEOUT_S 60
|
||||||
|
|
||||||
enum nbd_io_state_t {
|
enum nbd_io_state_t {
|
||||||
/* Receiving or ready to receive nbd request header */
|
/* Receiving or ready to receive nbd request header */
|
||||||
@ -922,6 +923,17 @@ nbd_start_complete(struct spdk_nbd_start_ctx *ctx)
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef NBD_SET_TIMEOUT
|
||||||
|
rc = ioctl(ctx->nbd->dev_fd, NBD_SET_TIMEOUT, NBD_IO_TIMEOUT_S);
|
||||||
|
if (rc == -1) {
|
||||||
|
SPDK_ERRLOG("ioctl(NBD_SET_TIMEOUT) failed: %s\n", spdk_strerror(errno));
|
||||||
|
rc = -errno;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
SPDK_NOTICELOG("ioctl(NBD_SET_TIMEOUT) is not supported.\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef NBD_FLAG_SEND_TRIM
|
#ifdef NBD_FLAG_SEND_TRIM
|
||||||
rc = ioctl(ctx->nbd->dev_fd, NBD_SET_FLAGS, NBD_FLAG_SEND_TRIM);
|
rc = ioctl(ctx->nbd->dev_fd, NBD_SET_FLAGS, NBD_FLAG_SEND_TRIM);
|
||||||
if (rc == -1) {
|
if (rc == -1) {
|
||||||
|
@ -418,8 +418,12 @@ spdk_nvme_ctrlr_alloc_io_qpair(struct spdk_nvme_ctrlr *ctrlr,
|
|||||||
rc = spdk_nvme_ctrlr_connect_io_qpair(ctrlr, qpair);
|
rc = spdk_nvme_ctrlr_connect_io_qpair(ctrlr, qpair);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
SPDK_ERRLOG("nvme_transport_ctrlr_connect_io_qpair() failed\n");
|
SPDK_ERRLOG("nvme_transport_ctrlr_connect_io_qpair() failed\n");
|
||||||
|
nvme_robust_mutex_lock(&ctrlr->ctrlr_lock);
|
||||||
|
nvme_ctrlr_proc_remove_io_qpair(qpair);
|
||||||
TAILQ_REMOVE(&ctrlr->active_io_qpairs, qpair, tailq);
|
TAILQ_REMOVE(&ctrlr->active_io_qpairs, qpair, tailq);
|
||||||
|
spdk_bit_array_set(ctrlr->free_io_qids, qpair->id);
|
||||||
nvme_transport_ctrlr_delete_io_qpair(ctrlr, qpair);
|
nvme_transport_ctrlr_delete_io_qpair(ctrlr, qpair);
|
||||||
|
nvme_robust_mutex_unlock(&ctrlr->ctrlr_lock);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -481,6 +481,7 @@ struct spdk_nvme_ns {
|
|||||||
uint32_t md_size;
|
uint32_t md_size;
|
||||||
uint32_t pi_type;
|
uint32_t pi_type;
|
||||||
uint32_t sectors_per_max_io;
|
uint32_t sectors_per_max_io;
|
||||||
|
uint32_t sectors_per_max_io_no_md;
|
||||||
uint32_t sectors_per_stripe;
|
uint32_t sectors_per_stripe;
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
uint16_t flags;
|
uint16_t flags;
|
||||||
|
@ -64,6 +64,7 @@ nvme_ns_set_identify_data(struct spdk_nvme_ns *ns)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ns->sectors_per_max_io = spdk_nvme_ns_get_max_io_xfer_size(ns) / ns->extended_lba_size;
|
ns->sectors_per_max_io = spdk_nvme_ns_get_max_io_xfer_size(ns) / ns->extended_lba_size;
|
||||||
|
ns->sectors_per_max_io_no_md = spdk_nvme_ns_get_max_io_xfer_size(ns) / ns->sector_size;
|
||||||
|
|
||||||
if (nsdata->noiob) {
|
if (nsdata->noiob) {
|
||||||
ns->sectors_per_stripe = nsdata->noiob;
|
ns->sectors_per_stripe = nsdata->noiob;
|
||||||
@ -556,6 +557,7 @@ void nvme_ns_destruct(struct spdk_nvme_ns *ns)
|
|||||||
ns->md_size = 0;
|
ns->md_size = 0;
|
||||||
ns->pi_type = 0;
|
ns->pi_type = 0;
|
||||||
ns->sectors_per_max_io = 0;
|
ns->sectors_per_max_io = 0;
|
||||||
|
ns->sectors_per_max_io_no_md = 0;
|
||||||
ns->sectors_per_stripe = 0;
|
ns->sectors_per_stripe = 0;
|
||||||
ns->flags = 0;
|
ns->flags = 0;
|
||||||
ns->csi = SPDK_NVME_CSI_NVM;
|
ns->csi = SPDK_NVME_CSI_NVM;
|
||||||
|
@ -62,19 +62,27 @@ nvme_ns_check_request_length(uint32_t lba_count, uint32_t sectors_per_max_io,
|
|||||||
return child_per_io >= qdepth;
|
return child_per_io >= qdepth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
_nvme_md_excluded_from_xfer(struct spdk_nvme_ns *ns, uint32_t io_flags)
|
||||||
|
{
|
||||||
|
return (io_flags & SPDK_NVME_IO_FLAGS_PRACT) &&
|
||||||
|
(ns->flags & SPDK_NVME_NS_EXTENDED_LBA_SUPPORTED) &&
|
||||||
|
(ns->flags & SPDK_NVME_NS_DPS_PI_SUPPORTED) &&
|
||||||
|
(ns->md_size == 8);
|
||||||
|
}
|
||||||
|
|
||||||
static inline uint32_t
|
static inline uint32_t
|
||||||
_nvme_get_host_buffer_sector_size(struct spdk_nvme_ns *ns, uint32_t io_flags)
|
_nvme_get_host_buffer_sector_size(struct spdk_nvme_ns *ns, uint32_t io_flags)
|
||||||
{
|
{
|
||||||
uint32_t sector_size = ns->extended_lba_size;
|
return _nvme_md_excluded_from_xfer(ns, io_flags) ?
|
||||||
|
ns->sector_size : ns->extended_lba_size;
|
||||||
|
}
|
||||||
|
|
||||||
if ((io_flags & SPDK_NVME_IO_FLAGS_PRACT) &&
|
static inline uint32_t
|
||||||
(ns->flags & SPDK_NVME_NS_EXTENDED_LBA_SUPPORTED) &&
|
_nvme_get_sectors_per_max_io(struct spdk_nvme_ns *ns, uint32_t io_flags)
|
||||||
(ns->flags & SPDK_NVME_NS_DPS_PI_SUPPORTED) &&
|
{
|
||||||
(ns->md_size == 8)) {
|
return _nvme_md_excluded_from_xfer(ns, io_flags) ?
|
||||||
sector_size -= 8;
|
ns->sectors_per_max_io_no_md : ns->sectors_per_max_io;
|
||||||
}
|
|
||||||
|
|
||||||
return sector_size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct nvme_request *
|
static struct nvme_request *
|
||||||
@ -393,7 +401,7 @@ _nvme_ns_cmd_rw(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
|
|||||||
{
|
{
|
||||||
struct nvme_request *req;
|
struct nvme_request *req;
|
||||||
uint32_t sector_size = _nvme_get_host_buffer_sector_size(ns, io_flags);
|
uint32_t sector_size = _nvme_get_host_buffer_sector_size(ns, io_flags);
|
||||||
uint32_t sectors_per_max_io = ns->sectors_per_max_io;
|
uint32_t sectors_per_max_io = _nvme_get_sectors_per_max_io(ns, io_flags);
|
||||||
uint32_t sectors_per_stripe = ns->sectors_per_stripe;
|
uint32_t sectors_per_stripe = ns->sectors_per_stripe;
|
||||||
|
|
||||||
req = nvme_allocate_request(qpair, payload, lba_count * sector_size, lba_count * ns->md_size,
|
req = nvme_allocate_request(qpair, payload, lba_count * sector_size, lba_count * ns->md_size,
|
||||||
|
@ -918,7 +918,6 @@ nvme_pcie_qpair_build_contig_hw_sgl_request(struct spdk_nvme_qpair *qpair, struc
|
|||||||
|
|
||||||
length = req->payload_size;
|
length = req->payload_size;
|
||||||
virt_addr = req->payload.contig_or_cb_arg + req->payload_offset;
|
virt_addr = req->payload.contig_or_cb_arg + req->payload_offset;
|
||||||
mapping_length = length;
|
|
||||||
|
|
||||||
while (length > 0) {
|
while (length > 0) {
|
||||||
if (nseg >= NVME_MAX_SGL_DESCRIPTORS) {
|
if (nseg >= NVME_MAX_SGL_DESCRIPTORS) {
|
||||||
@ -932,6 +931,7 @@ nvme_pcie_qpair_build_contig_hw_sgl_request(struct spdk_nvme_qpair *qpair, struc
|
|||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mapping_length = length;
|
||||||
phys_addr = spdk_vtophys(virt_addr, &mapping_length);
|
phys_addr = spdk_vtophys(virt_addr, &mapping_length);
|
||||||
if (phys_addr == SPDK_VTOPHYS_ERROR) {
|
if (phys_addr == SPDK_VTOPHYS_ERROR) {
|
||||||
nvme_pcie_fail_request_bad_vtophys(qpair, tr);
|
nvme_pcie_fail_request_bad_vtophys(qpair, tr);
|
||||||
|
@ -94,6 +94,9 @@ static const struct nvme_quirk nvme_quirks[] = {
|
|||||||
NVME_INTEL_QUIRK_NO_LOG_PAGES |
|
NVME_INTEL_QUIRK_NO_LOG_PAGES |
|
||||||
NVME_QUIRK_MAXIMUM_PCI_ACCESS_WIDTH
|
NVME_QUIRK_MAXIMUM_PCI_ACCESS_WIDTH
|
||||||
},
|
},
|
||||||
|
{ {SPDK_PCI_CLASS_NVME, SPDK_PCI_VID_REDHAT, 0x0010, SPDK_PCI_ANY_ID, SPDK_PCI_ANY_ID},
|
||||||
|
NVME_QUIRK_MAXIMUM_PCI_ACCESS_WIDTH
|
||||||
|
},
|
||||||
{ {SPDK_PCI_CLASS_NVME, SPDK_PCI_VID_CNEXLABS, 0x1f1f, SPDK_PCI_ANY_ID, SPDK_PCI_ANY_ID},
|
{ {SPDK_PCI_CLASS_NVME, SPDK_PCI_VID_CNEXLABS, 0x1f1f, SPDK_PCI_ANY_ID, SPDK_PCI_ANY_ID},
|
||||||
NVME_QUIRK_IDENTIFY_CNS |
|
NVME_QUIRK_IDENTIFY_CNS |
|
||||||
NVME_QUIRK_OCSSD
|
NVME_QUIRK_OCSSD
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
*
|
*
|
||||||
* Copyright (c) Intel Corporation. All rights reserved.
|
* Copyright (c) Intel Corporation. All rights reserved.
|
||||||
* Copyright (c) 2019, 2020 Mellanox Technologies LTD. All rights reserved.
|
* Copyright (c) 2019-2021 Mellanox Technologies LTD. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
@ -944,6 +944,11 @@ nvmf_rdma_resize_cq(struct spdk_nvmf_rdma_qpair *rqpair, struct spdk_nvmf_rdma_d
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (rpoller->num_cqe != num_cqe) {
|
if (rpoller->num_cqe != num_cqe) {
|
||||||
|
if (device->context->device->transport_type == IBV_TRANSPORT_IWARP) {
|
||||||
|
SPDK_ERRLOG("iWARP doesn't support CQ resize. Current capacity %u, required %u\n"
|
||||||
|
"Using CQ of insufficient size may lead to CQ overrun\n", rpoller->num_cqe, num_cqe);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if (required_num_wr > device->attr.max_cqe) {
|
if (required_num_wr > device->attr.max_cqe) {
|
||||||
SPDK_ERRLOG("RDMA CQE requirement (%d) exceeds device max_cqe limitation (%d)\n",
|
SPDK_ERRLOG("RDMA CQE requirement (%d) exceeds device max_cqe limitation (%d)\n",
|
||||||
required_num_wr, device->attr.max_cqe);
|
required_num_wr, device->attr.max_cqe);
|
||||||
@ -4106,19 +4111,24 @@ nvmf_rdma_qpair_abort_request(struct spdk_nvmf_qpair *qpair,
|
|||||||
struct spdk_nvmf_rdma_transport *rtransport;
|
struct spdk_nvmf_rdma_transport *rtransport;
|
||||||
struct spdk_nvmf_transport *transport;
|
struct spdk_nvmf_transport *transport;
|
||||||
uint16_t cid;
|
uint16_t cid;
|
||||||
uint32_t i;
|
uint32_t i, max_req_count;
|
||||||
struct spdk_nvmf_rdma_request *rdma_req_to_abort = NULL;
|
struct spdk_nvmf_rdma_request *rdma_req_to_abort = NULL, *rdma_req;
|
||||||
|
|
||||||
rqpair = SPDK_CONTAINEROF(qpair, struct spdk_nvmf_rdma_qpair, qpair);
|
rqpair = SPDK_CONTAINEROF(qpair, struct spdk_nvmf_rdma_qpair, qpair);
|
||||||
rtransport = SPDK_CONTAINEROF(qpair->transport, struct spdk_nvmf_rdma_transport, transport);
|
rtransport = SPDK_CONTAINEROF(qpair->transport, struct spdk_nvmf_rdma_transport, transport);
|
||||||
transport = &rtransport->transport;
|
transport = &rtransport->transport;
|
||||||
|
|
||||||
cid = req->cmd->nvme_cmd.cdw10_bits.abort.cid;
|
cid = req->cmd->nvme_cmd.cdw10_bits.abort.cid;
|
||||||
|
max_req_count = rqpair->srq == NULL ? rqpair->max_queue_depth : rqpair->poller->max_srq_depth;
|
||||||
|
|
||||||
for (i = 0; i < rqpair->max_queue_depth; i++) {
|
for (i = 0; i < max_req_count; i++) {
|
||||||
if (rqpair->resources->reqs[i].state != RDMA_REQUEST_STATE_FREE &&
|
rdma_req = &rqpair->resources->reqs[i];
|
||||||
rqpair->resources->reqs[i].req.cmd->nvme_cmd.cid == cid) {
|
/* When SRQ == NULL, rqpair has its own requests and req.qpair pointer always points to the qpair
|
||||||
rdma_req_to_abort = &rqpair->resources->reqs[i];
|
* When SRQ != NULL all rqpairs share common requests and qpair pointer is assigned when we start to
|
||||||
|
* process a request. So in both cases all requests which are not in FREE state have valid qpair ptr */
|
||||||
|
if (rdma_req->state != RDMA_REQUEST_STATE_FREE && rdma_req->req.cmd->nvme_cmd.cid == cid &&
|
||||||
|
rdma_req->req.qpair == qpair) {
|
||||||
|
rdma_req_to_abort = rdma_req;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -832,6 +832,8 @@ spdk_sock_write_config_json(struct spdk_json_write_ctx *w)
|
|||||||
spdk_json_write_named_uint32(w, "send_buf_size", opts.send_buf_size);
|
spdk_json_write_named_uint32(w, "send_buf_size", opts.send_buf_size);
|
||||||
spdk_json_write_named_bool(w, "enable_recv_pipe", opts.enable_recv_pipe);
|
spdk_json_write_named_bool(w, "enable_recv_pipe", opts.enable_recv_pipe);
|
||||||
spdk_json_write_named_bool(w, "enable_zerocopy_send", opts.enable_zerocopy_send);
|
spdk_json_write_named_bool(w, "enable_zerocopy_send", opts.enable_zerocopy_send);
|
||||||
|
spdk_json_write_named_bool(w, "enable_quickack", opts.enable_quickack);
|
||||||
|
spdk_json_write_named_bool(w, "enable_placement_id", opts.enable_placement_id);
|
||||||
spdk_json_write_object_end(w);
|
spdk_json_write_object_end(w);
|
||||||
spdk_json_write_object_end(w);
|
spdk_json_write_object_end(w);
|
||||||
} else {
|
} else {
|
||||||
|
@ -85,8 +85,8 @@ int
|
|||||||
spdk_fd_group_add(struct spdk_fd_group *fgrp,
|
spdk_fd_group_add(struct spdk_fd_group *fgrp,
|
||||||
int efd, spdk_fd_fn fn, void *arg)
|
int efd, spdk_fd_fn fn, void *arg)
|
||||||
{
|
{
|
||||||
struct event_handler *ehdlr;
|
struct event_handler *ehdlr = NULL;
|
||||||
struct epoll_event epevent;
|
struct epoll_event epevent = {0};
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* parameter checking */
|
/* parameter checking */
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
#include "spdk/barrier.h"
|
#include "spdk/barrier.h"
|
||||||
#include "spdk/vhost.h"
|
#include "spdk/vhost.h"
|
||||||
#include "vhost_internal.h"
|
#include "vhost_internal.h"
|
||||||
|
#include <rte_version.h>
|
||||||
|
|
||||||
#include "spdk_internal/vhost_user.h"
|
#include "spdk_internal/vhost_user.h"
|
||||||
|
|
||||||
@ -331,7 +332,11 @@ vhost_register_unix_socket(const char *path, const char *ctrl_name,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if RTE_VERSION < RTE_VERSION_NUM(20, 8, 0, 0)
|
||||||
if (rte_vhost_driver_register(path, 0) != 0) {
|
if (rte_vhost_driver_register(path, 0) != 0) {
|
||||||
|
#else
|
||||||
|
if (rte_vhost_driver_register(path, RTE_VHOST_USER_ASYNC_COPY) != 0) {
|
||||||
|
#endif
|
||||||
SPDK_ERRLOG("Could not register controller %s with vhost library\n", ctrl_name);
|
SPDK_ERRLOG("Could not register controller %s with vhost library\n", ctrl_name);
|
||||||
SPDK_ERRLOG("Check if domain socket %s already exists\n", path);
|
SPDK_ERRLOG("Check if domain socket %s already exists\n", path);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
@ -888,6 +888,7 @@ static int
|
|||||||
vhost_parse_core_mask(const char *mask, struct spdk_cpuset *cpumask)
|
vhost_parse_core_mask(const char *mask, struct spdk_cpuset *cpumask)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
struct spdk_cpuset negative_vhost_mask;
|
||||||
|
|
||||||
if (cpumask == NULL) {
|
if (cpumask == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
@ -904,6 +905,16 @@ vhost_parse_core_mask(const char *mask, struct spdk_cpuset *cpumask)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spdk_cpuset_copy(&negative_vhost_mask, &g_vhost_core_mask);
|
||||||
|
spdk_cpuset_negate(&negative_vhost_mask);
|
||||||
|
spdk_cpuset_and(&negative_vhost_mask, cpumask);
|
||||||
|
|
||||||
|
if (spdk_cpuset_count(&negative_vhost_mask) != 0) {
|
||||||
|
SPDK_ERRLOG("one of selected cpu is outside of core mask(=%s)\n",
|
||||||
|
spdk_cpuset_fmt(&g_vhost_core_mask));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
spdk_cpuset_and(cpumask, &g_vhost_core_mask);
|
spdk_cpuset_and(cpumask, &g_vhost_core_mask);
|
||||||
|
|
||||||
if (spdk_cpuset_count(cpumask) == 0) {
|
if (spdk_cpuset_count(cpumask) == 0) {
|
||||||
|
@ -39,6 +39,13 @@ FIO_PLUGIN := $(SPDK_ROOT_DIR)/build/fio/$(notdir $(FIO_PLUGIN))
|
|||||||
LIBS += $(SPDK_LIB_LINKER_ARGS)
|
LIBS += $(SPDK_LIB_LINKER_ARGS)
|
||||||
|
|
||||||
CFLAGS += -I$(CONFIG_FIO_SOURCE_DIR)
|
CFLAGS += -I$(CONFIG_FIO_SOURCE_DIR)
|
||||||
|
# Compiling against fio 3.19 on latest FreeBSD generates warnings so we
|
||||||
|
# cannot use -Werror
|
||||||
|
ifeq ($(OS),FreeBSD)
|
||||||
|
CFLAGS += -Wno-error
|
||||||
|
else ifeq ($(CC_TYPE),clang)
|
||||||
|
CFLAGS += -Wno-error
|
||||||
|
endif
|
||||||
LDFLAGS += -shared -rdynamic -Wl,-z,nodelete
|
LDFLAGS += -shared -rdynamic -Wl,-z,nodelete
|
||||||
|
|
||||||
CLEAN_FILES = $(FIO_PLUGIN)
|
CLEAN_FILES = $(FIO_PLUGIN)
|
||||||
|
@ -727,13 +727,6 @@ _bdev_nvme_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_
|
|||||||
bdev_io->u.bdev.offset_blocks,
|
bdev_io->u.bdev.offset_blocks,
|
||||||
bdev->dif_check_flags);
|
bdev->dif_check_flags);
|
||||||
|
|
||||||
case SPDK_BDEV_IO_TYPE_WRITE_ZEROES:
|
|
||||||
return bdev_nvme_unmap(nvme_ns->ns,
|
|
||||||
qpair,
|
|
||||||
nbdev_io,
|
|
||||||
bdev_io->u.bdev.offset_blocks,
|
|
||||||
bdev_io->u.bdev.num_blocks);
|
|
||||||
|
|
||||||
case SPDK_BDEV_IO_TYPE_UNMAP:
|
case SPDK_BDEV_IO_TYPE_UNMAP:
|
||||||
return bdev_nvme_unmap(nvme_ns->ns,
|
return bdev_nvme_unmap(nvme_ns->ns,
|
||||||
qpair,
|
qpair,
|
||||||
@ -837,20 +830,11 @@ bdev_nvme_io_type_supported(void *ctx, enum spdk_bdev_io_type io_type)
|
|||||||
return cdata->oncs.dsm;
|
return cdata->oncs.dsm;
|
||||||
|
|
||||||
case SPDK_BDEV_IO_TYPE_WRITE_ZEROES:
|
case SPDK_BDEV_IO_TYPE_WRITE_ZEROES:
|
||||||
cdata = spdk_nvme_ctrlr_get_data(ctrlr);
|
|
||||||
/*
|
|
||||||
* If an NVMe controller guarantees reading unallocated blocks returns zero,
|
|
||||||
* we can implement WRITE_ZEROES as an NVMe deallocate command.
|
|
||||||
*/
|
|
||||||
if (cdata->oncs.dsm &&
|
|
||||||
spdk_nvme_ns_get_dealloc_logical_block_read_value(ns) ==
|
|
||||||
SPDK_NVME_DEALLOC_READ_00) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
* The NVMe controller write_zeroes function is currently not used by our driver.
|
* The NVMe controller write_zeroes function is currently not used by our driver.
|
||||||
* If a user submits an arbitrarily large write_zeroes request to the controller, the request will fail.
|
* NVMe write zeroes is limited to 16-bit block count, and the bdev layer currently
|
||||||
* Until this is resolved, we only claim support for write_zeroes if deallocated blocks return 0's when read.
|
* has no mechanism for reporting a max write zeroes block count, nor ability to
|
||||||
|
* split a write zeroes request.
|
||||||
*/
|
*/
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -967,7 +967,7 @@ bdev_ocssd_push_media_events(struct nvme_bdev_ns *nvme_ns,
|
|||||||
TAILQ_FOREACH(nvme_bdev, &nvme_ns->bdevs, tailq) {
|
TAILQ_FOREACH(nvme_bdev, &nvme_ns->bdevs, tailq) {
|
||||||
ocssd_bdev = SPDK_CONTAINEROF(nvme_bdev, struct ocssd_bdev, nvme_bdev);
|
ocssd_bdev = SPDK_CONTAINEROF(nvme_bdev, struct ocssd_bdev, nvme_bdev);
|
||||||
if (bdev_ocssd_lba_in_range(ocssd_bdev, ocssd_ns, chunk_entry->lba)) {
|
if (bdev_ocssd_lba_in_range(ocssd_bdev, ocssd_ns, chunk_entry->lba)) {
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,12 +2,12 @@
|
|||||||
%bcond_with doc
|
%bcond_with doc
|
||||||
|
|
||||||
Name: spdk
|
Name: spdk
|
||||||
Version: master
|
Version: 21.01.x
|
||||||
Release: 0%{?dist}
|
Release: 0%{?dist}
|
||||||
Epoch: 0
|
Epoch: 0
|
||||||
URL: http://spdk.io
|
URL: http://spdk.io
|
||||||
|
|
||||||
Source: https://github.com/spdk/spdk/archive/master.tar.gz
|
Source: https://github.com/spdk/spdk/archive/v21.01.x.tar.gz
|
||||||
Summary: Set of libraries and utilities for high performance user-mode storage
|
Summary: Set of libraries and utilities for high performance user-mode storage
|
||||||
|
|
||||||
%define package_version %{epoch}:%{version}-%{release}
|
%define package_version %{epoch}:%{version}-%{release}
|
||||||
@ -22,7 +22,7 @@ License: BSD
|
|||||||
ExclusiveArch: x86_64
|
ExclusiveArch: x86_64
|
||||||
|
|
||||||
BuildRequires: gcc gcc-c++ make
|
BuildRequires: gcc gcc-c++ make
|
||||||
BuildRequires: dpdk-devel, numactl-devel
|
BuildRequires: dpdk-devel, numactl-devel, ncurses-devel
|
||||||
BuildRequires: libiscsi-devel, libaio-devel, openssl-devel, libuuid-devel
|
BuildRequires: libiscsi-devel, libaio-devel, openssl-devel, libuuid-devel
|
||||||
BuildRequires: libibverbs-devel, librdmacm-devel
|
BuildRequires: libibverbs-devel, librdmacm-devel
|
||||||
%if %{with doc}
|
%if %{with doc}
|
||||||
@ -32,6 +32,7 @@ BuildRequires: doxygen mscgen graphviz
|
|||||||
# Install dependencies
|
# Install dependencies
|
||||||
Requires: dpdk >= 19.11, numactl-libs, openssl-libs
|
Requires: dpdk >= 19.11, numactl-libs, openssl-libs
|
||||||
Requires: libiscsi, libaio, libuuid
|
Requires: libiscsi, libaio, libuuid
|
||||||
|
Requires: python3-configshell, python3-pexpect
|
||||||
# NVMe over Fabrics
|
# NVMe over Fabrics
|
||||||
Requires: librdmacm, librdmacm
|
Requires: librdmacm, librdmacm
|
||||||
Requires(post): /sbin/ldconfig
|
Requires(post): /sbin/ldconfig
|
||||||
|
@ -15,6 +15,7 @@ mnt_dir=${base_dir}/mnt
|
|||||||
image=/var/tmp/ceph_raw.img
|
image=/var/tmp/ceph_raw.img
|
||||||
dev=/dev/loop200
|
dev=/dev/loop200
|
||||||
|
|
||||||
|
modprobe loop
|
||||||
umount ${dev}p2 || true
|
umount ${dev}p2 || true
|
||||||
losetup -d $dev || true
|
losetup -d $dev || true
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
readonly BASEDIR=$(readlink -f $(dirname $0))/..
|
rootdir=$(readlink -f "$(dirname "$0")")/..
|
||||||
cd $BASEDIR
|
|
||||||
|
cd "$rootdir"
|
||||||
|
|
||||||
# exit on errors
|
# exit on errors
|
||||||
set -e
|
set -e
|
||||||
@ -488,17 +489,19 @@ function check_bash_static_analysis() {
|
|||||||
# SC2086: Double quote to prevent globbing and word splitting.
|
# SC2086: Double quote to prevent globbing and word splitting.
|
||||||
# SC2119: Use foo "$@" if function's $1 should mean script's $1.
|
# SC2119: Use foo "$@" if function's $1 should mean script's $1.
|
||||||
# SC2120: foo references arguments, but none are ever passed.
|
# SC2120: foo references arguments, but none are ever passed.
|
||||||
|
# SC2128: Expanding an array without an index only gives the first element.
|
||||||
# SC2148: Add shebang to the top of your script.
|
# SC2148: Add shebang to the top of your script.
|
||||||
# SC2153: Possible Misspelling: MYVARIABLE may not be assigned, but MY_VARIABLE is.
|
# SC2153: Possible Misspelling: MYVARIABLE may not be assigned, but MY_VARIABLE is.
|
||||||
# SC2154: var is referenced but not assigned.
|
# SC2154: var is referenced but not assigned.
|
||||||
# SC2164: Use cd ... || exit in case cd fails.
|
# SC2164: Use cd ... || exit in case cd fails.
|
||||||
# SC2174: When used with -p, -m only applies to the deepest directory.
|
# SC2174: When used with -p, -m only applies to the deepest directory.
|
||||||
|
# SC2178: Variable was used as an array but is now assigned a string.
|
||||||
# SC2206: Quote to prevent word splitting/globbing,
|
# SC2206: Quote to prevent word splitting/globbing,
|
||||||
# or split robustly with mapfile or read -a.
|
# or split robustly with mapfile or read -a.
|
||||||
# SC2207: Prefer mapfile or read -a to split command output (or quote to avoid splitting).
|
# SC2207: Prefer mapfile or read -a to split command output (or quote to avoid splitting).
|
||||||
# SC2223: This default assignment may cause DoS due to globbing. Quote it.
|
# SC2223: This default assignment may cause DoS due to globbing. Quote it.
|
||||||
SHCK_EXCLUDE="$SHCK_EXCLUDE,SC1083,SC1090,SC1091,SC2010,SC2015,SC2016,SC2034,SC2046,SC2086,\
|
SHCK_EXCLUDE="$SHCK_EXCLUDE,SC1083,SC1090,SC1091,SC2010,SC2015,SC2016,SC2034,SC2046,SC2086,\
|
||||||
SC2119,SC2120,SC2148,SC2153,SC2154,SC2164,SC2174,SC2001,SC2206,SC2207,SC2223"
|
SC2119,SC2120,SC2128,SC2148,SC2153,SC2154,SC2164,SC2174,SC2178,SC2001,SC2206,SC2207,SC2223"
|
||||||
|
|
||||||
SHCK_FORMAT="tty"
|
SHCK_FORMAT="tty"
|
||||||
SHCK_APPLY=false
|
SHCK_APPLY=false
|
||||||
|
@ -35,7 +35,7 @@ class Server:
|
|||||||
print("[%s] %s" % (self.name, msg), flush=True)
|
print("[%s] %s" % (self.name, msg), flush=True)
|
||||||
|
|
||||||
def get_uncommented_lines(self, lines):
|
def get_uncommented_lines(self, lines):
|
||||||
return [l for l in lines if l and not l.startswith('#')]
|
return [line for line in lines if line and not line.startswith('#')]
|
||||||
|
|
||||||
|
|
||||||
class Target(Server):
|
class Target(Server):
|
||||||
|
@ -152,7 +152,7 @@ parser.add_argument('-d', '--max-disks', default=0, type=int,
|
|||||||
each virtual machine gets it's own bdev to work on.")
|
each virtual machine gets it's own bdev to work on.")
|
||||||
parser.add_argument('-v', '--vm-count', default=1, type=int,
|
parser.add_argument('-v', '--vm-count', default=1, type=int,
|
||||||
help="How many VMs to run in test. Default: 1")
|
help="How many VMs to run in test. Default: 1")
|
||||||
parser.add_argument('-i', '--vm-image', default="$HOME/spdk_test_image.qcow2",
|
parser.add_argument('-i', '--vm-image', default="$DEPENDENCY_DIR/spdk_test_image.qcow2",
|
||||||
type=str, help="VM image to use for running VMs.")
|
type=str, help="VM image to use for running VMs.")
|
||||||
|
|
||||||
subparsers = parser.add_subparsers()
|
subparsers = parser.add_subparsers()
|
||||||
|
@ -14,6 +14,22 @@ def print_json(s):
|
|||||||
print(json.dumps(s, indent=2).strip('"'))
|
print(json.dumps(s, indent=2).strip('"'))
|
||||||
|
|
||||||
|
|
||||||
|
def get_addr_type(addr):
|
||||||
|
try:
|
||||||
|
socket.inet_pton(socket.AF_INET, addr)
|
||||||
|
return socket.AF_INET
|
||||||
|
except Exception as e:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
socket.inet_pton(socket.AF_INET6, addr)
|
||||||
|
return socket.AF_INET6
|
||||||
|
except Exception as e:
|
||||||
|
pass
|
||||||
|
if os.path.exists(addr):
|
||||||
|
return socket.AF_UNIX
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class JSONRPCException(Exception):
|
class JSONRPCException(Exception):
|
||||||
def __init__(self, message):
|
def __init__(self, message):
|
||||||
self.message = message
|
self.message = message
|
||||||
@ -54,23 +70,24 @@ class JSONRPCClient(object):
|
|||||||
|
|
||||||
def _connect(self, addr, port):
|
def _connect(self, addr, port):
|
||||||
try:
|
try:
|
||||||
if os.path.exists(addr):
|
addr_type = get_addr_type(addr)
|
||||||
|
|
||||||
|
if addr_type == socket.AF_UNIX:
|
||||||
self._logger.debug("Trying to connect to UNIX socket: %s", addr)
|
self._logger.debug("Trying to connect to UNIX socket: %s", addr)
|
||||||
self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||||
self.sock.connect(addr)
|
self.sock.connect(addr)
|
||||||
elif port:
|
elif addr_type == socket.AF_INET6:
|
||||||
if ':' in addr:
|
self._logger.debug("Trying to connect to IPv6 address addr:%s, port:%i", addr, port)
|
||||||
self._logger.debug("Trying to connect to IPv6 address addr:%s, port:%i", addr, port)
|
for res in socket.getaddrinfo(addr, port, socket.AF_INET6, socket.SOCK_STREAM, socket.SOL_TCP):
|
||||||
for res in socket.getaddrinfo(addr, port, socket.AF_INET6, socket.SOCK_STREAM, socket.SOL_TCP):
|
af, socktype, proto, canonname, sa = res
|
||||||
af, socktype, proto, canonname, sa = res
|
self.sock = socket.socket(af, socktype, proto)
|
||||||
self.sock = socket.socket(af, socktype, proto)
|
self.sock.connect(sa)
|
||||||
self.sock.connect(sa)
|
elif addr_type == socket.AF_INET:
|
||||||
else:
|
self._logger.debug("Trying to connect to IPv4 address addr:%s, port:%i'", addr, port)
|
||||||
self._logger.debug("Trying to connect to IPv4 address addr:%s, port:%i'", addr, port)
|
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
self.sock.connect((addr, port))
|
||||||
self.sock.connect((addr, port))
|
|
||||||
else:
|
else:
|
||||||
raise socket.error("Unix socket '%s' does not exist" % addr)
|
raise socket.error("Invalid or non-existing address: '%s'" % addr)
|
||||||
except socket.error as ex:
|
except socket.error as ex:
|
||||||
raise JSONRPCException("Error while connecting to %s\n"
|
raise JSONRPCException("Error while connecting to %s\n"
|
||||||
"Error details: %s" % (addr, ex))
|
"Error details: %s" % (addr, ex))
|
||||||
|
@ -172,6 +172,10 @@ print_status() {
|
|||||||
local field field_ref fieldidx
|
local field field_ref fieldidx
|
||||||
local pad
|
local pad
|
||||||
|
|
||||||
|
if [[ -n $NO_HEADER ]]; then
|
||||||
|
unset -v "lines[0]"
|
||||||
|
fi
|
||||||
|
|
||||||
for field_ref in "${lines[@]}"; do
|
for field_ref in "${lines[@]}"; do
|
||||||
printf ' '
|
printf ' '
|
||||||
fieldidx=0
|
fieldidx=0
|
||||||
@ -243,23 +247,38 @@ link_up() {
|
|||||||
echo $(($(< "$net/$1/flags") | 0x1)) > "$net/$1/flags"
|
echo $(($(< "$net/$1/flags") | 0x1)) > "$net/$1/flags"
|
||||||
}
|
}
|
||||||
|
|
||||||
collect_devices() {
|
collect_net_devices() {
|
||||||
local net_dev rxe_dev
|
local net_dev
|
||||||
|
|
||||||
for net_dev in "$net/"!(bonding_masters); do
|
for net_dev in "$net/"!(bonding_masters); do
|
||||||
(($(< "$net_dev/type") != 1)) && continue
|
(($(< "$net_dev/type") != 1)) && continue
|
||||||
net_devices["${net_dev##*/}"]=$net_dev
|
net_devices["${net_dev##*/}"]=$net_dev
|
||||||
for rxe_dev in "$infiniband/rxe"+([0-9]); do
|
|
||||||
if [[ $(< "$rxe_dev/parent") == "${net_dev##*/}" ]]; then
|
|
||||||
net_to_rxe["${net_dev##*/}"]=${rxe_dev##*/}
|
|
||||||
rxe_to_net["${rxe_dev##*/}"]=${net_dev##*/}
|
|
||||||
continue 2
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
collect_devices
|
collect_rxe_devices() {
|
||||||
|
local rxe_dev net_dev
|
||||||
|
|
||||||
|
for rxe_dev in "$infiniband/"*; do
|
||||||
|
if [[ -e $rxe_dev/parent ]]; then
|
||||||
|
# Soft
|
||||||
|
net_dev=$(< "$rxe_dev/parent")
|
||||||
|
elif [[ -e $rxe_dev/device/net ]]; then
|
||||||
|
# HW
|
||||||
|
net_dev=$(readlink -f "$rxe_dev/device/net/"*)
|
||||||
|
net_dev=${net_dev##*/}
|
||||||
|
else
|
||||||
|
continue
|
||||||
|
fi 2> /dev/null
|
||||||
|
|
||||||
|
[[ -n ${net_devices["$net_dev"]} ]] || continue
|
||||||
|
net_to_rxe["$net_dev"]=${rxe_dev##*/}
|
||||||
|
rxe_to_net["${rxe_dev##*/}"]=$net_dev
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
collect_net_devices
|
||||||
|
collect_rxe_devices
|
||||||
|
|
||||||
case "${1:-status}" in
|
case "${1:-status}" in
|
||||||
start)
|
start)
|
||||||
@ -281,6 +300,9 @@ case "${1:-status}" in
|
|||||||
)
|
)
|
||||||
status | grep -E "${match:-.}"
|
status | grep -E "${match:-.}"
|
||||||
;;
|
;;
|
||||||
|
rxe-net)
|
||||||
|
printf '%s\n' "${rxe_to_net[@]}"
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
printf 'Invalid argument (%s)\n' "$1"
|
printf 'Invalid argument (%s)\n' "$1"
|
||||||
;;
|
;;
|
||||||
|
@ -579,7 +579,9 @@ function status_linux() {
|
|||||||
printf '\n%-8s %-15s %-6s %-6s %-7s %-16s %-10s %s\n' \
|
printf '\n%-8s %-15s %-6s %-6s %-7s %-16s %-10s %s\n' \
|
||||||
"Type" "BDF" "Vendor" "Device" "NUMA" "Driver" "Device" "Block devices" >&2
|
"Type" "BDF" "Vendor" "Device" "NUMA" "Driver" "Device" "Block devices" >&2
|
||||||
|
|
||||||
for bdf in "${!all_devices_d[@]}"; do
|
sorted_bdfs=($(printf '%s\n' "${!all_devices_d[@]}" | sort))
|
||||||
|
|
||||||
|
for bdf in "${sorted_bdfs[@]}"; do
|
||||||
driver=${drivers_d["$bdf"]}
|
driver=${drivers_d["$bdf"]}
|
||||||
if [ "$numa_nodes" = "0" ]; then
|
if [ "$numa_nodes" = "0" ]; then
|
||||||
node="-"
|
node="-"
|
||||||
@ -611,7 +613,7 @@ function status_linux() {
|
|||||||
printf '%-8s %-15s %-6s %-6s %-7s %-16s %-10s %s\n' \
|
printf '%-8s %-15s %-6s %-6s %-7s %-16s %-10s %s\n' \
|
||||||
"$desc" "$bdf" "${pci_ids_vendor["$bdf"]#0x}" "${pci_ids_device["$bdf"]#0x}" \
|
"$desc" "$bdf" "${pci_ids_vendor["$bdf"]#0x}" "${pci_ids_device["$bdf"]#0x}" \
|
||||||
"$node" "${driver:--}" "${name:-}" "${blknames[*]:--}"
|
"$node" "${driver:--}" "${name:-}" "${blknames[*]:--}"
|
||||||
done | sort -bk2,2
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
function status_freebsd() {
|
function status_freebsd() {
|
||||||
|
@ -9,6 +9,7 @@ SPDK_TEST_ISCSI_INITIATOR=0
|
|||||||
SPDK_TEST_NVME=0
|
SPDK_TEST_NVME=0
|
||||||
SPDK_TEST_NVME_CLI=0
|
SPDK_TEST_NVME_CLI=0
|
||||||
SPDK_TEST_NVMF=1
|
SPDK_TEST_NVMF=1
|
||||||
|
SPDK_TEST_VFIOUSER=1
|
||||||
SPDK_TEST_RBD=0
|
SPDK_TEST_RBD=0
|
||||||
SPDK_TEST_CRYPTO=0
|
SPDK_TEST_CRYPTO=0
|
||||||
SPDK_TEST_OCF=0
|
SPDK_TEST_OCF=0
|
||||||
|
@ -81,6 +81,8 @@ export SPDK_TEST_NVME_CLI
|
|||||||
export SPDK_TEST_NVME_CUSE
|
export SPDK_TEST_NVME_CUSE
|
||||||
: ${SPDK_TEST_NVMF=0}
|
: ${SPDK_TEST_NVMF=0}
|
||||||
export SPDK_TEST_NVMF
|
export SPDK_TEST_NVMF
|
||||||
|
: ${SPDK_TEST_VFIOUSER=0}
|
||||||
|
export SPDK_TEST_VFIOUSER
|
||||||
: ${SPDK_TEST_NVMF_TRANSPORT="rdma"}
|
: ${SPDK_TEST_NVMF_TRANSPORT="rdma"}
|
||||||
export SPDK_TEST_NVMF_TRANSPORT
|
export SPDK_TEST_NVMF_TRANSPORT
|
||||||
: ${SPDK_TEST_RBD=0}
|
: ${SPDK_TEST_RBD=0}
|
||||||
@ -173,6 +175,8 @@ leak:$CONFIG_FIO_SOURCE_DIR/init.c
|
|||||||
leak:$CONFIG_FIO_SOURCE_DIR/filesetup.c
|
leak:$CONFIG_FIO_SOURCE_DIR/filesetup.c
|
||||||
leak:fio_memalign
|
leak:fio_memalign
|
||||||
leak:spdk_fio_io_u_init
|
leak:spdk_fio_io_u_init
|
||||||
|
# Suppress leaks in gperftools-libs from fio
|
||||||
|
leak:libtcmalloc_minimal.so
|
||||||
|
|
||||||
# Suppress leaks in libiscsi
|
# Suppress leaks in libiscsi
|
||||||
leak:libiscsi.so
|
leak:libiscsi.so
|
||||||
@ -186,7 +190,7 @@ export LSAN_OPTIONS=suppressions="$asan_suppression_file"
|
|||||||
export DEFAULT_RPC_ADDR="/var/tmp/spdk.sock"
|
export DEFAULT_RPC_ADDR="/var/tmp/spdk.sock"
|
||||||
|
|
||||||
if [ -z "$DEPENDENCY_DIR" ]; then
|
if [ -z "$DEPENDENCY_DIR" ]; then
|
||||||
export DEPENDENCY_DIR=/home/sys_sgsw
|
export DEPENDENCY_DIR=$HOME/spdk_dependencies
|
||||||
else
|
else
|
||||||
export DEPENDENCY_DIR
|
export DEPENDENCY_DIR
|
||||||
fi
|
fi
|
||||||
@ -201,10 +205,16 @@ if [ $SPDK_RUN_VALGRIND -eq 0 ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$(uname -s)" = "Linux" ]; then
|
if [ "$(uname -s)" = "Linux" ]; then
|
||||||
|
export HUGEMEM=4096 CLEAR_HUGE=yes
|
||||||
|
if [[ $SPDK_TEST_CRYPTO -eq 1 || $SPDK_TEST_REDUCE -eq 1 ]]; then
|
||||||
|
# Make sure that memory is distributed across all NUMA nodes - by default, all goes to
|
||||||
|
# node0, but if QAT devices are attached to a different node, all of their VFs will end
|
||||||
|
# up under that node too and memory needs to be available there for the tests.
|
||||||
|
export HUGE_EVEN_ALLOC=yes
|
||||||
|
fi
|
||||||
|
|
||||||
MAKE="make"
|
MAKE="make"
|
||||||
MAKEFLAGS=${MAKEFLAGS:--j$(nproc)}
|
MAKEFLAGS=${MAKEFLAGS:--j$(nproc)}
|
||||||
# Override the default HUGEMEM in scripts/setup.sh to allocate 8GB in hugepages.
|
|
||||||
export HUGEMEM=8192
|
|
||||||
if [[ $SPDK_TEST_USE_IGB_UIO -eq 1 ]]; then
|
if [[ $SPDK_TEST_USE_IGB_UIO -eq 1 ]]; then
|
||||||
export DRIVER_OVERRIDE=igb_uio
|
export DRIVER_OVERRIDE=igb_uio
|
||||||
# Building kernel modules requires root privileges
|
# Building kernel modules requires root privileges
|
||||||
@ -422,6 +432,10 @@ function get_config_params() {
|
|||||||
config_params+=' --with-raid5'
|
config_params+=' --with-raid5'
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ $SPDK_TEST_VFIOUSER -eq 1 ]; then
|
||||||
|
config_params+=' --with-vfio-user'
|
||||||
|
fi
|
||||||
|
|
||||||
# Check whether liburing library header exists
|
# Check whether liburing library header exists
|
||||||
if [ -f /usr/include/liburing/io_uring.h ] && [ $SPDK_TEST_URING -eq 1 ]; then
|
if [ -f /usr/include/liburing/io_uring.h ] && [ $SPDK_TEST_URING -eq 1 ]; then
|
||||||
config_params+=' --with-uring'
|
config_params+=' --with-uring'
|
||||||
@ -636,11 +650,6 @@ function process_shm() {
|
|||||||
id=$2
|
id=$2
|
||||||
if [ "$type" = "--pid" ]; then
|
if [ "$type" = "--pid" ]; then
|
||||||
id="pid${id}"
|
id="pid${id}"
|
||||||
elif [ "$type" = "--id" ]; then
|
|
||||||
id="${id}"
|
|
||||||
else
|
|
||||||
echo "Please specify to search for pid or shared memory id."
|
|
||||||
return 1
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
shm_files=$(find /dev/shm -name "*.${id}" -printf "%f\n")
|
shm_files=$(find /dev/shm -name "*.${id}" -printf "%f\n")
|
||||||
|
@ -17,7 +17,7 @@ to emulate an RDMA enabled NIC. NVMe controllers can also be virtualized in emul
|
|||||||
|
|
||||||
## VM Specs
|
## VM Specs
|
||||||
|
|
||||||
When creating the user during the fedora installation, it is best to use the name sys_sgsw. Efforts are being made
|
When creating the user during the fedora installation, it is best to use the name sys_sgci. Efforts are being made
|
||||||
to remove all references to this user, or files specific to this user from the codebase, but there are still some
|
to remove all references to this user, or files specific to this user from the codebase, but there are still some
|
||||||
trailing references to it.
|
trailing references to it.
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ configuration file. For a full list of the variable declarations available for a
|
|||||||
|
|
||||||
1. Download a fresh Fedora 26 image.
|
1. Download a fresh Fedora 26 image.
|
||||||
2. Perform the installation of Fedora 26 server.
|
2. Perform the installation of Fedora 26 server.
|
||||||
3. Create an admin user sys_sgsw (enabling passwordless sudo for this account will make life easier during the tests).
|
3. Create an admin user sys_sgci (enabling passwordless sudo for this account will make life easier during the tests).
|
||||||
4. Run the vm_setup.sh script which will install all proper dependencies.
|
4. Run the vm_setup.sh script which will install all proper dependencies.
|
||||||
5. Modify the autorun-spdk.conf file in the home directory.
|
5. Modify the autorun-spdk.conf file in the home directory.
|
||||||
6. Reboot the VM.
|
6. Reboot the VM.
|
||||||
@ -81,5 +81,5 @@ To create the VM image manually use following steps:
|
|||||||
~~~
|
~~~
|
||||||
./spdk/test/common/config/vm_setup.sh -t 'fio'
|
./spdk/test/common/config/vm_setup.sh -t 'fio'
|
||||||
~~~
|
~~~
|
||||||
6. Place the guest VM in the host at the following location: `/home/sys_sgci/spdk_test_image.qcow2`.
|
6. Place the guest VM in the host at the following location: `$DEPENDENCY_DIR/spdk_test_image.qcow2`.
|
||||||
7. On the host, edit the `~/autorun-spdk.conf` file to include the following line: SPDK_TEST_VHOST=1.
|
7. On the host, edit the `~/autorun-spdk.conf` file to include the following line: SPDK_TEST_VHOST=1.
|
||||||
|
@ -203,7 +203,7 @@ function install_rocksdb() {
|
|||||||
function install_fio() {
|
function install_fio() {
|
||||||
# This version of fio is installed in /usr/src/fio to enable
|
# This version of fio is installed in /usr/src/fio to enable
|
||||||
# building the spdk fio plugin.
|
# building the spdk fio plugin.
|
||||||
local fio_version="fio-3.19"
|
local fio_version="fio-3.28"
|
||||||
|
|
||||||
if [ ! -d /usr/src/fio ]; then
|
if [ ! -d /usr/src/fio ]; then
|
||||||
if [ ! -d fio ]; then
|
if [ ! -d fio ]; then
|
||||||
|
@ -185,6 +185,7 @@ SPDK_TEST_ISCSI_INITIATOR=1
|
|||||||
SPDK_TEST_NVME=1
|
SPDK_TEST_NVME=1
|
||||||
SPDK_TEST_NVME_CLI=1
|
SPDK_TEST_NVME_CLI=1
|
||||||
SPDK_TEST_NVMF=1
|
SPDK_TEST_NVMF=1
|
||||||
|
SPDK_TEST_VFIOUSER=1
|
||||||
SPDK_TEST_RBD=1
|
SPDK_TEST_RBD=1
|
||||||
SPDK_TEST_BLOCKDEV=1
|
SPDK_TEST_BLOCKDEV=1
|
||||||
SPDK_TEST_BLOBFS=1
|
SPDK_TEST_BLOBFS=1
|
||||||
|
@ -5,10 +5,9 @@ rootdir=$(readlink -f $testdir/../..)
|
|||||||
source $rootdir/test/common/autotest_common.sh
|
source $rootdir/test/common/autotest_common.sh
|
||||||
|
|
||||||
rpc_py="$rootdir/scripts/rpc.py"
|
rpc_py="$rootdir/scripts/rpc.py"
|
||||||
SPDK_APP="$SPDK_BIN_DIR/spdk_tgt"
|
|
||||||
MEM_SCRIPT="$rootdir/scripts/dpdk_mem_info.py"
|
MEM_SCRIPT="$rootdir/scripts/dpdk_mem_info.py"
|
||||||
|
|
||||||
$SPDK_APP &
|
"${SPDK_APP[@]}" &
|
||||||
spdkpid=$!
|
spdkpid=$!
|
||||||
|
|
||||||
waitforlisten $spdkpid
|
waitforlisten $spdkpid
|
||||||
|
@ -32,13 +32,13 @@ $rpc_py framework_start_init
|
|||||||
echo "iscsi_tgt is listening. Running tests..."
|
echo "iscsi_tgt is listening. Running tests..."
|
||||||
|
|
||||||
# RPC framework_wait_init should be already returned, so its process must be non-existed
|
# RPC framework_wait_init should be already returned, so its process must be non-existed
|
||||||
! ps $rpc_wait_pid
|
NOT ps $rpc_wait_pid
|
||||||
|
|
||||||
# RPC framework_wait_init will directly returned after subsystem initialized.
|
# RPC framework_wait_init will directly returned after subsystem initialized.
|
||||||
$rpc_py framework_wait_init &
|
$rpc_py framework_wait_init &
|
||||||
rpc_wait_pid=$!
|
rpc_wait_pid=$!
|
||||||
sleep 1
|
sleep 1
|
||||||
! ps $rpc_wait_pid
|
NOT ps $rpc_wait_pid
|
||||||
|
|
||||||
timing_exit start_iscsi_tgt
|
timing_exit start_iscsi_tgt
|
||||||
|
|
||||||
|
@ -300,8 +300,12 @@ function create_iscsi_subsystem_config() {
|
|||||||
function create_nvmf_subsystem_config() {
|
function create_nvmf_subsystem_config() {
|
||||||
timing_enter "${FUNCNAME[0]}"
|
timing_enter "${FUNCNAME[0]}"
|
||||||
|
|
||||||
RDMA_IP_LIST=$(get_available_rdma_ips)
|
NVMF_FIRST_TARGET_IP="127.0.0.1"
|
||||||
NVMF_FIRST_TARGET_IP=$(echo "$RDMA_IP_LIST" | head -n 1)
|
if [[ $SPDK_TEST_NVMF_TRANSPORT == "rdma" ]]; then
|
||||||
|
rdma_device_init
|
||||||
|
NVMF_FIRST_TARGET_IP=$(get_available_rdma_ips | head -n 1)
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ -z $NVMF_FIRST_TARGET_IP ]]; then
|
if [[ -z $NVMF_FIRST_TARGET_IP ]]; then
|
||||||
echo "Error: no NIC for nvmf test"
|
echo "Error: no NIC for nvmf test"
|
||||||
return 1
|
return 1
|
||||||
@ -310,11 +314,11 @@ function create_nvmf_subsystem_config() {
|
|||||||
tgt_rpc bdev_malloc_create 8 512 --name MallocForNvmf0
|
tgt_rpc bdev_malloc_create 8 512 --name MallocForNvmf0
|
||||||
tgt_rpc bdev_malloc_create 4 1024 --name MallocForNvmf1
|
tgt_rpc bdev_malloc_create 4 1024 --name MallocForNvmf1
|
||||||
|
|
||||||
tgt_rpc nvmf_create_transport -t RDMA -u 8192 -c 0
|
tgt_rpc nvmf_create_transport -t $SPDK_TEST_NVMF_TRANSPORT -u 8192 -c 0
|
||||||
tgt_rpc nvmf_create_subsystem nqn.2016-06.io.spdk:cnode1 -a -s SPDK00000000000001
|
tgt_rpc nvmf_create_subsystem nqn.2016-06.io.spdk:cnode1 -a -s SPDK00000000000001
|
||||||
tgt_rpc nvmf_subsystem_add_ns nqn.2016-06.io.spdk:cnode1 MallocForNvmf0
|
tgt_rpc nvmf_subsystem_add_ns nqn.2016-06.io.spdk:cnode1 MallocForNvmf0
|
||||||
tgt_rpc nvmf_subsystem_add_ns nqn.2016-06.io.spdk:cnode1 MallocForNvmf1
|
tgt_rpc nvmf_subsystem_add_ns nqn.2016-06.io.spdk:cnode1 MallocForNvmf1
|
||||||
tgt_rpc nvmf_subsystem_add_listener nqn.2016-06.io.spdk:cnode1 -t RDMA -a $NVMF_FIRST_TARGET_IP -s "$NVMF_PORT"
|
tgt_rpc nvmf_subsystem_add_listener nqn.2016-06.io.spdk:cnode1 -t $SPDK_TEST_NVMF_TRANSPORT -a $NVMF_FIRST_TARGET_IP -s "$NVMF_PORT"
|
||||||
|
|
||||||
timing_exit "${FUNCNAME[0]}"
|
timing_exit "${FUNCNAME[0]}"
|
||||||
}
|
}
|
||||||
|
@ -49,17 +49,6 @@ function confirm_abi_deps() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
cat << EOF > ${suppression_file}
|
cat << EOF > ${suppression_file}
|
||||||
[suppress_type]
|
|
||||||
name = spdk_nvme_ctrlr_data
|
|
||||||
[suppress_type]
|
|
||||||
type_kind = enum
|
|
||||||
changed_enumerators = SPDK_BDEV_NUM_IO_TYPES
|
|
||||||
[suppress_type]
|
|
||||||
name = spdk_env_opts
|
|
||||||
[suppress_type]
|
|
||||||
name = spdk_app_opts
|
|
||||||
[suppress_type]
|
|
||||||
name = spdk_thread
|
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
for object in "$libdir"/libspdk_*.so; do
|
for object in "$libdir"/libspdk_*.so; do
|
||||||
|
@ -54,7 +54,7 @@ function devices_delete() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
password=$1
|
password=$1
|
||||||
base_img=$HOME/spdk_test_image.qcow2
|
base_img=$DEPENDENCY_DIR/spdk_test_image.qcow2
|
||||||
qemu_pidfile=$HOME/qemupid
|
qemu_pidfile=$HOME/qemupid
|
||||||
|
|
||||||
if [ ! -e "$base_img" ]; then
|
if [ ! -e "$base_img" ]; then
|
||||||
|
@ -71,7 +71,7 @@ function detect_nics_and_probe_drivers() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function pci_nics_switch() {
|
function pci_rdma_switch() {
|
||||||
local driver=$1
|
local driver=$1
|
||||||
|
|
||||||
local -a driver_args=()
|
local -a driver_args=()
|
||||||
@ -103,26 +103,60 @@ function pci_nics_switch() {
|
|||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function pci_tcp_switch() {
|
||||||
|
local driver=$1
|
||||||
|
|
||||||
|
local -a driver_args=()
|
||||||
|
driver_args+=("Intel E810 ice")
|
||||||
|
|
||||||
|
case $driver in
|
||||||
|
ice)
|
||||||
|
detect_nics_and_probe_drivers ${driver_args[0]}
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
for d in "${driver_args[@]}"; do
|
||||||
|
detect_nics_and_probe_drivers $d
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
function detect_pci_nics() {
|
function detect_pci_nics() {
|
||||||
|
|
||||||
if ! hash lspci; then
|
if ! hash lspci; then
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local rdma_drivers="mlx5_ib|irdma|i40iw|iw_cxgb4"
|
local nic_drivers
|
||||||
local found_drivers
|
local found_drivers
|
||||||
|
|
||||||
# Try to find RDMA drivers which are already loded and try to
|
if [[ -z "$TEST_TRANSPORT" ]]; then
|
||||||
# use only it's associated NICs, without probing all drivers.
|
TEST_TRANSPORT=$SPDK_TEST_NVMF_TRANSPORT
|
||||||
found_drivers=$(lsmod | grep -Eo $rdma_drivers | sort -u)
|
fi
|
||||||
for d in $found_drivers; do
|
|
||||||
pci_nics_switch $d
|
|
||||||
done
|
|
||||||
|
|
||||||
# In case lsmod reported driver, but lspci does not report
|
if [[ "$TEST_TRANSPORT" == "rdma" ]]; then
|
||||||
# physical NICs - fall back to old approach any try to
|
nic_drivers="mlx5_ib|irdma|i40iw|iw_cxgb4"
|
||||||
# probe all compatible NICs.
|
|
||||||
((have_pci_nics == 0)) && pci_nics_switch "default"
|
# Try to find RDMA drivers which are already loded and try to
|
||||||
|
# use only it's associated NICs, without probing all drivers.
|
||||||
|
found_drivers=$(lsmod | grep -Eo $nic_drivers | sort -u)
|
||||||
|
for d in $found_drivers; do
|
||||||
|
pci_rdma_switch $d
|
||||||
|
done
|
||||||
|
|
||||||
|
# In case lsmod reported driver, but lspci does not report
|
||||||
|
# physical NICs - fall back to old approach any try to
|
||||||
|
# probe all compatible NICs.
|
||||||
|
((have_pci_nics == 0)) && pci_rdma_switch "default"
|
||||||
|
|
||||||
|
elif [[ "$TEST_TRANSPORT" == "tcp" ]]; then
|
||||||
|
nic_drivers="ice"
|
||||||
|
found_drivers=$(lsmod | grep -Eo $nic_drivers | sort -u)
|
||||||
|
for d in $found_drivers; do
|
||||||
|
pci_tcp_switch $d
|
||||||
|
done
|
||||||
|
((have_pci_nics == 0)) && pci_tcp_switch "default"
|
||||||
|
fi
|
||||||
|
|
||||||
# Use softroce if everything else failed.
|
# Use softroce if everything else failed.
|
||||||
((have_pci_nics == 0)) && return 0
|
((have_pci_nics == 0)) && return 0
|
||||||
@ -131,7 +165,7 @@ function detect_pci_nics() {
|
|||||||
sleep 5
|
sleep 5
|
||||||
}
|
}
|
||||||
|
|
||||||
function detect_rdma_nics() {
|
function detect_transport_nics() {
|
||||||
detect_pci_nics
|
detect_pci_nics
|
||||||
if [ "$have_pci_nics" -eq "0" ]; then
|
if [ "$have_pci_nics" -eq "0" ]; then
|
||||||
detect_soft_roce_nics
|
detect_soft_roce_nics
|
||||||
@ -159,13 +193,17 @@ function get_available_rdma_ips() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function get_rdma_if_list() {
|
function get_rdma_if_list() {
|
||||||
for nic_type in /sys/class/infiniband/*; do
|
rxe_cfg rxe-net
|
||||||
[[ -e "$nic_type" ]] || break
|
}
|
||||||
for nic_name in /sys/class/infiniband/"$(basename ${nic_type})"/device/net/*; do
|
|
||||||
[[ -e "$nic_name" ]] || break
|
function get_tcp_if_list_by_driver() {
|
||||||
basename "$nic_name"
|
local driver
|
||||||
done
|
driver=${1:-ice}
|
||||||
done
|
|
||||||
|
shopt -s nullglob
|
||||||
|
tcp_if_list=(/sys/bus/pci/drivers/$driver/0000*/net/*)
|
||||||
|
shopt -u nullglob
|
||||||
|
printf '%s\n' "${tcp_if_list[@]##*/}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_ip_address() {
|
function get_ip_address() {
|
||||||
@ -284,6 +322,67 @@ function nvmf_veth_fini() {
|
|||||||
ip netns del $NVMF_TARGET_NAMESPACE
|
ip netns del $NVMF_TARGET_NAMESPACE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function nvmf_tcp_init() {
|
||||||
|
NVMF_INITIATOR_IP=10.0.0.1
|
||||||
|
NVMF_FIRST_TARGET_IP=10.0.0.2
|
||||||
|
TCP_INTERFACE_LIST=($(get_tcp_if_list_by_driver))
|
||||||
|
if ((${#TCP_INTERFACE_LIST[@]} == 0)); then
|
||||||
|
nvmf_veth_init
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# We need two net devs at minimum
|
||||||
|
((${#TCP_INTERFACE_LIST[@]} > 1))
|
||||||
|
|
||||||
|
NVMF_TARGET_INTERFACE=${TCP_INTERFACE_LIST[0]}
|
||||||
|
NVMF_INITIATOR_INTERFACE=${TCP_INTERFACE_LIST[1]}
|
||||||
|
|
||||||
|
# Skip case nvmf_multipath in nvmf_tcp_init(), it will be covered by nvmf_veth_init().
|
||||||
|
NVMF_SECOND_TARGET_IP=""
|
||||||
|
|
||||||
|
NVMF_TARGET_NAMESPACE=$NVMF_TARGET_INTERFACE"_ns"
|
||||||
|
NVMF_TARGET_NS_CMD=(ip netns exec "$NVMF_TARGET_NAMESPACE")
|
||||||
|
ip netns del $NVMF_TARGET_NAMESPACE || true
|
||||||
|
ip -4 addr flush $NVMF_TARGET_INTERFACE || true
|
||||||
|
ip -4 addr flush $NVMF_INITIATOR_INTERFACE || true
|
||||||
|
|
||||||
|
trap 'nvmf_tcp_fini; exit 1' SIGINT SIGTERM
|
||||||
|
|
||||||
|
# Create network namespace
|
||||||
|
ip netns add $NVMF_TARGET_NAMESPACE
|
||||||
|
|
||||||
|
# Associate phy interface pairs with network namespace
|
||||||
|
ip link set $NVMF_TARGET_INTERFACE netns $NVMF_TARGET_NAMESPACE
|
||||||
|
|
||||||
|
# Allocate IP addresses
|
||||||
|
ip addr add $NVMF_INITIATOR_IP/24 dev $NVMF_INITIATOR_INTERFACE
|
||||||
|
"${NVMF_TARGET_NS_CMD[@]}" ip addr add $NVMF_FIRST_TARGET_IP/24 dev $NVMF_TARGET_INTERFACE
|
||||||
|
|
||||||
|
# Link up phy interfaces
|
||||||
|
ip link set $NVMF_INITIATOR_INTERFACE up
|
||||||
|
|
||||||
|
"${NVMF_TARGET_NS_CMD[@]}" ip link set $NVMF_TARGET_INTERFACE up
|
||||||
|
"${NVMF_TARGET_NS_CMD[@]}" ip link set lo up
|
||||||
|
|
||||||
|
# Accept connections from phy interface
|
||||||
|
iptables -I INPUT 1 -i $NVMF_INITIATOR_INTERFACE -p tcp --dport $NVMF_PORT -j ACCEPT
|
||||||
|
|
||||||
|
# Verify connectivity
|
||||||
|
ping -c 1 $NVMF_FIRST_TARGET_IP
|
||||||
|
"${NVMF_TARGET_NS_CMD[@]}" ping -c 1 $NVMF_INITIATOR_IP
|
||||||
|
|
||||||
|
NVMF_APP=("${NVMF_TARGET_NS_CMD[@]}" "${NVMF_APP[@]}")
|
||||||
|
}
|
||||||
|
|
||||||
|
function nvmf_tcp_fini() {
|
||||||
|
if [[ "$NVMF_TARGET_NAMESPACE" == "nvmf_tgt_ns" ]]; then
|
||||||
|
nvmf_veth_fini
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
ip netns del $NVMF_TARGET_NAMESPACE
|
||||||
|
ip -4 addr flush $NVMF_INITIATOR_INTERFACE
|
||||||
|
}
|
||||||
|
|
||||||
function nvmftestinit() {
|
function nvmftestinit() {
|
||||||
if [ -z $TEST_TRANSPORT ]; then
|
if [ -z $TEST_TRANSPORT ]; then
|
||||||
echo "transport not specified - use --transport= to specify"
|
echo "transport not specified - use --transport= to specify"
|
||||||
@ -291,22 +390,25 @@ function nvmftestinit() {
|
|||||||
fi
|
fi
|
||||||
if [ "$TEST_MODE" == "iso" ]; then
|
if [ "$TEST_MODE" == "iso" ]; then
|
||||||
$rootdir/scripts/setup.sh
|
$rootdir/scripts/setup.sh
|
||||||
if [ "$TEST_TRANSPORT" == "rdma" ]; then
|
if [[ "$TEST_TRANSPORT" == "rdma" ]]; then
|
||||||
rdma_device_init
|
rdma_device_init
|
||||||
fi
|
fi
|
||||||
|
if [[ "$TEST_TRANSPORT" == "tcp" ]]; then
|
||||||
|
tcp_device_init
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
NVMF_TRANSPORT_OPTS="-t $TEST_TRANSPORT"
|
NVMF_TRANSPORT_OPTS="-t $TEST_TRANSPORT"
|
||||||
if [ "$TEST_TRANSPORT" == "rdma" ]; then
|
if [[ "$TEST_TRANSPORT" == "rdma" ]]; then
|
||||||
RDMA_IP_LIST=$(get_available_rdma_ips)
|
RDMA_IP_LIST=$(get_available_rdma_ips)
|
||||||
NVMF_FIRST_TARGET_IP=$(echo "$RDMA_IP_LIST" | head -n 1)
|
NVMF_FIRST_TARGET_IP=$(echo "$RDMA_IP_LIST" | head -n 1)
|
||||||
NVMF_SECOND_TARGET_IP=$(echo "$RDMA_IP_LIST" | tail -n +2 | head -n 1)
|
NVMF_SECOND_TARGET_IP=$(echo "$RDMA_IP_LIST" | tail -n +2 | head -n 1)
|
||||||
if [ -z $NVMF_FIRST_TARGET_IP ]; then
|
if [ -z $NVMF_FIRST_TARGET_IP ]; then
|
||||||
echo "no NIC for nvmf test"
|
echo "no RDMA NIC for nvmf test"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
elif [ "$TEST_TRANSPORT" == "tcp" ]; then
|
elif [[ "$TEST_TRANSPORT" == "tcp" ]]; then
|
||||||
nvmf_veth_init
|
nvmf_tcp_init
|
||||||
NVMF_TRANSPORT_OPTS="$NVMF_TRANSPORT_OPTS -o"
|
NVMF_TRANSPORT_OPTS="$NVMF_TRANSPORT_OPTS -o"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -334,20 +436,25 @@ function nvmftestfini() {
|
|||||||
fi
|
fi
|
||||||
if [ "$TEST_MODE" == "iso" ]; then
|
if [ "$TEST_MODE" == "iso" ]; then
|
||||||
$rootdir/scripts/setup.sh reset
|
$rootdir/scripts/setup.sh reset
|
||||||
if [ "$TEST_TRANSPORT" == "rdma" ]; then
|
if [[ "$TEST_TRANSPORT" == "rdma" ]]; then
|
||||||
rdma_device_init
|
rdma_device_init
|
||||||
elif [ "$TEST_TRANSPORT" == "tcp" ]; then
|
|
||||||
nvmf_veth_fini
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
if [[ "$TEST_TRANSPORT" == "tcp" ]]; then
|
||||||
|
nvmf_tcp_fini
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function rdma_device_init() {
|
function rdma_device_init() {
|
||||||
load_ib_rdma_modules
|
load_ib_rdma_modules
|
||||||
detect_rdma_nics
|
detect_transport_nics
|
||||||
allocate_nic_ips
|
allocate_nic_ips
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function tcp_device_init() {
|
||||||
|
detect_transport_nics
|
||||||
|
}
|
||||||
|
|
||||||
function revert_soft_roce() {
|
function revert_soft_roce() {
|
||||||
rxe_cfg stop
|
rxe_cfg stop
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ run_test "nvmf_invalid" test/nvmf/target/invalid.sh "${TEST_ARGS[@]}"
|
|||||||
run_test "nvmf_abort" test/nvmf/target/abort.sh "${TEST_ARGS[@]}"
|
run_test "nvmf_abort" test/nvmf/target/abort.sh "${TEST_ARGS[@]}"
|
||||||
run_test "nvmf_ns_hotplug_stress" test/nvmf/target/ns_hotplug_stress.sh "${TEST_ARGS[@]}"
|
run_test "nvmf_ns_hotplug_stress" test/nvmf/target/ns_hotplug_stress.sh "${TEST_ARGS[@]}"
|
||||||
|
|
||||||
if grep -q '#define SPDK_CONFIG_VFIO_USER 1' $rootdir/include/spdk/config.h; then
|
if [ $SPDK_TEST_VFIOUSER -eq 1 ]; then
|
||||||
run_test "nvmf_vfio_user" test/nvmf/target/nvmf_vfio_user.sh "${TEST_ARGS[@]}"
|
run_test "nvmf_vfio_user" test/nvmf/target/nvmf_vfio_user.sh "${TEST_ARGS[@]}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ $rpc_py nvmf_subsystem_allow_any_host -d nqn.2016-06.io.spdk:cnode1
|
|||||||
$rpc_py nvmf_subsystem_add_listener nqn.2016-06.io.spdk:cnode1 -t $TEST_TRANSPORT -a $NVMF_FIRST_TARGET_IP -s $NVMF_PORT
|
$rpc_py nvmf_subsystem_add_listener nqn.2016-06.io.spdk:cnode1 -t $TEST_TRANSPORT -a $NVMF_FIRST_TARGET_IP -s $NVMF_PORT
|
||||||
|
|
||||||
# This connect should fail - the host NQN is not allowed
|
# This connect should fail - the host NQN is not allowed
|
||||||
! nvme connect -t $TEST_TRANSPORT -n nqn.2016-06.io.spdk:cnode1 -q nqn.2016-06.io.spdk:host1 -a "$NVMF_FIRST_TARGET_IP" -s "$NVMF_PORT"
|
NOT nvme connect -t $TEST_TRANSPORT -n nqn.2016-06.io.spdk:cnode1 -q nqn.2016-06.io.spdk:host1 -a "$NVMF_FIRST_TARGET_IP" -s "$NVMF_PORT"
|
||||||
|
|
||||||
# Add the host NQN and verify that the connect succeeds
|
# Add the host NQN and verify that the connect succeeds
|
||||||
$rpc_py nvmf_subsystem_add_host nqn.2016-06.io.spdk:cnode1 nqn.2016-06.io.spdk:host1
|
$rpc_py nvmf_subsystem_add_host nqn.2016-06.io.spdk:cnode1 nqn.2016-06.io.spdk:host1
|
||||||
@ -69,7 +69,7 @@ nvme disconnect -n nqn.2016-06.io.spdk:cnode1
|
|||||||
|
|
||||||
# Remove the host and verify that the connect fails
|
# Remove the host and verify that the connect fails
|
||||||
$rpc_py nvmf_subsystem_remove_host nqn.2016-06.io.spdk:cnode1 nqn.2016-06.io.spdk:host1
|
$rpc_py nvmf_subsystem_remove_host nqn.2016-06.io.spdk:cnode1 nqn.2016-06.io.spdk:host1
|
||||||
! nvme connect -t $TEST_TRANSPORT -n nqn.2016-06.io.spdk:cnode1 -q nqn.2016-06.io.spdk:host1 -a "$NVMF_FIRST_TARGET_IP" -s "$NVMF_PORT"
|
NOT nvme connect -t $TEST_TRANSPORT -n nqn.2016-06.io.spdk:cnode1 -q nqn.2016-06.io.spdk:host1 -a "$NVMF_FIRST_TARGET_IP" -s "$NVMF_PORT"
|
||||||
|
|
||||||
# Allow any host and verify that the connect succeeds
|
# Allow any host and verify that the connect succeeds
|
||||||
$rpc_py nvmf_subsystem_allow_any_host -e nqn.2016-06.io.spdk:cnode1
|
$rpc_py nvmf_subsystem_allow_any_host -e nqn.2016-06.io.spdk:cnode1
|
||||||
|
@ -57,7 +57,7 @@ $rpc_py bdev_ocf_delete ocfWT
|
|||||||
|
|
||||||
# Check that ocfWT was deleted properly
|
# Check that ocfWT was deleted properly
|
||||||
|
|
||||||
! $rpc_py bdev_ocf_get_bdevs | jq -r '.[] .name' | grep -qw ocfWT
|
[[ -z $("$rpc_py" bdev_ocf_get_bdevs | jq -r '.[] | select(.name == "ocfWT") | .name') ]]
|
||||||
|
|
||||||
trap - SIGINT SIGTERM EXIT
|
trap - SIGINT SIGTERM EXIT
|
||||||
|
|
||||||
@ -73,7 +73,7 @@ waitforlisten $spdk_pid
|
|||||||
|
|
||||||
# Check that ocfWT was not loaded on app start
|
# Check that ocfWT was not loaded on app start
|
||||||
|
|
||||||
! $rpc_py bdev_ocf_get_bdevs | jq -r '.[] .name' | grep -qw ocfWT
|
[[ -z $("$rpc_py" bdev_ocf_get_bdevs | jq -r '.[] | select(name == "ocfWT") | .name') ]]
|
||||||
|
|
||||||
trap - SIGINT SIGTERM EXIT
|
trap - SIGINT SIGTERM EXIT
|
||||||
|
|
||||||
|
@ -372,14 +372,15 @@ _get_thread_stats() {
|
|||||||
|
|
||||||
get_cpu_stat() {
|
get_cpu_stat() {
|
||||||
local cpu_idx=$1
|
local cpu_idx=$1
|
||||||
local stat=$2 stats
|
local stat=$2 stats astats
|
||||||
|
|
||||||
while read -r cpu stats; do
|
while read -r cpu stats; do
|
||||||
[[ $cpu == "cpu$cpu_idx" ]] && stats=($stats)
|
[[ $cpu == "cpu$cpu_idx" ]] && astats=($stats)
|
||||||
done < /proc/stat
|
done < /proc/stat
|
||||||
|
|
||||||
case "$stat" in
|
case "$stat" in
|
||||||
idle) echo "${stats[3]}" ;;
|
idle) echo "${astats[3]}" ;;
|
||||||
|
all) printf '%u\n' "${astats[@]}" ;;
|
||||||
*) ;;
|
*) ;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
@ -395,3 +396,124 @@ destroy_thread() {
|
|||||||
active_thread() {
|
active_thread() {
|
||||||
"$rootdir/scripts/rpc.py" --plugin "$plugin" scheduler_thread_set_active "$@"
|
"$rootdir/scripts/rpc.py" --plugin "$plugin" scheduler_thread_set_active "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get_cpu_time() {
|
||||||
|
xtrace_disable
|
||||||
|
|
||||||
|
local interval=$1 cpu_time=$2 interval_count
|
||||||
|
shift 2
|
||||||
|
local cpus=("$@") cpu
|
||||||
|
local stats stat old_stats avg_load
|
||||||
|
local total_sample
|
||||||
|
|
||||||
|
# Exposed for the caller
|
||||||
|
local -g cpu_times=()
|
||||||
|
local -g avg_cpu_time=()
|
||||||
|
|
||||||
|
# cpu_time:
|
||||||
|
# 0 - user (time spent in user mode)
|
||||||
|
# 1 - nice (Time spent in user mode with low priority)
|
||||||
|
# 2 - system (Time spent in system mode)
|
||||||
|
# 3 - idle (Time spent in the idle task)
|
||||||
|
# 4 - iowait (Time waiting for I/O to complete)
|
||||||
|
# 5 - irq (Time servicing interrupts)
|
||||||
|
# 6 - softirq (Time servicing softirqs)
|
||||||
|
# 7 - steal (Stolen time)
|
||||||
|
# 8 - guest (Time spent running a virtual CPU)
|
||||||
|
# 9 - guest_nice (Time spent running a niced guest)
|
||||||
|
|
||||||
|
local -A cpu_time_map
|
||||||
|
cpu_time_map["user"]=0
|
||||||
|
cpu_time_map["nice"]=1
|
||||||
|
cpu_time_map["system"]=2
|
||||||
|
cpu_time_map["idle"]=3
|
||||||
|
cpu_time_map["iowait"]=4
|
||||||
|
cpu_time_map["irq"]=5
|
||||||
|
cpu_time_map["softirq"]=6
|
||||||
|
cpu_time_map["steal"]=7
|
||||||
|
cpu_time_map["guest"]=8
|
||||||
|
cpu_time_map["guest_nice"]=9
|
||||||
|
|
||||||
|
# Clear up the env
|
||||||
|
unset -v ${!stat_@}
|
||||||
|
unset -v ${!old_stat_@}
|
||||||
|
unset -v ${!avg_stat@}
|
||||||
|
unset -v ${!avg_load@}
|
||||||
|
|
||||||
|
cpu_time=${cpu_time_map["$cpu_time"]:-3}
|
||||||
|
interval=$((interval <= 0 ? 1 : interval))
|
||||||
|
# We skip first sample to have min 2 for stat comparision
|
||||||
|
interval=$((interval + 1)) interval_count=0
|
||||||
|
while ((interval_count++, --interval >= 0)); do
|
||||||
|
for cpu in "${cpus[@]}"; do
|
||||||
|
local -n old_stats=old_stats_$cpu
|
||||||
|
local -n avg_load=avg_load_$cpu
|
||||||
|
sample_stats=() total_sample=0
|
||||||
|
|
||||||
|
stats=($(get_cpu_stat "$cpu" all))
|
||||||
|
if ((interval_count == 1)); then
|
||||||
|
# Skip first sample
|
||||||
|
old_stats=("${stats[@]}")
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
for stat in "${!stats[@]}"; do
|
||||||
|
avg_load[stat]="stat_${stat}_${cpu}[@]"
|
||||||
|
sample_stats[stat]=$((stats[stat] - old_stats[stat]))
|
||||||
|
: $((total_sample += sample_stats[stat]))
|
||||||
|
done
|
||||||
|
for stat in "${!stats[@]}"; do
|
||||||
|
local -n avg_stat=stat_${stat}_${cpu}
|
||||||
|
avg_stat+=($((sample_stats[stat] * 100 / (total_sample == 0 ? 1 : total_sample))))
|
||||||
|
done
|
||||||
|
old_stats=("${stats[@]}")
|
||||||
|
done
|
||||||
|
sleep 1s
|
||||||
|
done
|
||||||
|
|
||||||
|
# We collected % for each time. Now determine the avg % for requested time.
|
||||||
|
local load stat_load
|
||||||
|
for cpu in "${cpus[@]}"; do
|
||||||
|
load=0
|
||||||
|
local -n avg_load_cpu=avg_load_$cpu
|
||||||
|
stat_load=("${!avg_load_cpu[cpu_time]}")
|
||||||
|
for stat in "${stat_load[@]}"; do
|
||||||
|
: $((load += stat))
|
||||||
|
done
|
||||||
|
cpu_times[cpu]=${stat_load[*]}
|
||||||
|
avg_cpu_time[cpu]=$((load / ${#stat_load[@]}))
|
||||||
|
done
|
||||||
|
|
||||||
|
xtrace_restore
|
||||||
|
}
|
||||||
|
|
||||||
|
collect_cpu_idle() {
|
||||||
|
((${#cpus_to_collect[@]} > 0)) || return 1
|
||||||
|
|
||||||
|
local time=${1:-5}
|
||||||
|
local cpu
|
||||||
|
local samples
|
||||||
|
local -g is_idle=()
|
||||||
|
|
||||||
|
printf 'Collecting cpu idle stats (cpus: %s) for %u seconds...\n' \
|
||||||
|
"${cpus_to_collect[*]}" "$time"
|
||||||
|
|
||||||
|
get_cpu_time "$time" idle "${cpus_to_collect[@]}"
|
||||||
|
|
||||||
|
for cpu in "${cpus_to_collect[@]}"; do
|
||||||
|
samples=(${cpu_times[cpu]})
|
||||||
|
printf '* cpu%u idle samples: %s (avg: %u%%)\n' \
|
||||||
|
"$cpu" "${samples[*]}" "${avg_cpu_time[cpu]}"
|
||||||
|
# Cores with polling reactors have 0% idle time,
|
||||||
|
# while the ones in interrupt mode won't have 100% idle.
|
||||||
|
# Work can be potentially be scheduled to the core by kernel,
|
||||||
|
# to prevent that affecting tests set reasonably high idle limit.
|
||||||
|
# Consider last sample
|
||||||
|
if ((samples[-1] >= 70)); then
|
||||||
|
printf '* cpu%u is idle\n' "$cpu"
|
||||||
|
is_idle[cpu]=1
|
||||||
|
else
|
||||||
|
printf '*cpu%u is not idle\n' "$cpu"
|
||||||
|
is_idle[cpu]=0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
@ -86,7 +86,8 @@ verify_dpdk_governor() {
|
|||||||
elif ((main_core_setspeed < old_main_core_setspeed)); then
|
elif ((main_core_setspeed < old_main_core_setspeed)); then
|
||||||
dir=0
|
dir=0
|
||||||
elif ((main_core_setspeed == old_main_core_setspeed)); then
|
elif ((main_core_setspeed == old_main_core_setspeed)); then
|
||||||
# Frequency didn't change, skip
|
# Frequency didn't change, skip and wait for a bit
|
||||||
|
sleep 0.5s
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -15,62 +15,6 @@ fold_list_onto_array cpus $(parse_cpu_list <(echo "$spdk_cpus_csv"))
|
|||||||
# Normalize the indexes
|
# Normalize the indexes
|
||||||
cpus=("${cpus[@]}")
|
cpus=("${cpus[@]}")
|
||||||
|
|
||||||
collect_cpu_stat() {
|
|
||||||
local list=$1
|
|
||||||
local stat=$2
|
|
||||||
|
|
||||||
for cpu in "${cpus_to_collect[@]}"; do
|
|
||||||
eval "${list}[cpu]=\$(get_cpu_stat $cpu $stat)"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
collect_cpu_idle() {
|
|
||||||
xtrace_disable
|
|
||||||
|
|
||||||
local sample_time=${1:-5} samples=0
|
|
||||||
local cpu bool inc user_hz
|
|
||||||
|
|
||||||
# idle scales to USER_HZ so we use that in order to determine the expected
|
|
||||||
# value it should have been increased to (more or less).
|
|
||||||
user_hz=100
|
|
||||||
# Expected increase of the idle stat
|
|
||||||
inc=$((user_hz * sample_time))
|
|
||||||
|
|
||||||
bool[0]="not" bool[1]="is"
|
|
||||||
|
|
||||||
init_idle_samples=() idle_samples=() is_idle=()
|
|
||||||
|
|
||||||
collect_cpu_stat init_idle_samples idle
|
|
||||||
|
|
||||||
printf 'Collecting cpu idle stats (cpus: %s) for %u seconds...\n' \
|
|
||||||
"${cpus_to_collect[*]}" "$sample_time"
|
|
||||||
|
|
||||||
while ((++samples <= sample_time)) && sleep 1s; do
|
|
||||||
collect_cpu_stat idle_samples idle
|
|
||||||
done
|
|
||||||
|
|
||||||
for cpu in "${!idle_samples[@]}"; do
|
|
||||||
# We start to collect after the spdk app is initialized hence if the interrupt
|
|
||||||
# mode is not working as expected, the idle time of given cpu will not have a
|
|
||||||
# chance to increase. If it does work correctly, then it should change even for
|
|
||||||
# a fraction, depending on how much time we spent on collecting this data.
|
|
||||||
# If idle time is over 70% of expected increase then we consider this cpu as
|
|
||||||
# idle. This is done in order to take into consideration time window the app
|
|
||||||
# needs to actually spin up|down the cpu. It's also taken for granted that
|
|
||||||
# there is no extra load on the target cpus which may be coming from other
|
|
||||||
# processes.
|
|
||||||
if ((idle_samples[cpu] > init_idle_samples[cpu] + (inc * 70 / 100))); then
|
|
||||||
is_idle[cpu]=1
|
|
||||||
else
|
|
||||||
is_idle[cpu]=0
|
|
||||||
fi
|
|
||||||
printf 'cpu%u %s idle (%u %u)\n' \
|
|
||||||
"$cpu" "${bool[is_idle[cpu]]}" "${init_idle_samples[cpu]}" "${idle_samples[cpu]}"
|
|
||||||
done
|
|
||||||
|
|
||||||
xtrace_restore
|
|
||||||
}
|
|
||||||
|
|
||||||
interrupt() {
|
interrupt() {
|
||||||
local busy_cpus
|
local busy_cpus
|
||||||
local cpu thread
|
local cpu thread
|
||||||
|
@ -43,3 +43,6 @@ function check_match() {
|
|||||||
$rootdir/test/app/match/match $testdir/match_files/${MATCH_FILE}.match
|
$rootdir/test/app/match/match $testdir/match_files/${MATCH_FILE}.match
|
||||||
rm -f $testdir/match_files/${MATCH_FILE}
|
rm -f $testdir/match_files/${MATCH_FILE}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Allocate 5GB of hugepages to have some overhead for run_*()s
|
||||||
|
HUGEMEM=5120 CLEAR_HUGE=yes "$rootdir/scripts/setup.sh"
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"cpumask": "$(S)",
|
"cpumask": "0x3",
|
||||||
"ctrlr": "vhost_scsi1",
|
"ctrlr": "vhost_scsi1",
|
||||||
"delay_base_us": 20,
|
"delay_base_us": 20,
|
||||||
"iops_threshold": 1000000,
|
"iops_threshold": 1000000,
|
||||||
|
@ -7,9 +7,9 @@ o- nvmf ........................................................................
|
|||||||
| | o- hosts .......................................................................................................... [Hosts: 1]
|
| | o- hosts .......................................................................................................... [Hosts: 1]
|
||||||
| | | o- nqn.2014-08.org.spdk:cnode2 ....................................................................................... [...]
|
| | | o- nqn.2014-08.org.spdk:cnode2 ....................................................................................... [...]
|
||||||
| | o- listen_addresses ........................................................................................... [Addresses: 3]
|
| | o- listen_addresses ........................................................................................... [Addresses: 3]
|
||||||
| | | o- $(N).$(N).$(N).$(N):4260 $(S) [RDMA]
|
| | | o- $(N).$(N).$(N).$(N):4260 $(S) [$(S)]
|
||||||
| | | o- $(N).$(N).$(N).$(N):4261 $(S) [RDMA]
|
| | | o- $(N).$(N).$(N).$(N):4261 $(S) [$(S)]
|
||||||
| | | o- $(N).$(N).$(N).$(N):4262 $(S) [RDMA]
|
| | | o- $(N).$(N).$(N).$(N):4262 $(S) [$(S)]
|
||||||
| | o- namespaces ................................................................................................ [Namespaces: 4]
|
| | o- namespaces ................................................................................................ [Namespaces: 4]
|
||||||
| | o- Malloc3 .................................................................................................... [Malloc3, 1]
|
| | o- Malloc3 .................................................................................................... [Malloc3, 1]
|
||||||
| | o- Malloc4 .................................................................................................... [Malloc4, 2]
|
| | o- Malloc4 .................................................................................................... [Malloc4, 2]
|
||||||
@ -18,7 +18,7 @@ o- nvmf ........................................................................
|
|||||||
| o- nqn.2014-08.org.spdk:cnode2 ...................................................... [sn=$(S), st=NVMe, Allow any host]
|
| o- nqn.2014-08.org.spdk:cnode2 ...................................................... [sn=$(S), st=NVMe, Allow any host]
|
||||||
| | o- hosts .......................................................................................................... [Hosts: 0]
|
| | o- hosts .......................................................................................................... [Hosts: 0]
|
||||||
| | o- listen_addresses ........................................................................................... [Addresses: 1]
|
| | o- listen_addresses ........................................................................................... [Addresses: 1]
|
||||||
| | | o- $(N).$(N).$(N).$(N):4260 $(S) [RDMA]
|
| | | o- $(N).$(N).$(N).$(N):4260 $(S) [$(S)]
|
||||||
| | o- namespaces ................................................................................................ [Namespaces: 1]
|
| | o- namespaces ................................................................................................ [Namespaces: 1]
|
||||||
| | o- Malloc2 .................................................................................................... [Malloc2, 1]
|
| | o- Malloc2 .................................................................................................... [Malloc2, 1]
|
||||||
| o- nqn.2014-08.org.spdk:cnode3 ...................................................... [sn=$(S), st=NVMe, Allow any host]
|
| o- nqn.2014-08.org.spdk:cnode3 ...................................................... [sn=$(S), st=NVMe, Allow any host]
|
||||||
@ -26,9 +26,9 @@ o- nvmf ........................................................................
|
|||||||
| | o- nqn.2014-08.org.spdk:cnode1 ....................................................................................... [...]
|
| | o- nqn.2014-08.org.spdk:cnode1 ....................................................................................... [...]
|
||||||
| | o- nqn.2014-08.org.spdk:cnode2 ....................................................................................... [...]
|
| | o- nqn.2014-08.org.spdk:cnode2 ....................................................................................... [...]
|
||||||
| o- listen_addresses ........................................................................................... [Addresses: 2]
|
| o- listen_addresses ........................................................................................... [Addresses: 2]
|
||||||
| | o- $(N).$(N).$(N).$(N):4260 $(S) [RDMA]
|
| | o- $(N).$(N).$(N).$(N):4260 $(S) [$(S)]
|
||||||
| | o- $(N).$(N).$(N).$(N):4261 $(S) [RDMA]
|
| | o- $(N).$(N).$(N).$(N):4261 $(S) [$(S)]
|
||||||
| o- namespaces ................................................................................................ [Namespaces: 1]
|
| o- namespaces ................................................................................................ [Namespaces: 1]
|
||||||
| o- Malloc1 .................................................................................................... [Malloc1, 1]
|
| o- Malloc1 .................................................................................................... [Malloc1, 1]
|
||||||
o- transport ..................................................................................................... [Transports: 1]
|
o- transport ..................................................................................................... [Transports: 1]
|
||||||
o- RDMA .................................................................................................................. [...]
|
o- $(S) $(*) [...]
|
||||||
|
@ -10,14 +10,16 @@ MATCH_FILE="spdkcli_nvmf.test"
|
|||||||
SPDKCLI_BRANCH="/nvmf"
|
SPDKCLI_BRANCH="/nvmf"
|
||||||
|
|
||||||
trap 'on_error_exit; revert_soft_roce' ERR
|
trap 'on_error_exit; revert_soft_roce' ERR
|
||||||
rdma_device_init
|
|
||||||
|
|
||||||
timing_enter run_nvmf_tgt
|
timing_enter run_nvmf_tgt
|
||||||
run_nvmf_tgt
|
run_nvmf_tgt
|
||||||
timing_exit run_nvmf_tgt
|
timing_exit run_nvmf_tgt
|
||||||
|
|
||||||
RDMA_IP_LIST=$(get_available_rdma_ips)
|
NVMF_TARGET_IP="127.0.0.1"
|
||||||
NVMF_TARGET_IP=$(echo "$RDMA_IP_LIST" | head -n 1)
|
if [[ $TEST_TRANSPORT == "rdma" ]]; then
|
||||||
|
rdma_device_init
|
||||||
|
NVMF_TARGET_IP=$(get_available_rdma_ips | head -n 1)
|
||||||
|
fi
|
||||||
|
|
||||||
timing_enter spdkcli_create_nvmf_config
|
timing_enter spdkcli_create_nvmf_config
|
||||||
$spdkcli_job "'/bdevs/malloc create 32 512 Malloc1' 'Malloc1' True
|
$spdkcli_job "'/bdevs/malloc create 32 512 Malloc1' 'Malloc1' True
|
||||||
@ -26,33 +28,33 @@ $spdkcli_job "'/bdevs/malloc create 32 512 Malloc1' 'Malloc1' True
|
|||||||
'/bdevs/malloc create 32 512 Malloc4' 'Malloc4' True
|
'/bdevs/malloc create 32 512 Malloc4' 'Malloc4' True
|
||||||
'/bdevs/malloc create 32 512 Malloc5' 'Malloc5' True
|
'/bdevs/malloc create 32 512 Malloc5' 'Malloc5' True
|
||||||
'/bdevs/malloc create 32 512 Malloc6' 'Malloc6' True
|
'/bdevs/malloc create 32 512 Malloc6' 'Malloc6' True
|
||||||
'nvmf/transport create RDMA max_io_qpairs_per_ctrlr=4 io_unit_size=8192' '' True
|
'nvmf/transport create $TEST_TRANSPORT max_io_qpairs_per_ctrlr=4 io_unit_size=8192' '' True
|
||||||
'/nvmf/subsystem create nqn.2014-08.org.spdk:cnode1 N37SXV509SRW\
|
'/nvmf/subsystem create nqn.2014-08.org.spdk:cnode1 N37SXV509SRW\
|
||||||
max_namespaces=4 allow_any_host=True' 'nqn.2014-08.org.spdk:cnode1' True
|
max_namespaces=4 allow_any_host=True' 'nqn.2014-08.org.spdk:cnode1' True
|
||||||
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode1/namespaces create Malloc3 1' 'Malloc3' True
|
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode1/namespaces create Malloc3 1' 'Malloc3' True
|
||||||
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode1/namespaces create Malloc4 2' 'Malloc4' True
|
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode1/namespaces create Malloc4 2' 'Malloc4' True
|
||||||
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode1/listen_addresses create \
|
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode1/listen_addresses create \
|
||||||
RDMA $NVMF_TARGET_IP 4260 IPv4' '$NVMF_TARGET_IP:4260' True
|
$TEST_TRANSPORT $NVMF_TARGET_IP 4260 IPv4' '$NVMF_TARGET_IP:4260' True
|
||||||
'/nvmf/subsystem create nqn.2014-08.org.spdk:cnode2 N37SXV509SRD\
|
'/nvmf/subsystem create nqn.2014-08.org.spdk:cnode2 N37SXV509SRD\
|
||||||
max_namespaces=2 allow_any_host=True' 'nqn.2014-08.org.spdk:cnode2' True
|
max_namespaces=2 allow_any_host=True' 'nqn.2014-08.org.spdk:cnode2' True
|
||||||
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode2/namespaces create Malloc2' 'Malloc2' True
|
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode2/namespaces create Malloc2' 'Malloc2' True
|
||||||
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode2/listen_addresses create \
|
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode2/listen_addresses create \
|
||||||
RDMA $NVMF_TARGET_IP 4260 IPv4' '$NVMF_TARGET_IP:4260' True
|
$TEST_TRANSPORT $NVMF_TARGET_IP 4260 IPv4' '$NVMF_TARGET_IP:4260' True
|
||||||
'/nvmf/subsystem create nqn.2014-08.org.spdk:cnode3 N37SXV509SRR\
|
'/nvmf/subsystem create nqn.2014-08.org.spdk:cnode3 N37SXV509SRR\
|
||||||
max_namespaces=2 allow_any_host=True' 'nqn.2014-08.org.spdk:cnode2' True
|
max_namespaces=2 allow_any_host=True' 'nqn.2014-08.org.spdk:cnode2' True
|
||||||
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode3/namespaces create Malloc1' 'Malloc1' True
|
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode3/namespaces create Malloc1' 'Malloc1' True
|
||||||
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode3/listen_addresses create \
|
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode3/listen_addresses create \
|
||||||
RDMA $NVMF_TARGET_IP 4260 IPv4' '$NVMF_TARGET_IP:4260' True
|
$TEST_TRANSPORT $NVMF_TARGET_IP 4260 IPv4' '$NVMF_TARGET_IP:4260' True
|
||||||
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode3/listen_addresses create \
|
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode3/listen_addresses create \
|
||||||
RDMA $NVMF_TARGET_IP 4261 IPv4' '$NVMF_TARGET_IP:4261' True
|
$TEST_TRANSPORT $NVMF_TARGET_IP 4261 IPv4' '$NVMF_TARGET_IP:4261' True
|
||||||
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode3/hosts create \
|
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode3/hosts create \
|
||||||
nqn.2014-08.org.spdk:cnode1' 'nqn.2014-08.org.spdk:cnode1' True
|
nqn.2014-08.org.spdk:cnode1' 'nqn.2014-08.org.spdk:cnode1' True
|
||||||
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode3/hosts create \
|
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode3/hosts create \
|
||||||
nqn.2014-08.org.spdk:cnode2' 'nqn.2014-08.org.spdk:cnode2' True
|
nqn.2014-08.org.spdk:cnode2' 'nqn.2014-08.org.spdk:cnode2' True
|
||||||
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode1 allow_any_host True' 'Allow any host'
|
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode1 allow_any_host True' 'Allow any host'
|
||||||
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode1 allow_any_host False' 'Allow any host' True
|
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode1 allow_any_host False' 'Allow any host' True
|
||||||
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode1/listen_addresses create RDMA $NVMF_TARGET_IP 4261 IPv4' '$NVMF_TARGET_IP:4261' True
|
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode1/listen_addresses create $TEST_TRANSPORT $NVMF_TARGET_IP 4261 IPv4' '$NVMF_TARGET_IP:4261' True
|
||||||
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode1/listen_addresses create RDMA $NVMF_TARGET_IP 4262 IPv4' '$NVMF_TARGET_IP:4262' True
|
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode1/listen_addresses create $TEST_TRANSPORT $NVMF_TARGET_IP 4262 IPv4' '$NVMF_TARGET_IP:4262' True
|
||||||
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode1/hosts create nqn.2014-08.org.spdk:cnode2' 'nqn.2014-08.org.spdk:cnode2' True
|
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode1/hosts create nqn.2014-08.org.spdk:cnode2' 'nqn.2014-08.org.spdk:cnode2' True
|
||||||
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode1/namespaces create Malloc5' 'Malloc5' True
|
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode1/namespaces create Malloc5' 'Malloc5' True
|
||||||
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode1/namespaces create Malloc6' 'Malloc6' True
|
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode1/namespaces create Malloc6' 'Malloc6' True
|
||||||
@ -68,7 +70,7 @@ $spdkcli_job "'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode1/namespaces delete nsi
|
|||||||
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode1/namespaces delete_all' 'Malloc4'
|
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode1/namespaces delete_all' 'Malloc4'
|
||||||
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode1/hosts delete nqn.2014-08.org.spdk:cnode2' 'nqn.2014-08.org.spdk:cnode2'
|
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode1/hosts delete nqn.2014-08.org.spdk:cnode2' 'nqn.2014-08.org.spdk:cnode2'
|
||||||
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode3/hosts delete_all' 'nqn.2014-08.org.spdk:cnode1'
|
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode3/hosts delete_all' 'nqn.2014-08.org.spdk:cnode1'
|
||||||
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode1/listen_addresses delete RDMA $NVMF_TARGET_IP 4262' '$NVMF_TARGET_IP:4262'
|
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode1/listen_addresses delete $TEST_TRANSPORT $NVMF_TARGET_IP 4262' '$NVMF_TARGET_IP:4262'
|
||||||
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode1/listen_addresses delete_all' '$NVMF_TARGET_IP:4261'
|
'/nvmf/subsystem/nqn.2014-08.org.spdk:cnode1/listen_addresses delete_all' '$NVMF_TARGET_IP:4261'
|
||||||
'/nvmf/subsystem delete nqn.2014-08.org.spdk:cnode3' 'nqn.2014-08.org.spdk:cnode3'
|
'/nvmf/subsystem delete nqn.2014-08.org.spdk:cnode3' 'nqn.2014-08.org.spdk:cnode3'
|
||||||
'/nvmf/subsystem delete_all' 'nqn.2014-08.org.spdk:cnode2'
|
'/nvmf/subsystem delete_all' 'nqn.2014-08.org.spdk:cnode2'
|
||||||
|
@ -120,7 +120,7 @@ test_spdk_app_parse_args(void)
|
|||||||
"-d",
|
"-d",
|
||||||
"-p",
|
"-p",
|
||||||
"--single-file-segments",
|
"--single-file-segments",
|
||||||
"--silence-noticelog"
|
"--silence-noticelog",
|
||||||
"-R"
|
"-R"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -44,6 +44,9 @@
|
|||||||
#define NUM_ENGINES_PER_GROUP 1
|
#define NUM_ENGINES_PER_GROUP 1
|
||||||
#define TOTAL_WQS (NUM_GROUPS * NUM_WQ_PER_GROUP)
|
#define TOTAL_WQS (NUM_GROUPS * NUM_WQ_PER_GROUP)
|
||||||
#define TOTAL_ENGINES (NUM_GROUPS * NUM_ENGINES_PER_GROUP)
|
#define TOTAL_ENGINES (NUM_GROUPS * NUM_ENGINES_PER_GROUP)
|
||||||
|
#define GRP_CFG_OFFSET 0x400
|
||||||
|
#define MAX_TOKENS 0x40
|
||||||
|
#define MAX_ARRAY_SIZE 0x20
|
||||||
|
|
||||||
DEFINE_STUB(spdk_pci_idxd_get_driver, struct spdk_pci_driver *, (void), NULL);
|
DEFINE_STUB(spdk_pci_idxd_get_driver, struct spdk_pci_driver *, (void), NULL);
|
||||||
|
|
||||||
@ -108,6 +111,10 @@ test_idxd_wq_config(void)
|
|||||||
SPDK_CU_ASSERT_FATAL(idxd.reg_base != NULL);
|
SPDK_CU_ASSERT_FATAL(idxd.reg_base != NULL);
|
||||||
|
|
||||||
g_dev_cfg = &g_dev_cfg0;
|
g_dev_cfg = &g_dev_cfg0;
|
||||||
|
SPDK_CU_ASSERT_FATAL(g_dev_cfg->num_groups <= MAX_ARRAY_SIZE);
|
||||||
|
idxd.groups = calloc(g_dev_cfg->num_groups, sizeof(struct idxd_group));
|
||||||
|
SPDK_CU_ASSERT_FATAL(idxd.groups != NULL);
|
||||||
|
|
||||||
idxd.registers.wqcap.total_wq_size = TOTAL_WQE_SIZE;
|
idxd.registers.wqcap.total_wq_size = TOTAL_WQE_SIZE;
|
||||||
idxd.registers.wqcap.num_wqs = TOTAL_WQS;
|
idxd.registers.wqcap.num_wqs = TOTAL_WQS;
|
||||||
idxd.registers.gencap.max_batch_shift = LOG2_WQ_MAX_BATCH;
|
idxd.registers.gencap.max_batch_shift = LOG2_WQ_MAX_BATCH;
|
||||||
@ -138,12 +145,11 @@ test_idxd_wq_config(void)
|
|||||||
|
|
||||||
free(idxd.queues);
|
free(idxd.queues);
|
||||||
free(idxd.reg_base);
|
free(idxd.reg_base);
|
||||||
|
free(idxd.groups);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define GRP_CFG_OFFSET 0x400
|
|
||||||
#define MAX_TOKENS 0x40
|
|
||||||
static int
|
static int
|
||||||
test_idxd_group_config(void)
|
test_idxd_group_config(void)
|
||||||
{
|
{
|
||||||
|
@ -1993,6 +1993,43 @@ pdu_hdr_op_data_test(void)
|
|||||||
g_task_pool_is_empty = false;
|
g_task_pool_is_empty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Test an ISCSI_OP_TEXT PDU with CONTINUE bit set but
|
||||||
|
* no data.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
empty_text_with_cbit_test(void)
|
||||||
|
{
|
||||||
|
struct spdk_iscsi_sess sess = {};
|
||||||
|
struct spdk_iscsi_conn conn = {};
|
||||||
|
struct spdk_scsi_dev dev = {};
|
||||||
|
struct spdk_iscsi_pdu *req_pdu;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
req_pdu = iscsi_get_pdu(&conn);
|
||||||
|
|
||||||
|
sess.ExpCmdSN = 0;
|
||||||
|
sess.MaxCmdSN = 64;
|
||||||
|
sess.session_type = SESSION_TYPE_NORMAL;
|
||||||
|
sess.MaxBurstLength = 1024;
|
||||||
|
|
||||||
|
conn.full_feature = 1;
|
||||||
|
conn.sess = &sess;
|
||||||
|
conn.dev = &dev;
|
||||||
|
conn.state = ISCSI_CONN_STATE_RUNNING;
|
||||||
|
|
||||||
|
memset(&req_pdu->bhs, 0, sizeof(req_pdu->bhs));
|
||||||
|
req_pdu->bhs.opcode = ISCSI_OP_TEXT;
|
||||||
|
req_pdu->bhs.flags = ISCSI_TEXT_CONTINUE;
|
||||||
|
|
||||||
|
rc = iscsi_pdu_hdr_handle(&conn, req_pdu);
|
||||||
|
CU_ASSERT(rc == 0);
|
||||||
|
CU_ASSERT(!req_pdu->is_rejected);
|
||||||
|
rc = iscsi_pdu_payload_handle(&conn, req_pdu);
|
||||||
|
CU_ASSERT(rc == 0);
|
||||||
|
|
||||||
|
iscsi_put_pdu(req_pdu);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
@ -2024,6 +2061,7 @@ main(int argc, char **argv)
|
|||||||
CU_ADD_TEST(suite, pdu_hdr_op_task_mgmt_test);
|
CU_ADD_TEST(suite, pdu_hdr_op_task_mgmt_test);
|
||||||
CU_ADD_TEST(suite, pdu_hdr_op_nopout_test);
|
CU_ADD_TEST(suite, pdu_hdr_op_nopout_test);
|
||||||
CU_ADD_TEST(suite, pdu_hdr_op_data_test);
|
CU_ADD_TEST(suite, pdu_hdr_op_data_test);
|
||||||
|
CU_ADD_TEST(suite, empty_text_with_cbit_test);
|
||||||
|
|
||||||
CU_basic_set_mode(CU_BRM_VERBOSE);
|
CU_basic_set_mode(CU_BRM_VERBOSE);
|
||||||
CU_basic_run_tests();
|
CU_basic_run_tests();
|
||||||
|
@ -264,6 +264,14 @@ parse_valid_test(void)
|
|||||||
EXPECT_VAL("F", "IIII");
|
EXPECT_VAL("F", "IIII");
|
||||||
CU_ASSERT_PTR_NULL(partial_parameter);
|
CU_ASSERT_PTR_NULL(partial_parameter);
|
||||||
|
|
||||||
|
/* partial parameter: NULL data */
|
||||||
|
/* It is technically allowed to have a TEXT PDU with no data, yet
|
||||||
|
* CONTINUE bit is enabled - make sure we handle that case correctly.
|
||||||
|
*/
|
||||||
|
rc = iscsi_parse_params(¶ms, NULL, 0, true, &partial_parameter);
|
||||||
|
CU_ASSERT(rc == 0);
|
||||||
|
CU_ASSERT_PTR_NULL(partial_parameter);
|
||||||
|
|
||||||
/* Second partial parameter is the only parameter */
|
/* Second partial parameter is the only parameter */
|
||||||
PARSE("OOOO", true, &partial_parameter);
|
PARSE("OOOO", true, &partial_parameter);
|
||||||
CU_ASSERT_STRING_EQUAL(partial_parameter, "OOOO");
|
CU_ASSERT_STRING_EQUAL(partial_parameter, "OOOO");
|
||||||
|
@ -2162,6 +2162,27 @@ test_nvme_ctrlr_init_set_keep_alive_timeout(void)
|
|||||||
nvme_ctrlr_destruct(&ctrlr);
|
nvme_ctrlr_destruct(&ctrlr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_alloc_io_qpair_fail(void)
|
||||||
|
{
|
||||||
|
struct spdk_nvme_ctrlr ctrlr = {};
|
||||||
|
struct spdk_nvme_qpair *q0;
|
||||||
|
|
||||||
|
setup_qpairs(&ctrlr, 1);
|
||||||
|
|
||||||
|
/* Modify the connect_qpair return code to inject a failure */
|
||||||
|
g_connect_qpair_return_code = 1;
|
||||||
|
|
||||||
|
/* Attempt to allocate a qpair, this should fail */
|
||||||
|
q0 = spdk_nvme_ctrlr_alloc_io_qpair(&ctrlr, NULL, 0);
|
||||||
|
SPDK_CU_ASSERT_FATAL(q0 == NULL);
|
||||||
|
|
||||||
|
/* Verify that the qpair is removed from the lists */
|
||||||
|
SPDK_CU_ASSERT_FATAL(TAILQ_EMPTY(&ctrlr.active_io_qpairs));
|
||||||
|
|
||||||
|
cleanup_qpairs(&ctrlr);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
CU_pSuite suite = NULL;
|
CU_pSuite suite = NULL;
|
||||||
@ -2200,6 +2221,7 @@ int main(int argc, char **argv)
|
|||||||
CU_ADD_TEST(suite, test_nvme_ctrlr_init_set_nvmf_ioccsz);
|
CU_ADD_TEST(suite, test_nvme_ctrlr_init_set_nvmf_ioccsz);
|
||||||
CU_ADD_TEST(suite, test_nvme_ctrlr_init_set_num_queues);
|
CU_ADD_TEST(suite, test_nvme_ctrlr_init_set_num_queues);
|
||||||
CU_ADD_TEST(suite, test_nvme_ctrlr_init_set_keep_alive_timeout);
|
CU_ADD_TEST(suite, test_nvme_ctrlr_init_set_keep_alive_timeout);
|
||||||
|
CU_ADD_TEST(suite, test_alloc_io_qpair_fail);
|
||||||
|
|
||||||
CU_basic_set_mode(CU_BRM_VERBOSE);
|
CU_basic_set_mode(CU_BRM_VERBOSE);
|
||||||
CU_basic_run_tests();
|
CU_basic_run_tests();
|
||||||
|
@ -71,7 +71,8 @@ test_nvme_ns_construct(void)
|
|||||||
{
|
{
|
||||||
struct spdk_nvme_ns ns = {};
|
struct spdk_nvme_ns ns = {};
|
||||||
uint32_t id = 1;
|
uint32_t id = 1;
|
||||||
struct spdk_nvme_ctrlr ctrlr = {};
|
struct spdk_nvme_ns_data nsdata = {};
|
||||||
|
struct spdk_nvme_ctrlr ctrlr = { .nsdata = &nsdata };
|
||||||
|
|
||||||
nvme_ns_construct(&ns, id, &ctrlr);
|
nvme_ns_construct(&ns, id, &ctrlr);
|
||||||
CU_ASSERT(ns.id == 1);
|
CU_ASSERT(ns.id == 1);
|
||||||
|
@ -240,6 +240,7 @@ prepare_for_test(struct spdk_nvme_ns *ns, struct spdk_nvme_ctrlr *ctrlr,
|
|||||||
}
|
}
|
||||||
ns->md_size = md_size;
|
ns->md_size = md_size;
|
||||||
ns->sectors_per_max_io = spdk_nvme_ns_get_max_io_xfer_size(ns) / ns->extended_lba_size;
|
ns->sectors_per_max_io = spdk_nvme_ns_get_max_io_xfer_size(ns) / ns->extended_lba_size;
|
||||||
|
ns->sectors_per_max_io_no_md = spdk_nvme_ns_get_max_io_xfer_size(ns) / ns->sector_size;
|
||||||
ns->sectors_per_stripe = stripe_size / ns->extended_lba_size;
|
ns->sectors_per_stripe = stripe_size / ns->extended_lba_size;
|
||||||
|
|
||||||
memset(qpair, 0, sizeof(*qpair));
|
memset(qpair, 0, sizeof(*qpair));
|
||||||
@ -909,11 +910,7 @@ test_nvme_ns_cmd_comparev_with_md(void)
|
|||||||
* Protection information enabled + PRACT
|
* Protection information enabled + PRACT
|
||||||
*
|
*
|
||||||
* Special case for 8-byte metadata + PI + PRACT: no metadata transferred
|
* Special case for 8-byte metadata + PI + PRACT: no metadata transferred
|
||||||
* In theory, 256 blocks * 512 bytes per block = one I/O (128 KB)
|
* 256 blocks * 512 bytes per block = single 128 KB I/O (no splitting required)
|
||||||
* However, the splitting code does not account for PRACT when calculating
|
|
||||||
* max sectors per transfer, so we actually get two I/Os:
|
|
||||||
* child 0: 252 blocks
|
|
||||||
* child 1: 4 blocks
|
|
||||||
*/
|
*/
|
||||||
prepare_for_test(&ns, &ctrlr, &qpair, 512, 8, 128 * 1024, 0, true);
|
prepare_for_test(&ns, &ctrlr, &qpair, 512, 8, 128 * 1024, 0, true);
|
||||||
ns.flags |= SPDK_NVME_NS_DPS_PI_SUPPORTED;
|
ns.flags |= SPDK_NVME_NS_DPS_PI_SUPPORTED;
|
||||||
@ -923,18 +920,11 @@ test_nvme_ns_cmd_comparev_with_md(void)
|
|||||||
|
|
||||||
SPDK_CU_ASSERT_FATAL(rc == 0);
|
SPDK_CU_ASSERT_FATAL(rc == 0);
|
||||||
SPDK_CU_ASSERT_FATAL(g_request != NULL);
|
SPDK_CU_ASSERT_FATAL(g_request != NULL);
|
||||||
SPDK_CU_ASSERT_FATAL(g_request->num_children == 2);
|
SPDK_CU_ASSERT_FATAL(g_request->num_children == 0);
|
||||||
child0 = TAILQ_FIRST(&g_request->children);
|
|
||||||
|
|
||||||
SPDK_CU_ASSERT_FATAL(child0 != NULL);
|
CU_ASSERT(g_request->payload.md == NULL);
|
||||||
CU_ASSERT(child0->payload_offset == 0);
|
CU_ASSERT(g_request->payload_offset == 0);
|
||||||
CU_ASSERT(child0->payload_size == 252 * 512); /* NOTE: does not include metadata! */
|
CU_ASSERT(g_request->payload_size == 256 * 512); /* NOTE: does not include metadata! */
|
||||||
child1 = TAILQ_NEXT(child0, child_tailq);
|
|
||||||
|
|
||||||
SPDK_CU_ASSERT_FATAL(child1 != NULL);
|
|
||||||
CU_ASSERT(child1->payload.md == NULL);
|
|
||||||
CU_ASSERT(child1->payload_offset == 252 * 512);
|
|
||||||
CU_ASSERT(child1->payload_size == 4 * 512);
|
|
||||||
|
|
||||||
nvme_request_free_children(g_request);
|
nvme_request_free_children(g_request);
|
||||||
nvme_free_request(g_request);
|
nvme_free_request(g_request);
|
||||||
@ -1373,11 +1363,7 @@ test_nvme_ns_cmd_write_with_md(void)
|
|||||||
* Protection information enabled + PRACT
|
* Protection information enabled + PRACT
|
||||||
*
|
*
|
||||||
* Special case for 8-byte metadata + PI + PRACT: no metadata transferred
|
* Special case for 8-byte metadata + PI + PRACT: no metadata transferred
|
||||||
* In theory, 256 blocks * 512 bytes per block = one I/O (128 KB)
|
* 256 blocks * 512 bytes per block = single 128 KB I/O (no splitting required)
|
||||||
* However, the splitting code does not account for PRACT when calculating
|
|
||||||
* max sectors per transfer, so we actually get two I/Os:
|
|
||||||
* child 0: 252 blocks
|
|
||||||
* child 1: 4 blocks
|
|
||||||
*/
|
*/
|
||||||
prepare_for_test(&ns, &ctrlr, &qpair, 512, 8, 128 * 1024, 0, true);
|
prepare_for_test(&ns, &ctrlr, &qpair, 512, 8, 128 * 1024, 0, true);
|
||||||
ns.flags |= SPDK_NVME_NS_DPS_PI_SUPPORTED;
|
ns.flags |= SPDK_NVME_NS_DPS_PI_SUPPORTED;
|
||||||
@ -1387,18 +1373,11 @@ test_nvme_ns_cmd_write_with_md(void)
|
|||||||
|
|
||||||
SPDK_CU_ASSERT_FATAL(rc == 0);
|
SPDK_CU_ASSERT_FATAL(rc == 0);
|
||||||
SPDK_CU_ASSERT_FATAL(g_request != NULL);
|
SPDK_CU_ASSERT_FATAL(g_request != NULL);
|
||||||
SPDK_CU_ASSERT_FATAL(g_request->num_children == 2);
|
SPDK_CU_ASSERT_FATAL(g_request->num_children == 0);
|
||||||
child0 = TAILQ_FIRST(&g_request->children);
|
|
||||||
|
|
||||||
SPDK_CU_ASSERT_FATAL(child0 != NULL);
|
CU_ASSERT(g_request->payload.md == NULL);
|
||||||
CU_ASSERT(child0->payload_offset == 0);
|
CU_ASSERT(g_request->payload_offset == 0);
|
||||||
CU_ASSERT(child0->payload_size == 252 * 512); /* NOTE: does not include metadata! */
|
CU_ASSERT(g_request->payload_size == 256 * 512); /* NOTE: does not include metadata! */
|
||||||
child1 = TAILQ_NEXT(child0, child_tailq);
|
|
||||||
|
|
||||||
SPDK_CU_ASSERT_FATAL(child1 != NULL);
|
|
||||||
CU_ASSERT(child1->payload.md == NULL);
|
|
||||||
CU_ASSERT(child1->payload_offset == 252 * 512);
|
|
||||||
CU_ASSERT(child1->payload_size == 4 * 512);
|
|
||||||
|
|
||||||
nvme_request_free_children(g_request);
|
nvme_request_free_children(g_request);
|
||||||
nvme_free_request(g_request);
|
nvme_free_request(g_request);
|
||||||
@ -1758,11 +1737,7 @@ test_nvme_ns_cmd_compare_with_md(void)
|
|||||||
* Protection information enabled + PRACT
|
* Protection information enabled + PRACT
|
||||||
*
|
*
|
||||||
* Special case for 8-byte metadata + PI + PRACT: no metadata transferred
|
* Special case for 8-byte metadata + PI + PRACT: no metadata transferred
|
||||||
* In theory, 256 blocks * 512 bytes per block = one I/O (128 KB)
|
* 256 blocks * 512 bytes per block = single 128 KB I/O (no splitting required)
|
||||||
* However, the splitting code does not account for PRACT when calculating
|
|
||||||
* max sectors per transfer, so we actually get two I/Os:
|
|
||||||
* child 0: 252 blocks
|
|
||||||
* child 1: 4 blocks
|
|
||||||
*/
|
*/
|
||||||
prepare_for_test(&ns, &ctrlr, &qpair, 512, 8, 128 * 1024, 0, true);
|
prepare_for_test(&ns, &ctrlr, &qpair, 512, 8, 128 * 1024, 0, true);
|
||||||
ns.flags |= SPDK_NVME_NS_DPS_PI_SUPPORTED;
|
ns.flags |= SPDK_NVME_NS_DPS_PI_SUPPORTED;
|
||||||
@ -1772,18 +1747,11 @@ test_nvme_ns_cmd_compare_with_md(void)
|
|||||||
|
|
||||||
SPDK_CU_ASSERT_FATAL(rc == 0);
|
SPDK_CU_ASSERT_FATAL(rc == 0);
|
||||||
SPDK_CU_ASSERT_FATAL(g_request != NULL);
|
SPDK_CU_ASSERT_FATAL(g_request != NULL);
|
||||||
SPDK_CU_ASSERT_FATAL(g_request->num_children == 2);
|
SPDK_CU_ASSERT_FATAL(g_request->num_children == 0);
|
||||||
child0 = TAILQ_FIRST(&g_request->children);
|
|
||||||
|
|
||||||
SPDK_CU_ASSERT_FATAL(child0 != NULL);
|
CU_ASSERT(g_request->payload.md == NULL);
|
||||||
CU_ASSERT(child0->payload_offset == 0);
|
CU_ASSERT(g_request->payload_offset == 0);
|
||||||
CU_ASSERT(child0->payload_size == 252 * 512); /* NOTE: does not include metadata! */
|
CU_ASSERT(g_request->payload_size == 256 * 512); /* NOTE: does not include metadata! */
|
||||||
child1 = TAILQ_NEXT(child0, child_tailq);
|
|
||||||
|
|
||||||
SPDK_CU_ASSERT_FATAL(child1 != NULL);
|
|
||||||
CU_ASSERT(child1->payload.md == NULL);
|
|
||||||
CU_ASSERT(child1->payload_offset == 252 * 512);
|
|
||||||
CU_ASSERT(child1->payload_size == 4 * 512);
|
|
||||||
|
|
||||||
nvme_request_free_children(g_request);
|
nvme_request_free_children(g_request);
|
||||||
nvme_free_request(g_request);
|
nvme_free_request(g_request);
|
||||||
|
@ -267,28 +267,56 @@ create_controller_test(void)
|
|||||||
int ret;
|
int ret;
|
||||||
char long_name[PATH_MAX];
|
char long_name[PATH_MAX];
|
||||||
|
|
||||||
spdk_cpuset_set_cpu(&g_vhost_core_mask, 0, true);
|
spdk_cpuset_parse(&g_vhost_core_mask, "0xf");
|
||||||
|
|
||||||
|
/* Create device with cpumask implcitly matching whole application */
|
||||||
|
ret = alloc_vdev(&vdev, "vdev_name_0", NULL);
|
||||||
|
SPDK_CU_ASSERT_FATAL(ret == 0 && vdev);
|
||||||
|
SPDK_CU_ASSERT_FATAL(!strcmp(spdk_cpuset_fmt(spdk_thread_get_cpumask(vdev->thread)), "f"));
|
||||||
|
cleanup_vdev(vdev);
|
||||||
|
|
||||||
|
/* Create device with cpumask matching whole application */
|
||||||
|
ret = alloc_vdev(&vdev, "vdev_name_0", "0xf");
|
||||||
|
SPDK_CU_ASSERT_FATAL(ret == 0 && vdev);
|
||||||
|
SPDK_CU_ASSERT_FATAL(!strcmp(spdk_cpuset_fmt(spdk_thread_get_cpumask(vdev->thread)), "f"));
|
||||||
|
cleanup_vdev(vdev);
|
||||||
|
|
||||||
|
/* Create device with single core in cpumask */
|
||||||
|
ret = alloc_vdev(&vdev, "vdev_name_0", "0x2");
|
||||||
|
SPDK_CU_ASSERT_FATAL(ret == 0 && vdev);
|
||||||
|
SPDK_CU_ASSERT_FATAL(!strcmp(spdk_cpuset_fmt(spdk_thread_get_cpumask(vdev->thread)), "2"));
|
||||||
|
cleanup_vdev(vdev);
|
||||||
|
|
||||||
|
/* Create device with cpumask spanning two cores */
|
||||||
|
ret = alloc_vdev(&vdev, "vdev_name_0", "0x3");
|
||||||
|
SPDK_CU_ASSERT_FATAL(ret == 0 && vdev);
|
||||||
|
SPDK_CU_ASSERT_FATAL(!strcmp(spdk_cpuset_fmt(spdk_thread_get_cpumask(vdev->thread)), "3"));
|
||||||
|
cleanup_vdev(vdev);
|
||||||
|
|
||||||
|
/* Create device with incorrect cpumask outside of application cpumask */
|
||||||
|
ret = alloc_vdev(&vdev, "vdev_name_0", "0xf0");
|
||||||
|
SPDK_CU_ASSERT_FATAL(ret != 0);
|
||||||
|
|
||||||
|
/* Create device with incorrect cpumask partially outside of application cpumask */
|
||||||
|
ret = alloc_vdev(&vdev, "vdev_name_0", "0xff");
|
||||||
|
SPDK_CU_ASSERT_FATAL(ret != 0);
|
||||||
|
|
||||||
/* Create device with no name */
|
/* Create device with no name */
|
||||||
ret = alloc_vdev(&vdev, NULL, "0x1");
|
ret = alloc_vdev(&vdev, NULL, NULL);
|
||||||
CU_ASSERT(ret != 0);
|
|
||||||
|
|
||||||
/* Create device with incorrect cpumask */
|
|
||||||
ret = alloc_vdev(&vdev, "vdev_name_0", "0x2");
|
|
||||||
CU_ASSERT(ret != 0);
|
CU_ASSERT(ret != 0);
|
||||||
|
|
||||||
/* Create device with too long name and path */
|
/* Create device with too long name and path */
|
||||||
memset(long_name, 'x', sizeof(long_name));
|
memset(long_name, 'x', sizeof(long_name));
|
||||||
long_name[PATH_MAX - 1] = 0;
|
long_name[PATH_MAX - 1] = 0;
|
||||||
snprintf(dev_dirname, sizeof(dev_dirname), "some_path/");
|
snprintf(dev_dirname, sizeof(dev_dirname), "some_path/");
|
||||||
ret = alloc_vdev(&vdev, long_name, "0x1");
|
ret = alloc_vdev(&vdev, long_name, NULL);
|
||||||
CU_ASSERT(ret != 0);
|
CU_ASSERT(ret != 0);
|
||||||
dev_dirname[0] = 0;
|
dev_dirname[0] = 0;
|
||||||
|
|
||||||
/* Create device when device name is already taken */
|
/* Create device when device name is already taken */
|
||||||
ret = alloc_vdev(&vdev, "vdev_name_0", "0x1");
|
ret = alloc_vdev(&vdev, "vdev_name_0", NULL);
|
||||||
SPDK_CU_ASSERT_FATAL(ret == 0 && vdev);
|
SPDK_CU_ASSERT_FATAL(ret == 0 && vdev);
|
||||||
ret = alloc_vdev(&vdev2, "vdev_name_0", "0x1");
|
ret = alloc_vdev(&vdev2, "vdev_name_0", NULL);
|
||||||
CU_ASSERT(ret != 0);
|
CU_ASSERT(ret != 0);
|
||||||
cleanup_vdev(vdev);
|
cleanup_vdev(vdev);
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ VM_DIR=$VHOST_DIR/vms
|
|||||||
TARGET_DIR=$VHOST_DIR/vhost
|
TARGET_DIR=$VHOST_DIR/vhost
|
||||||
VM_PASSWORD="root"
|
VM_PASSWORD="root"
|
||||||
|
|
||||||
VM_IMAGE=$HOME/spdk_test_image.qcow2
|
VM_IMAGE=${VM_IMAGE:-"$DEPENDENCY_DIR/spdk_test_image.qcow2"}
|
||||||
|
|
||||||
if ! hash $QEMU_IMG_BIN $QEMU_BIN; then
|
if ! hash $QEMU_IMG_BIN $QEMU_BIN; then
|
||||||
error 'QEMU is not installed on this system. Unable to run vhost tests.'
|
error 'QEMU is not installed on this system. Unable to run vhost tests.'
|
||||||
@ -27,22 +27,17 @@ source $rootdir/test/vhost/common/autotest.config
|
|||||||
function vhosttestinit() {
|
function vhosttestinit() {
|
||||||
if [ "$TEST_MODE" == "iso" ]; then
|
if [ "$TEST_MODE" == "iso" ]; then
|
||||||
$rootdir/scripts/setup.sh
|
$rootdir/scripts/setup.sh
|
||||||
|
fi
|
||||||
|
|
||||||
# Look for the VM image
|
if [[ -e $VM_IMAGE.gz ]]; then
|
||||||
if [[ ! -f $VM_IMAGE ]]; then
|
gzip -dc "$VM_IMAGE.gz" > "$VM_IMAGE"
|
||||||
echo "VM image not found at $VM_IMAGE"
|
|
||||||
echo "Download to $HOME? [yn]"
|
|
||||||
read -r download
|
|
||||||
if [ "$download" = "y" ]; then
|
|
||||||
curl https://ci.spdk.io/download/test_resources/vhost_vm_image.tar.gz | tar xz -C $HOME
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Look for the VM image
|
# Look for the VM image
|
||||||
if [[ "$1" != "--no_vm" ]] && [[ ! -f $VM_IMAGE ]]; then
|
if [[ ! -f $VM_IMAGE ]]; then
|
||||||
error "VM image not found at $VM_IMAGE"
|
[[ $1 != "--no_vm" ]] || return 0
|
||||||
exit 1
|
echo "$VM_IMAGE is missing" >&2
|
||||||
|
return 1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ rpc_py="$rootdir/scripts/rpc.py -s $(get_vhost_dir 0)/rpc.sock"
|
|||||||
|
|
||||||
for vm_conf in "${vms[@]}"; do
|
for vm_conf in "${vms[@]}"; do
|
||||||
IFS=',' read -ra conf <<< "$vm_conf"
|
IFS=',' read -ra conf <<< "$vm_conf"
|
||||||
if [[ x"${conf[0]}" == x"" ]] || ! assert_number ${conf[0]}; then
|
if [[ -z ${conf[0]} ]] || ! assert_number ${conf[0]}; then
|
||||||
fail "invalid VM configuration syntax $vm_conf"
|
fail "invalid VM configuration syntax $vm_conf"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ function print_test_fio_header() {
|
|||||||
function vms_setup() {
|
function vms_setup() {
|
||||||
for vm_conf in "${vms[@]}"; do
|
for vm_conf in "${vms[@]}"; do
|
||||||
IFS=',' read -ra conf <<< "$vm_conf"
|
IFS=',' read -ra conf <<< "$vm_conf"
|
||||||
if [[ x"${conf[0]}" == x"" ]] || ! assert_number ${conf[0]}; then
|
if [[ -z ${conf[0]} ]] || ! assert_number ${conf[0]}; then
|
||||||
fail "invalid VM configuration syntax $vm_conf"
|
fail "invalid VM configuration syntax $vm_conf"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ function err_cleanup() {
|
|||||||
|
|
||||||
# start vhost and configure it
|
# start vhost and configure it
|
||||||
trap 'err_cleanup; exit 1' SIGINT SIGTERM EXIT
|
trap 'err_cleanup; exit 1' SIGINT SIGTERM EXIT
|
||||||
$SPDK_BIN_DIR/vhost &
|
$SPDK_BIN_DIR/vhost -m 0xf &
|
||||||
vhost_pid=$!
|
vhost_pid=$!
|
||||||
waitforlisten $vhost_pid
|
waitforlisten $vhost_pid
|
||||||
|
|
||||||
@ -35,17 +35,22 @@ rpc_cmd vhost_scsi_controller_add_target naa.Nvme0n1_scsi0.0 0 Nvme0n1p0
|
|||||||
rpc_cmd vhost_scsi_controller_add_target naa.Nvme0n1_scsi0.0 1 Nvme0n1p1
|
rpc_cmd vhost_scsi_controller_add_target naa.Nvme0n1_scsi0.0 1 Nvme0n1p1
|
||||||
rpc_cmd vhost_scsi_controller_add_target naa.Nvme0n1_scsi0.0 2 Nvme0n1p2
|
rpc_cmd vhost_scsi_controller_add_target naa.Nvme0n1_scsi0.0 2 Nvme0n1p2
|
||||||
rpc_cmd vhost_scsi_controller_add_target naa.Nvme0n1_scsi0.0 3 Nvme0n1p3
|
rpc_cmd vhost_scsi_controller_add_target naa.Nvme0n1_scsi0.0 3 Nvme0n1p3
|
||||||
|
[[ "$(rpc_cmd vhost_get_controllers -n naa.Nvme0n1_scsi0.0 | jq -r '.[].cpumask')" == "0xf" ]]
|
||||||
|
|
||||||
rpc_cmd vhost_create_blk_controller naa.Nvme0n1_blk0.0 Nvme0n1p4
|
rpc_cmd vhost_create_blk_controller naa.Nvme0n1_blk0.0 Nvme0n1p4 --cpumask 0xf
|
||||||
rpc_cmd vhost_create_blk_controller naa.Nvme0n1_blk1.0 Nvme0n1p5
|
[[ "$(rpc_cmd vhost_get_controllers -n naa.Nvme0n1_blk0.0 | jq -r '.[].cpumask')" == "0xf" ]]
|
||||||
|
rpc_cmd vhost_create_blk_controller naa.Nvme0n1_blk1.0 Nvme0n1p5 --cpumask 0x1
|
||||||
|
[[ "$(rpc_cmd vhost_get_controllers -n naa.Nvme0n1_blk1.0 | jq -r '.[].cpumask')" == "0x1" ]]
|
||||||
|
|
||||||
rpc_cmd bdev_malloc_create 128 512 --name Malloc0
|
rpc_cmd bdev_malloc_create 128 512 --name Malloc0
|
||||||
rpc_cmd vhost_create_scsi_controller naa.Malloc0.0
|
rpc_cmd vhost_create_scsi_controller naa.Malloc0.0 --cpumask 0x2
|
||||||
rpc_cmd vhost_scsi_controller_add_target naa.Malloc0.0 0 Malloc0
|
rpc_cmd vhost_scsi_controller_add_target naa.Malloc0.0 0 Malloc0
|
||||||
|
[[ "$(rpc_cmd vhost_get_controllers -n naa.Malloc0.0 | jq -r '.[].cpumask')" == "0x2" ]]
|
||||||
|
|
||||||
rpc_cmd bdev_malloc_create 128 4096 --name Malloc1
|
rpc_cmd bdev_malloc_create 128 4096 --name Malloc1
|
||||||
rpc_cmd vhost_create_scsi_controller naa.Malloc1.0
|
rpc_cmd vhost_create_scsi_controller naa.Malloc1.0 --cpumask 0xc
|
||||||
rpc_cmd vhost_scsi_controller_add_target naa.Malloc1.0 0 Malloc1
|
rpc_cmd vhost_scsi_controller_add_target naa.Malloc1.0 0 Malloc1
|
||||||
|
[[ "$(rpc_cmd vhost_get_controllers -n naa.Malloc1.0 | jq -r '.[].cpumask')" == "0xc" ]]
|
||||||
|
|
||||||
# start a dummy app, create vhost bdevs in it, then dump the config for FIO
|
# start a dummy app, create vhost bdevs in it, then dump the config for FIO
|
||||||
$SPDK_BIN_DIR/spdk_tgt -r /tmp/spdk2.sock -g &
|
$SPDK_BIN_DIR/spdk_tgt -r /tmp/spdk2.sock -g &
|
||||||
|
@ -6,7 +6,7 @@ source $rootdir/test/common/autotest_common.sh
|
|||||||
source $rootdir/test/vhost/common.sh
|
source $rootdir/test/vhost/common.sh
|
||||||
|
|
||||||
CENTOS_VM_IMAGE="/home/sys_sgsw/spdk_vhost_CentOS_vm_image.qcow2"
|
CENTOS_VM_IMAGE="/home/sys_sgsw/spdk_vhost_CentOS_vm_image.qcow2"
|
||||||
DEFAULT_FIO_BIN="/home/sys_sgsw/fio_ubuntu"
|
DEFAULT_FIO_BIN="$DEPENDENCY_DIR/fio"
|
||||||
CENTOS_FIO_BIN="/home/sys_sgsw/fio_ubuntu_bak"
|
CENTOS_FIO_BIN="/home/sys_sgsw/fio_ubuntu_bak"
|
||||||
|
|
||||||
case $1 in
|
case $1 in
|
||||||
@ -21,7 +21,7 @@ case $1 in
|
|||||||
echo " -h |--help prints this message"
|
echo " -h |--help prints this message"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Environment:"
|
echo "Environment:"
|
||||||
echo " VM_IMAGE path to QCOW2 VM image used during test (default: $HOME/spdk_test_image.qcow2)"
|
echo " VM_IMAGE path to QCOW2 VM image used during test (default: $DEPENDENCY_DIR/spdk_test_image.qcow2)"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Tests are performed only on Linux machine. For other OS no action is performed."
|
echo "Tests are performed only on Linux machine. For other OS no action is performed."
|
||||||
echo ""
|
echo ""
|
||||||
@ -38,13 +38,7 @@ if [[ $(uname -s) != Linux ]]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
: ${FIO_BIN="$DEFAULT_FIO_BIN"}
|
: ${FIO_BIN="$DEFAULT_FIO_BIN"}
|
||||||
|
vhosttestinit
|
||||||
if [[ ! -r "${VM_IMAGE}" ]]; then
|
|
||||||
echo ""
|
|
||||||
echo "ERROR: VM image '${VM_IMAGE}' does not exist."
|
|
||||||
echo ""
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
DISKS_NUMBER=$(lspci -mm -n | grep 0108 | tr -d '"' | awk -F " " '{print "0000:"$1}' | wc -l)
|
DISKS_NUMBER=$(lspci -mm -n | grep 0108 | tr -d '"' | awk -F " " '{print "0000:"$1}' | wc -l)
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ notice "==============="
|
|||||||
notice ""
|
notice ""
|
||||||
notice "running SPDK"
|
notice "running SPDK"
|
||||||
notice ""
|
notice ""
|
||||||
vhost_run 0
|
vhost_run 0 "-m 0xf"
|
||||||
notice ""
|
notice ""
|
||||||
rpc_py="$rootdir/scripts/rpc.py -s $(get_vhost_dir 0)/rpc.sock"
|
rpc_py="$rootdir/scripts/rpc.py -s $(get_vhost_dir 0)/rpc.sock"
|
||||||
$rpc_py bdev_malloc_create -b Malloc0 128 4096
|
$rpc_py bdev_malloc_create -b Malloc0 128 4096
|
||||||
@ -88,8 +88,13 @@ if $rpc_py vhost_delete_controller unk0 > /dev/null; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# SCSI
|
# SCSI
|
||||||
notice "Trying to create scsi controller with incorrect cpumask"
|
notice "Trying to create scsi controller with incorrect cpumask outside of application cpumask"
|
||||||
if $rpc_py vhost_create_scsi_controller vhost.invalid.cpumask --cpumask 0x2; then
|
if $rpc_py vhost_create_scsi_controller vhost.invalid.cpumask --cpumask 0xf0; then
|
||||||
|
error "Creating scsi controller with incorrect cpumask succeeded, but it shouldn't"
|
||||||
|
fi
|
||||||
|
|
||||||
|
notice "Trying to create scsi controller with incorrect cpumask partially outside of application cpumask"
|
||||||
|
if $rpc_py vhost_create_scsi_controller vhost.invalid.cpumask --cpumask 0xff; then
|
||||||
error "Creating scsi controller with incorrect cpumask succeeded, but it shouldn't"
|
error "Creating scsi controller with incorrect cpumask succeeded, but it shouldn't"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -167,8 +172,13 @@ notice "Re-adding device 0 to naa.0"
|
|||||||
$rpc_py vhost_scsi_controller_add_target naa.0 0 Malloc0
|
$rpc_py vhost_scsi_controller_add_target naa.0 0 Malloc0
|
||||||
|
|
||||||
# BLK
|
# BLK
|
||||||
notice "Trying to create block controller with incorrect cpumask"
|
notice "Trying to create block controller with incorrect cpumask outside of application cpumask"
|
||||||
if $rpc_py vhost_create_blk_controller vhost.invalid.cpumask Malloc0 --cpumask 0x2; then
|
if $rpc_py vhost_create_blk_controller vhost.invalid.cpumask Malloc0 --cpumask 0xf0; then
|
||||||
|
error "Creating block controller with incorrect cpumask succeeded, but it shouldn't"
|
||||||
|
fi
|
||||||
|
|
||||||
|
notice "Trying to create block controller with incorrect cpumask partially outside of application cpumask"
|
||||||
|
if $rpc_py vhost_create_blk_controller vhost.invalid.cpumask Malloc0 --cpumask 0xff; then
|
||||||
error "Creating block controller with incorrect cpumask succeeded, but it shouldn't"
|
error "Creating block controller with incorrect cpumask succeeded, but it shouldn't"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ function usage() {
|
|||||||
echo " --vm-memory=INT Amount of RAM memory (in MB) to pass to a single VM."
|
echo " --vm-memory=INT Amount of RAM memory (in MB) to pass to a single VM."
|
||||||
echo " Default: 2048 MB"
|
echo " Default: 2048 MB"
|
||||||
echo " --vm-image=PATH OS image to use for running the VMs."
|
echo " --vm-image=PATH OS image to use for running the VMs."
|
||||||
echo " Default: \$HOME/spdk_test_image.qcow2"
|
echo " Default: \$DEPENDENCY_DIR/spdk_test_image.qcow2"
|
||||||
echo " --vm-sar-enable Measure CPU utilization in guest VMs using sar."
|
echo " --vm-sar-enable Measure CPU utilization in guest VMs using sar."
|
||||||
echo " --host-sar-enable Measure CPU utilization on host using sar."
|
echo " --host-sar-enable Measure CPU utilization on host using sar."
|
||||||
echo " --sar-delay=INT Wait for X seconds before starting SAR measurement. Default: 0."
|
echo " --sar-delay=INT Wait for X seconds before starting SAR measurement. Default: 0."
|
||||||
|
@ -13,17 +13,11 @@ if [[ $(uname -s) != Linux ]]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
CENTOS_VM_IMAGE="/home/sys_sgsw/spdk_vhost_CentOS_vm_image.qcow2"
|
CENTOS_VM_IMAGE="/home/sys_sgsw/spdk_vhost_CentOS_vm_image.qcow2"
|
||||||
DEFAULT_FIO_BIN="/home/sys_sgsw/fio_ubuntu"
|
DEFAULT_FIO_BIN="$DEPENDENCY_DIR/fio"
|
||||||
CENTOS_FIO_BIN="/home/sys_sgsw/fio_ubuntu_bak"
|
CENTOS_FIO_BIN="/home/sys_sgsw/fio_ubuntu_bak"
|
||||||
|
|
||||||
: ${FIO_BIN="$DEFAULT_FIO_BIN"}
|
: ${FIO_BIN="$DEFAULT_FIO_BIN"}
|
||||||
|
vhosttestinit
|
||||||
if [[ ! -r "${VM_IMAGE}" ]]; then
|
|
||||||
echo ""
|
|
||||||
echo "ERROR: VM image '${VM_IMAGE}' does not exist."
|
|
||||||
echo ""
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
DISKS_NUMBER=$(lspci -mm -n | grep 0108 | tr -d '"' | awk -F " " '{print "0000:"$1}' | wc -l)
|
DISKS_NUMBER=$(lspci -mm -n | grep 0108 | tr -d '"' | awk -F " " '{print "0000:"$1}' | wc -l)
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ source $rootdir/test/vhost/common.sh
|
|||||||
# and OS Version: 6.3.9600 N/A Build 9600
|
# and OS Version: 6.3.9600 N/A Build 9600
|
||||||
# In order to run this test with windows vm
|
# In order to run this test with windows vm
|
||||||
# windows virtio scsi driver must be installed
|
# windows virtio scsi driver must be installed
|
||||||
WINDOWS_IMG="/home/sys_sgsw/windows_scsi_compliance/windows_vm_image.qcow2"
|
WINDOWS_IMG="$DEPENDENCY_DIR/windows_scsi_compliance/windows_vm_image.qcow2"
|
||||||
aio_file="$SPDK_TEST_STORAGE/aio_disk"
|
aio_file="$SPDK_TEST_STORAGE/aio_disk"
|
||||||
ssh_pass=""
|
ssh_pass=""
|
||||||
vm_num=1
|
vm_num=1
|
||||||
|
Loading…
Reference in New Issue
Block a user