test/dma: Add option to check specific operation

Add a CLI param "-x" to specify which memory
domain operation must be executed during test

Signed-off-by: Alexey Marchuk <alexeymar@mellanox.com>
Change-Id: I0dbee8d5d186da1e177e24beadc4e71909e4057f
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/12344
Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com>
Community-CI: Mellanox Build Bot
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Shuhei Matsumoto <smatsumoto@nvidia.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
Alexey Marchuk 2022-04-22 12:17:03 +03:00 committed by Tomasz Zawadzki
parent 248ccd8607
commit 381aa0e105
2 changed files with 92 additions and 11 deletions

View File

@ -76,6 +76,7 @@ struct dma_test_task {
struct spdk_thread *thread;
const char *bdev_name;
uint64_t num_translations;
uint64_t num_pull_push;
uint32_t lcore;
TAILQ_ENTRY(dma_test_task) link;
@ -86,6 +87,11 @@ struct dma_test_data_cpl_ctx {
void *data_cpl_arg;
};
enum dma_test_domain_ops {
DMA_TEST_DOMAIN_OP_TRANSLATE = 1u << 0,
DMA_TEST_DOMAIN_OP_PULL_PUSH = 1u << 1,
};
TAILQ_HEAD(, dma_test_task) g_tasks = TAILQ_HEAD_INITIALIZER(g_tasks);
/* User's input */
@ -96,6 +102,7 @@ static uint32_t g_queue_depth;
static uint32_t g_io_size;
static uint32_t g_run_time_sec;
static uint32_t g_run_count;
static uint32_t g_test_ops;
static bool g_is_random;
static bool g_force_memory_domains_support;
@ -303,6 +310,7 @@ dma_test_copy_memory(struct dma_test_req *req, struct iovec *dst_iov, uint32_t d
cpl_ctx->data_cpl_arg = cpl_cb_arg;
spdk_iovcpy(src_iov, src_iovcnt, dst_iov, dst_iovcnt);
req->task->num_pull_push++;
spdk_thread_send_msg(req->task->thread, dma_test_data_cpl, cpl_ctx);
return 0;
@ -661,16 +669,48 @@ static int
verify_tasks(void)
{
struct dma_test_task *task;
uint64_t total_requests = 0;
uint64_t num_translations = 0;
uint64_t num_pull_push = 0;
int rc = 0;
if (!g_test_ops) {
/* No specific ops were requested, nothing to check */
return rc;
}
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;
total_requests += task->stats.io_completed;
num_translations += task->num_translations;
num_pull_push += task->num_pull_push;
}
if (g_test_ops & DMA_TEST_DOMAIN_OP_TRANSLATE) {
if (num_translations == 0) {
fprintf(stderr, "Requested \"translate\" operation, but it was not executed\n");
rc = -EINVAL;
}
}
if (g_test_ops & DMA_TEST_DOMAIN_OP_PULL_PUSH) {
if (num_pull_push == 0) {
fprintf(stderr, "Requested \"pull_push\" operation, but it was not executed\n");
rc = -EINVAL;
}
}
return 0;
/* bdev request can be split, so the total number of pull_push +translate operations
* can be bigger than total_number of requests */
if (num_translations + num_pull_push < total_requests) {
fprintf(stderr,
"Operations number mismatch: translate %"PRIu64", pull_push %"PRIu64", expected total %"PRIu64"\n",
num_translations, num_pull_push, total_requests);
rc = -EINVAL;
} else {
fprintf(stdout, "Total operations: %"PRIu64", translate %"PRIu64" pull_push %"PRIu64"\n",
total_requests, num_translations, num_pull_push);
}
return rc;
}
static void
@ -746,12 +786,49 @@ static void
print_usage(void)
{
printf(" -b <bdev> bdev name for test\n");
printf(" -f force memory domains support - abort test if bdev doesn't report memory domains\n");
printf(" -q <val> io depth\n");
printf(" -o <val> io size in bytes\n");
printf(" -t <val> run time in seconds\n");
printf(" -x <op,op> Comma separated memory domain operations expected in the test. Values are \"translate\" and \"pull_push\"\n");
printf(" -w <str> 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
parse_expected_ops(const char *_str)
{
char *str = strdup(_str);
char *tok;
int rc = 0;
if (!str) {
fprintf(stderr, "Failed to dup args\n");
return -ENOMEM;
}
tok = strtok(str, ",");
while (tok) {
if (strcmp(tok, "translate") == 0) {
g_test_ops |= DMA_TEST_DOMAIN_OP_TRANSLATE;
} else if (strcmp(tok, "pull_push") == 0) {
g_test_ops |= DMA_TEST_DOMAIN_OP_PULL_PUSH;
} else {
fprintf(stderr, "Unknown value %s\n", tok);
rc = -EINVAL;
break;
}
tok = strtok(NULL, ",");
}
free(str);
if (g_test_ops == 0 || rc) {
fprintf(stderr, "-e \"%s\" specified but nothing was parsed\n", _str);
return -EINVAL;
}
return rc;
}
static int
@ -794,7 +871,11 @@ parse_arg(int ch, char *arg)
case 'f':
g_force_memory_domains_support = true;
break;
case 'x':
if (parse_expected_ops(arg)) {
return 1;
}
break;
default:
fprintf(stderr, "Unknown option %c\n", ch);
return 1;
@ -860,7 +941,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:fq:o:t:w:M:", NULL, parse_arg, print_usage);
rc = spdk_app_parse_args(argc, argv, &opts, "b:fq:o:t:x:w:M:", NULL, parse_arg, print_usage);
if (rc != SPDK_APP_PARSE_ARGS_SUCCESS) {
exit(rc);
}
@ -871,7 +952,7 @@ main(int argc, char **argv)
}
rc = spdk_app_start(&opts, dma_test_start, NULL);
if (rc == 0 && g_force_memory_domains_support) {
if (rc == 0) {
rc = verify_tasks();
}
destroy_tasks();

View File

@ -69,10 +69,10 @@ $rpc_py nvmf_subsystem_add_listener nqn.2016-06.io.spdk:cnode$subsystem -t $TEST
# 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
"$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 -x translate -r /var/tmp/dma.sock
# test data pull/push with split against local malloc
"$rootdir/test/dma/test_dma/test_dma" -q 16 -o 4096 -w randrw -M 70 -t 5 -m 0xc --json <(gen_malloc_json) -b "Malloc0" -r /var/tmp/dma.sock
"$rootdir/test/dma/test_dma/test_dma" -q 16 -o 4096 -w randrw -M 70 -t 5 -m 0xc --json <(gen_malloc_json) -b "Malloc0" -x pull_push -r /var/tmp/dma.sock
trap - SIGINT SIGTERM EXIT