diff --git a/test/dma/test_dma/test_dma.c b/test/dma/test_dma/test_dma.c index 243ec6b7d..6119ac6e5 100644 --- a/test/dma/test_dma/test_dma.c +++ b/test/dma/test_dma/test_dma.c @@ -75,6 +75,7 @@ struct dma_test_task { struct dma_test_req *reqs; struct spdk_thread *thread; const char *bdev_name; + uint64_t num_translations; uint32_t lcore; TAILQ_ENTRY(dma_test_task) link; @@ -91,6 +92,7 @@ static uint32_t g_io_size; static uint32_t g_run_time_sec; static uint32_t g_run_count; static bool g_is_random; +static bool g_force_memory_domains_support; static struct spdk_thread *g_main_thread; static struct spdk_poller *g_runtime_poller; @@ -297,6 +299,8 @@ dma_test_translate_memory_cb(struct spdk_memory_domain *src_domain, void *src_do result->rdma.rkey = req->mr->rkey; result->dst_domain = dst_domain; + req->task->num_translations++; + return 0; } @@ -599,6 +603,22 @@ destroy_tasks(void) } } +static int +verify_tasks(void) +{ + struct dma_test_task *task; + + TAILQ_FOREACH(task, &g_tasks, link) { + if (task->num_translations < task->stats.io_completed) { + fprintf(stderr, "Unexpected number of translations %"PRIu64", must be at least %"PRIu64"\n", + task->num_translations, task->stats.io_completed); + return -1; + } + } + + return 0; +} + static void dma_test_start(void *arg) { @@ -615,7 +635,10 @@ dma_test_start(void *arg) return; } bdev = spdk_bdev_desc_get_bdev(desc); - if (!dma_test_check_bdev_supports_rdma_memory_domain(bdev)) { + /* This function checks if bdev supports memory domains. Test is not failed if there are + * no memory domains since bdev layer can pull/push data */ + if (!dma_test_check_bdev_supports_rdma_memory_domain(bdev) && g_force_memory_domains_support) { + fprintf(stderr, "Test aborted due to \"-f\" (force memory domains support) option\n"); spdk_bdev_close(desc); spdk_app_stop(-ENODEV); return; @@ -672,6 +695,7 @@ print_usage(void) printf(" -t run time in seconds\n"); printf(" -w io pattern (read, write, randread, randwrite, randrw)\n"); printf(" -M <0-100> rw percentage (100 for reads, 0 for writes)\n"); + printf(" -f force memory domains support - abort test if bdev doesn't report memory domains\n"); } static int @@ -711,6 +735,9 @@ parse_arg(int ch, char *arg) case 'b': g_bdev_name = arg; break; + case 'f': + g_force_memory_domains_support = true; + break; default: fprintf(stderr, "Unknown option %c\n", ch); @@ -777,7 +804,7 @@ main(int argc, char **argv) opts.name = "test_dma"; opts.shutdown_cb = dma_test_shutdown_cb; - rc = spdk_app_parse_args(argc, argv, &opts, "b:q:o:t:w:M:", NULL, parse_arg, print_usage); + rc = spdk_app_parse_args(argc, argv, &opts, "b:fq:o:t:w:M:", NULL, parse_arg, print_usage); if (rc != SPDK_APP_PARSE_ARGS_SUCCESS) { exit(rc); } @@ -788,6 +815,9 @@ main(int argc, char **argv) } rc = spdk_app_start(&opts, dma_test_start, NULL); + if (rc == 0 && g_force_memory_domains_support) { + rc = verify_tasks(); + } destroy_tasks(); spdk_app_fini(); diff --git a/test/nvmf/host/dma.sh b/test/nvmf/host/dma.sh index 55ff5f5eb..7597a66e3 100755 --- a/test/nvmf/host/dma.sh +++ b/test/nvmf/host/dma.sh @@ -23,11 +23,9 @@ $rpc_py nvmf_create_subsystem nqn.2016-06.io.spdk:cnode$subsystem -a -s SPDK0000 $rpc_py nvmf_subsystem_add_ns nqn.2016-06.io.spdk:cnode$subsystem Malloc0 $rpc_py nvmf_subsystem_add_listener nqn.2016-06.io.spdk:cnode$subsystem -t $TEST_TRANSPORT -a $NVMF_FIRST_TARGET_IP -s $NVMF_PORT -"$rootdir/test/dma/test_dma/test_dma" -q 16 -o 4096 -w randrw -M 70 -t 5 -m 0xc --json <(gen_nvmf_target_json $subsystem) -b "Nvme${subsystem}n1" -test_dmapid=$! - -wait $test_dmapid -sync +# test memory translation +# test_dma doesn't use RPC, but we change the sock path since nvmf target is already using the default RPC sock +"$rootdir/test/dma/test_dma/test_dma" -q 16 -o 4096 -w randrw -M 70 -t 5 -m 0xc --json <(gen_nvmf_target_json $subsystem) -b "Nvme${subsystem}n1" -f -r /var/tmp/dma.sock trap - SIGINT SIGTERM EXIT