summaryrefslogtreecommitdiffstats
path: root/src/spdk/test/nvme/cuse
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
commit19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch)
tree42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/spdk/test/nvme/cuse
parentInitial commit. (diff)
downloadceph-upstream/16.2.11+ds.tar.xz
ceph-upstream/16.2.11+ds.zip
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/spdk/test/nvme/cuse')
-rw-r--r--src/spdk/test/nvme/cuse/.gitignore1
-rw-r--r--src/spdk/test/nvme/cuse/Makefile38
-rw-r--r--src/spdk/test/nvme/cuse/cuse.c189
-rwxr-xr-xsrc/spdk/test/nvme/cuse/nvme_cuse.sh46
-rwxr-xr-xsrc/spdk/test/nvme/cuse/nvme_cuse_rpc.sh58
-rwxr-xr-xsrc/spdk/test/nvme/cuse/nvme_ns_manage_cuse.sh164
-rwxr-xr-xsrc/spdk/test/nvme/cuse/spdk_nvme_cli_cuse.sh109
-rwxr-xr-xsrc/spdk/test/nvme/cuse/spdk_smartctl_cuse.sh79
8 files changed, 684 insertions, 0 deletions
diff --git a/src/spdk/test/nvme/cuse/.gitignore b/src/spdk/test/nvme/cuse/.gitignore
new file mode 100644
index 000000000..b13d42337
--- /dev/null
+++ b/src/spdk/test/nvme/cuse/.gitignore
@@ -0,0 +1 @@
+cuse
diff --git a/src/spdk/test/nvme/cuse/Makefile b/src/spdk/test/nvme/cuse/Makefile
new file mode 100644
index 000000000..c847fe13f
--- /dev/null
+++ b/src/spdk/test/nvme/cuse/Makefile
@@ -0,0 +1,38 @@
+#
+# BSD LICENSE
+#
+# Copyright (c) Intel Corporation.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../..)
+
+TEST_FILE = cuse.c
+
+include $(SPDK_ROOT_DIR)/mk/spdk.unittest.mk
diff --git a/src/spdk/test/nvme/cuse/cuse.c b/src/spdk/test/nvme/cuse/cuse.c
new file mode 100644
index 000000000..fe5c26f0c
--- /dev/null
+++ b/src/spdk/test/nvme/cuse/cuse.c
@@ -0,0 +1,189 @@
+
+/*-
+ * BSD LICENSE
+ *
+ * Copyright (c) Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "spdk_cunit.h"
+
+#include "common/lib/test_env.c"
+#include "nvme/nvme_cuse.c"
+
+DEFINE_STUB(nvme_io_msg_send, int, (struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid,
+ spdk_nvme_io_msg_fn fn, void *arg), 0);
+
+DEFINE_STUB(spdk_nvme_ctrlr_alloc_cmb_io_buffer, void *, (struct spdk_nvme_ctrlr *ctrlr,
+ size_t size), NULL);
+
+DEFINE_STUB(spdk_nvme_ctrlr_cmd_admin_raw, int, (struct spdk_nvme_ctrlr *ctrlr,
+ struct spdk_nvme_cmd *cmd, void *buf, uint32_t len,
+ spdk_nvme_cmd_cb cb_fn, void *cb_arg), 0);
+
+DEFINE_STUB(spdk_nvme_ctrlr_get_num_ns, uint32_t, (struct spdk_nvme_ctrlr *ctrlr), 128);
+
+static uint32_t g_active_num_ns = 4;
+static uint32_t g_active_nsid_min = 1;
+
+bool
+spdk_nvme_ctrlr_is_active_ns(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid)
+{
+ return nsid >= g_active_nsid_min && nsid < g_active_num_ns + g_active_nsid_min;
+}
+
+DEFINE_STUB(spdk_nvme_ctrlr_reset, int, (struct spdk_nvme_ctrlr *ctrlr), 0);
+
+DEFINE_STUB(spdk_nvme_ns_cmd_read, int, (struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
+ void *payload,
+ uint64_t lba, uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg,
+ uint32_t io_flags), 0);
+
+DEFINE_STUB(spdk_nvme_ns_cmd_write, int, (struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
+ void *payload,
+ uint64_t lba, uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg,
+ uint32_t io_flags), 0);
+
+DEFINE_STUB(spdk_nvme_ns_get_num_sectors, uint64_t, (struct spdk_nvme_ns *ns), 0);
+
+DEFINE_STUB(spdk_nvme_ns_get_sector_size, uint32_t, (struct spdk_nvme_ns *ns), 0);
+
+DEFINE_STUB_V(spdk_unaffinitize_thread, (void));
+
+DEFINE_STUB(spdk_nvme_ctrlr_get_ns, struct spdk_nvme_ns *, (struct spdk_nvme_ctrlr *ctrlr,
+ uint32_t nsid), NULL);
+
+static bool
+wait_for_file(char *filename, bool exists)
+{
+ int i;
+
+ for (i = 0; i < 1000; i++) {
+ if ((access(filename, F_OK) != -1) ^ (!exists)) {
+ return true;
+ }
+ usleep(100);
+ }
+ return false;
+}
+
+static void
+verify_devices(struct spdk_nvme_ctrlr *ctrlr)
+{
+ char ctrlr_name[256];
+ size_t ctrlr_name_size;
+ char ctrlr_dev[256], ns_dev[256 + 10];
+ uint32_t nsid, num_ns;
+ int rv;
+
+ ctrlr_name_size = sizeof(ctrlr_name);
+ rv = spdk_nvme_cuse_get_ctrlr_name(ctrlr, ctrlr_name, &ctrlr_name_size);
+ SPDK_CU_ASSERT_FATAL(rv == 0);
+
+ rv = snprintf(ctrlr_dev, sizeof(ctrlr_dev), "/dev/%s", ctrlr_name);
+ CU_ASSERT(rv > 0);
+ CU_ASSERT(wait_for_file(ctrlr_dev, true));
+
+ num_ns = spdk_nvme_ctrlr_get_num_ns(ctrlr);
+
+ for (nsid = 1; nsid <= num_ns; nsid++) {
+ snprintf(ns_dev, sizeof(ns_dev), "%sn%" PRIu32, ctrlr_dev, nsid);
+ if (spdk_nvme_ctrlr_is_active_ns(ctrlr, nsid)) {
+ CU_ASSERT(wait_for_file(ns_dev, true));
+ } else {
+ CU_ASSERT(wait_for_file(ns_dev, false));
+ }
+ }
+
+ /* Next one should never exist */
+ snprintf(ns_dev, sizeof(ns_dev), "%sn%" PRIu32, ctrlr_dev, nsid);
+ CU_ASSERT(wait_for_file(ns_dev, false));
+}
+
+static void
+test_cuse_update(void)
+{
+ int rc;
+ struct spdk_nvme_ctrlr ctrlr = {};
+
+ rc = nvme_cuse_start(&ctrlr);
+ CU_ASSERT(rc == 0);
+
+ g_active_num_ns = 4;
+ g_active_nsid_min = 1;
+ nvme_cuse_update(&ctrlr);
+ verify_devices(&ctrlr);
+
+ g_active_num_ns = 0;
+ nvme_cuse_update(&ctrlr);
+ verify_devices(&ctrlr);
+
+ g_active_num_ns = 4;
+ g_active_nsid_min = spdk_nvme_ctrlr_get_num_ns(&ctrlr) - g_active_num_ns;
+ nvme_cuse_update(&ctrlr);
+ verify_devices(&ctrlr);
+
+ g_active_num_ns = 2;
+ g_active_nsid_min = 2;
+ nvme_cuse_update(&ctrlr);
+ verify_devices(&ctrlr);
+
+ g_active_num_ns = 10;
+ g_active_nsid_min = 5;
+ nvme_cuse_update(&ctrlr);
+ verify_devices(&ctrlr);
+
+ g_active_num_ns = 5;
+ g_active_nsid_min = 3;
+ nvme_cuse_update(&ctrlr);
+ verify_devices(&ctrlr);
+
+ g_active_num_ns = 6;
+ g_active_nsid_min = 1;
+ nvme_cuse_update(&ctrlr);
+ verify_devices(&ctrlr);
+
+ nvme_cuse_stop(&ctrlr);
+}
+
+int main(int argc, char **argv)
+{
+ CU_pSuite suite = NULL;
+ unsigned int num_failures;
+
+ CU_set_error_action(CUEA_ABORT);
+ CU_initialize_registry();
+ suite = CU_add_suite("nvme_cuse", NULL, NULL);
+ CU_ADD_TEST(suite, test_cuse_update);
+ CU_basic_set_mode(CU_BRM_VERBOSE);
+ CU_basic_run_tests();
+ num_failures = CU_get_number_of_failures();
+ CU_cleanup_registry();
+ return num_failures;
+}
diff --git a/src/spdk/test/nvme/cuse/nvme_cuse.sh b/src/spdk/test/nvme/cuse/nvme_cuse.sh
new file mode 100755
index 000000000..699cd5ac8
--- /dev/null
+++ b/src/spdk/test/nvme/cuse/nvme_cuse.sh
@@ -0,0 +1,46 @@
+#!/usr/bin/env bash
+
+testdir=$(readlink -f $(dirname $0))
+rootdir=$(readlink -f $testdir/../../..)
+source $rootdir/scripts/common.sh
+source $rootdir/test/common/autotest_common.sh
+
+if [[ $(uname) != "Linux" ]]; then
+ echo "NVMe cuse tests only supported on Linux"
+ exit 1
+fi
+
+modprobe cuse
+run_test "nvme_cuse_app" $testdir/cuse
+run_test "nvme_cuse_rpc" $testdir/nvme_cuse_rpc.sh
+run_test "nvme_cli_cuse" $testdir/spdk_nvme_cli_cuse.sh
+run_test "nvme_smartctl_cuse" $testdir/spdk_smartctl_cuse.sh
+
+# Only run Namespace managment test case when such device is present
+bdfs=$(get_nvme_bdfs)
+
+$rootdir/scripts/setup.sh reset
+sleep 1
+
+# Find bdf that supports Namespace managment
+for bdf in $bdfs; do
+ nvme_name=$(get_nvme_ctrlr_from_bdf ${bdf})
+ if [[ -z "$nvme_name" ]]; then
+ continue
+ fi
+
+ # Check Optional Admin Command Support for Namespace Management
+ oacs=$(nvme id-ctrl /dev/${nvme_name} | grep oacs | cut -d: -f2)
+ oacs_ns_manage=$((oacs & 0x8))
+
+ if [[ "$oacs_ns_manage" -ne 0 ]]; then
+ break
+ fi
+done
+
+if [[ "$oacs_ns_manage" -ne 0 ]]; then
+ run_test "nvme_ns_manage_cuse" $testdir/nvme_ns_manage_cuse.sh
+fi
+$rootdir/scripts/setup.sh
+
+rmmod cuse
diff --git a/src/spdk/test/nvme/cuse/nvme_cuse_rpc.sh b/src/spdk/test/nvme/cuse/nvme_cuse_rpc.sh
new file mode 100755
index 000000000..eaf0dbd9c
--- /dev/null
+++ b/src/spdk/test/nvme/cuse/nvme_cuse_rpc.sh
@@ -0,0 +1,58 @@
+#!/usr/bin/env bash
+
+testdir=$(readlink -f $(dirname $0))
+rootdir=$(readlink -f $testdir/../../..)
+source $rootdir/scripts/common.sh
+source $rootdir/test/common/autotest_common.sh
+
+rpc_py=$rootdir/scripts/rpc.py
+
+bdf=$(get_first_nvme_bdf)
+ctrlr_base="/dev/spdk/nvme"
+
+$SPDK_BIN_DIR/spdk_tgt -m 0x3 &
+spdk_tgt_pid=$!
+trap 'kill -9 ${spdk_tgt_pid}; exit 1' SIGINT SIGTERM EXIT
+
+waitforlisten $spdk_tgt_pid
+
+$rpc_py bdev_nvme_attach_controller -b Nvme0 -t PCIe -a ${bdf}
+$rpc_py bdev_nvme_cuse_register -n Nvme0
+
+sleep 5
+
+if [ ! -c "${ctrlr_base}0" ]; then
+ exit 1
+fi
+
+$rpc_py bdev_get_bdevs
+$rpc_py bdev_nvme_get_controllers
+
+$rpc_py bdev_nvme_cuse_unregister -n Nvme0
+sleep 1
+if [ -c "${ctrlr_base}0" ]; then
+ exit 1
+fi
+
+# Verify removing non-existent cuse device
+$rpc_py bdev_nvme_cuse_unregister -n Nvme0 && false
+
+$rpc_py bdev_nvme_cuse_register -n Nvme0
+sleep 1
+
+if [ ! -c "${ctrlr_base}0" ]; then
+ exit 1
+fi
+
+# Verify adding same nvme controller twice fails
+$rpc_py bdev_nvme_cuse_register -n Nvme0 && false
+sleep 1
+
+if [ -c "${ctrlr_base}1" ]; then
+ exit 1
+fi
+
+$rpc_py bdev_nvme_detach_controller Nvme0
+
+trap - SIGINT SIGTERM EXIT
+killprocess $spdk_tgt_pid
diff --git a/src/spdk/test/nvme/cuse/nvme_ns_manage_cuse.sh b/src/spdk/test/nvme/cuse/nvme_ns_manage_cuse.sh
new file mode 100755
index 000000000..fb390f34e
--- /dev/null
+++ b/src/spdk/test/nvme/cuse/nvme_ns_manage_cuse.sh
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+testdir=$(readlink -f $(dirname $0))
+rootdir=$(readlink -f $testdir/../../..)
+source $rootdir/scripts/common.sh
+source $rootdir/test/common/autotest_common.sh
+
+NVME_CMD="/usr/local/src/nvme-cli/nvme"
+
+rpc_py=$rootdir/scripts/rpc.py
+
+$rootdir/scripts/setup.sh
+sleep 1
+
+bdfs=$(get_nvme_bdfs)
+
+$rootdir/scripts/setup.sh reset
+sleep 1
+
+# Find bdf that supports Namespace Managment
+for bdf in $bdfs; do
+ nvme_name=$(get_nvme_ctrlr_from_bdf ${bdf})
+ if [[ -z "$nvme_name" ]]; then
+ continue
+ fi
+
+ # Check Optional Admin Command Support for Namespace Management
+ oacs=$($NVME_CMD id-ctrl /dev/${nvme_name} | grep oacs | cut -d: -f2)
+ oacs_ns_manage=$((oacs & 0x8))
+
+ if [[ "$oacs_ns_manage" -ne 0 ]]; then
+ break
+ fi
+done
+
+if [[ "${nvme_name}" == "" ]] || [[ "$oacs_ns_manage" -eq 0 ]]; then
+ echo "No NVMe device supporting Namespace managment found"
+ $rootdir/scripts/setup.sh
+ exit 1
+fi
+
+nvme_dev=/dev/${nvme_name}
+
+# Detect supported features and configuration
+oaes=$($NVME_CMD id-ctrl ${nvme_dev} | grep oaes | cut -d: -f2)
+aer_ns_change=$((oaes & 0x100))
+
+function reset_nvme_if_aer_unsupported() {
+ if [[ "$aer_ns_change" -eq "0" ]]; then
+ sleep 1
+ $NVME_CMD reset "$1" || true
+ fi
+}
+
+function clean_up() {
+ $rootdir/scripts/setup.sh reset
+
+ # This assumes every NVMe controller contains single namespace,
+ # encompassing Total NVM Capacity and formatted as 512 block size.
+ # 512 block size is needed for test/vhost/vhost_boot.sh to
+ # succesfully run.
+
+ tnvmcap=$($NVME_CMD id-ctrl ${nvme_dev} | grep tnvmcap | cut -d: -f2)
+ blksize=512
+
+ size=$((tnvmcap / blksize))
+
+ echo "Restoring $nvme_dev..."
+ $NVME_CMD detach-ns ${nvme_dev} -n 0xffffffff -c 0 || true
+ $NVME_CMD delete-ns ${nvme_dev} -n 0xffffffff || true
+ $NVME_CMD create-ns ${nvme_dev} -s ${size} -c ${size} -b ${blksize}
+ $NVME_CMD attach-ns ${nvme_dev} -n 1 -c 0
+ $NVME_CMD reset ${nvme_dev}
+
+ $rootdir/scripts/setup.sh
+}
+
+function info_print() {
+ echo "---"
+ echo "$@"
+ echo "---"
+}
+
+# Prepare controller
+info_print "delete all namespaces"
+$NVME_CMD detach-ns ${nvme_dev} -n 0xffffffff -c 0 || true
+$NVME_CMD delete-ns ${nvme_dev} -n 0xffffffff || true
+
+reset_nvme_if_aer_unsupported ${nvme_dev}
+sleep 1
+
+PCI_WHITELIST="${bdf}" $rootdir/scripts/setup.sh
+
+$SPDK_BIN_DIR/spdk_tgt -m 0x3 &
+spdk_tgt_pid=$!
+trap 'kill -9 ${spdk_tgt_pid}; clean_up; exit 1' SIGINT SIGTERM EXIT
+
+waitforlisten $spdk_tgt_pid
+
+$rpc_py bdev_nvme_attach_controller -b Nvme0 -t PCIe -a ${bdf}
+$rpc_py bdev_nvme_cuse_register -n Nvme0
+
+sleep 1
+[[ -c /dev/spdk/nvme0 ]]
+
+for dev in /dev/spdk/nvme0n*; do
+ [[ ! -c ${dev} ]]
+done
+
+info_print "create ns: nsze=10000 ncap=10000 flbias=0"
+$NVME_CMD create-ns /dev/spdk/nvme0 -s 10000 -c 10000 -f 0
+
+info_print "attach ns: nsid=1 controller=0"
+$NVME_CMD attach-ns /dev/spdk/nvme0 -n 1 -c 0
+
+reset_nvme_if_aer_unsupported /dev/spdk/nvme0
+sleep 1
+
+[[ -c /dev/spdk/nvme0n1 ]]
+
+info_print "create ns: nsze=10000 ncap=10000 flbias=0"
+$NVME_CMD create-ns /dev/spdk/nvme0 -s 10000 -c 10000 -f 0
+
+info_print "attach ns: nsid=2 controller=0"
+$NVME_CMD attach-ns /dev/spdk/nvme0 -n 2 -c 0
+
+reset_nvme_if_aer_unsupported /dev/spdk/nvme0
+sleep 1
+
+[[ -c /dev/spdk/nvme0n2 ]]
+
+info_print "detach ns: nsid=2 controller=0"
+$NVME_CMD detach-ns /dev/spdk/nvme0 -n 2 -c 0 || true
+
+info_print "delete ns: nsid=2"
+$NVME_CMD delete-ns /dev/spdk/nvme0 -n 2 || true
+
+reset_nvme_if_aer_unsupported /dev/spdk/nvme0
+sleep 1
+
+[[ ! -c /dev/spdk/nvme0n2 ]]
+
+info_print "detach ns: nsid=1 controller=0"
+$NVME_CMD detach-ns /dev/spdk/nvme0 -n 1 -c 0 || true
+
+info_print "delete ns: nsid=1"
+$NVME_CMD delete-ns /dev/spdk/nvme0 -n 1 || true
+
+reset_nvme_if_aer_unsupported /dev/spdk/nvme0
+sleep 1
+
+# Here we should not have any cuse devices
+for dev in /dev/spdk/nvme0n*; do
+ [[ ! -c ${dev} ]]
+done
+
+$rpc_py bdev_nvme_detach_controller Nvme0
+
+sleep 1
+[[ ! -c /dev/spdk/nvme0 ]]
+
+trap - SIGINT SIGTERM EXIT
+killprocess $spdk_tgt_pid
+clean_up
diff --git a/src/spdk/test/nvme/cuse/spdk_nvme_cli_cuse.sh b/src/spdk/test/nvme/cuse/spdk_nvme_cli_cuse.sh
new file mode 100755
index 000000000..cdddd2278
--- /dev/null
+++ b/src/spdk/test/nvme/cuse/spdk_nvme_cli_cuse.sh
@@ -0,0 +1,109 @@
+#!/usr/bin/env bash
+
+testdir=$(readlink -f $(dirname $0))
+rootdir=$(readlink -f $testdir/../../..)
+source $rootdir/scripts/common.sh
+source $rootdir/test/common/autotest_common.sh
+
+rm -Rf $testdir/match_files
+mkdir $testdir/match_files
+
+KERNEL_OUT=$testdir/match_files/kernel.out
+CUSE_OUT=$testdir/match_files/cuse.out
+
+NVME_CMD=/usr/local/src/nvme-cli/nvme
+rpc_py=$rootdir/scripts/rpc.py
+
+bdf=$(get_first_nvme_bdf)
+
+PCI_WHITELIST="${bdf}" $rootdir/scripts/setup.sh reset
+sleep 1
+nvme_name=$(get_nvme_ctrlr_from_bdf ${bdf})
+if [[ -z "$nvme_name" ]]; then
+ echo "setup.sh failed bind kernel driver to ${bdf}"
+ return 1
+fi
+
+ctrlr="/dev/${nvme_name}"
+ns="/dev/${nvme_name}n1"
+
+waitforblk "${nvme_name}n1"
+
+oacs=$(${NVME_CMD} id-ctrl $ctrlr | grep oacs | cut -d: -f2)
+oacs_firmware=$((oacs & 0x4))
+
+set +e
+
+${NVME_CMD} get-ns-id $ns > ${KERNEL_OUT}.1
+${NVME_CMD} id-ns $ns > ${KERNEL_OUT}.2
+${NVME_CMD} list-ns $ns > ${KERNEL_OUT}.3
+
+${NVME_CMD} id-ctrl $ctrlr > ${KERNEL_OUT}.4
+${NVME_CMD} list-ctrl $ctrlr > ${KERNEL_OUT}.5
+if [ "$oacs_firmware" -ne "0" ]; then
+ ${NVME_CMD} fw-log $ctrlr > ${KERNEL_OUT}.6
+fi
+${NVME_CMD} smart-log $ctrlr
+${NVME_CMD} error-log $ctrlr > ${KERNEL_OUT}.7
+${NVME_CMD} get-feature $ctrlr -f 1 -s 1 -l 100 > ${KERNEL_OUT}.8
+${NVME_CMD} get-log $ctrlr -i 1 -l 100 > ${KERNEL_OUT}.9
+${NVME_CMD} reset $ctrlr > ${KERNEL_OUT}.10
+
+set -e
+
+$rootdir/scripts/setup.sh
+
+$SPDK_BIN_DIR/spdk_tgt -m 0x3 &
+spdk_tgt_pid=$!
+trap 'kill -9 ${spdk_tgt_pid}; exit 1' SIGINT SIGTERM EXIT
+
+waitforlisten $spdk_tgt_pid
+
+$rpc_py bdev_nvme_attach_controller -b Nvme0 -t PCIe -a ${bdf}
+$rpc_py bdev_nvme_cuse_register -n Nvme0
+
+sleep 5
+
+if [ ! -c /dev/spdk/nvme0 ]; then
+ return 1
+fi
+
+$rpc_py bdev_get_bdevs
+$rpc_py bdev_nvme_get_controllers
+
+set +e
+
+ns="/dev/spdk/nvme0n1"
+${NVME_CMD} get-ns-id $ns > ${CUSE_OUT}.1
+${NVME_CMD} id-ns $ns > ${CUSE_OUT}.2
+${NVME_CMD} list-ns $ns > ${CUSE_OUT}.3
+
+ctrlr="/dev/spdk/nvme0"
+${NVME_CMD} id-ctrl $ctrlr > ${CUSE_OUT}.4
+${NVME_CMD} list-ctrl $ctrlr > ${CUSE_OUT}.5
+if [ "$oacs_firmware" -ne "0" ]; then
+ ${NVME_CMD} fw-log $ctrlr > ${CUSE_OUT}.6
+fi
+${NVME_CMD} smart-log $ctrlr
+${NVME_CMD} error-log $ctrlr > ${CUSE_OUT}.7
+${NVME_CMD} get-feature $ctrlr -f 1 -s 1 -l 100 > ${CUSE_OUT}.8
+${NVME_CMD} get-log $ctrlr -i 1 -l 100 > ${CUSE_OUT}.9
+${NVME_CMD} reset $ctrlr > ${CUSE_OUT}.10
+
+set -e
+
+for i in {1..10}; do
+ if [ -f "${KERNEL_OUT}.${i}" ] && [ -f "${CUSE_OUT}.${i}" ]; then
+ sed -i "s/${nvme_name}/nvme0/g" ${KERNEL_OUT}.${i}
+ diff --suppress-common-lines ${KERNEL_OUT}.${i} ${CUSE_OUT}.${i}
+ fi
+done
+
+rm -Rf $testdir/match_files
+
+if [ ! -c "$ctrlr" ]; then
+ return 1
+fi
+
+trap - SIGINT SIGTERM EXIT
+killprocess $spdk_tgt_pid
diff --git a/src/spdk/test/nvme/cuse/spdk_smartctl_cuse.sh b/src/spdk/test/nvme/cuse/spdk_smartctl_cuse.sh
new file mode 100755
index 000000000..a92ca1199
--- /dev/null
+++ b/src/spdk/test/nvme/cuse/spdk_smartctl_cuse.sh
@@ -0,0 +1,79 @@
+#!/usr/bin/env bash
+
+testdir=$(readlink -f $(dirname $0))
+rootdir=$(readlink -f $testdir/../../..)
+source $rootdir/scripts/common.sh
+source $rootdir/test/common/autotest_common.sh
+
+SMARTCTL_CMD='smartctl -d nvme'
+rpc_py=$rootdir/scripts/rpc.py
+
+bdf=$(get_first_nvme_bdf)
+
+PCI_WHITELIST="${bdf}" $rootdir/scripts/setup.sh reset
+sleep 1
+nvme_name=$(get_nvme_ctrlr_from_bdf ${bdf})
+if [[ -z "$nvme_name" ]]; then
+ echo "setup.sh failed bind kernel driver to ${bdf}"
+ exit 1
+fi
+
+KERNEL_SMART_JSON=$(${SMARTCTL_CMD} --json=g -a /dev/${nvme_name} | grep -v "/dev/${nvme_name}" | sort || true)
+
+${SMARTCTL_CMD} -i /dev/${nvme_name}n1
+
+# logs are not provided by json output
+KERNEL_SMART_ERRLOG=$(${SMARTCTL_CMD} -l error /dev/${nvme_name})
+
+$rootdir/scripts/setup.sh
+
+$SPDK_BIN_DIR/spdk_tgt -m 0x3 &
+spdk_tgt_pid=$!
+trap 'kill -9 ${spdk_tgt_pid}; exit 1' SIGINT SIGTERM EXIT
+
+waitforlisten $spdk_tgt_pid
+
+$rpc_py bdev_nvme_attach_controller -b Nvme0 -t PCIe -a ${bdf}
+$rpc_py bdev_nvme_cuse_register -n Nvme0
+
+sleep 5
+
+if [ ! -c /dev/spdk/nvme0 ]; then
+ exit 1
+fi
+
+CUSE_SMART_JSON=$(${SMARTCTL_CMD} --json=g -a /dev/spdk/nvme0 | grep -v "/dev/spdk/nvme0" | sort || true)
+
+DIFF_SMART_JSON=$(diff --changed-group-format='%<' --unchanged-group-format='' <(echo "$KERNEL_SMART_JSON") <(echo "$CUSE_SMART_JSON") || true)
+
+# Mask values can change
+ERR_SMART_JSON=$(grep -v "json\.nvme_smart_health_information_log\.\|json\.local_time\.\|json\.temperature\.\|json\.power_on_time\.hours" <<< $DIFF_SMART_JSON || true)
+
+if [ -n "$ERR_SMART_JSON" ]; then
+ echo "Wrong values for: $ERR_SMART_JSON"
+ exit 1
+fi
+
+CUSE_SMART_ERRLOG=$(${SMARTCTL_CMD} -l error /dev/spdk/nvme0)
+if [ "$CUSE_SMART_ERRLOG" != "$KERNEL_SMART_ERRLOG" ]; then
+ echo "Wrong values in NVMe Error log"
+ exit 1
+fi
+
+# Data integity was checked before, now make sure other commads didn't fail
+${SMARTCTL_CMD} -i /dev/spdk/nvme0n1
+${SMARTCTL_CMD} -c /dev/spdk/nvme0
+${SMARTCTL_CMD} -A /dev/spdk/nvme0
+
+# Health test can fail
+${SMARTCTL_CMD} -x /dev/spdk/nvme0 || true
+${SMARTCTL_CMD} -H /dev/spdk/nvme0 || true
+
+$rpc_py bdev_nvme_detach_controller Nvme0
+sleep 1
+if [ -c /dev/spdk/nvme1 ]; then
+ exit 1
+fi
+
+trap - SIGINT SIGTERM EXIT
+killprocess $spdk_tgt_pid