Spdk/test/nvme/fused_ordering/fused_ordering.c
paul luse a6dbe3721e update Intel copyright notices
per Intel policy to include file commit date using git cmd
below.  The policy does not apply to non-Intel (C) notices.

git log --follow -C90% --format=%ad --date default <file> | tail -1

and then pull just the 4 digit year from the result.

Intel copyrights were not added to files where Intel either had
no contribution ot the contribution lacked substance (ie license
header updates, formatting changes, etc).  Contribution date used
"--follow -C95%" to get the most accurate date.

Note that several files in this patch didn't end the license/(c)
block with a blank comment line so these were added as the vast
majority of files do have this last blank line.  Simply there for
consistency.

Signed-off-by: paul luse <paul.e.luse@intel.com>
Change-Id: Id5b7ce4f658fe87132f14139ead58d6e285c04d4
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/15192
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Community-CI: Mellanox Build Bot
2022-11-10 08:28:53 +00:00

205 lines
4.9 KiB
C

/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (C) 2022 Intel Corporation.
* All rights reserved.
*/
#include "spdk/stdinc.h"
#include "spdk/nvme.h"
#include "spdk/env.h"
#include "spdk/string.h"
#include "spdk/log.h"
static struct spdk_nvme_ctrlr *g_ctrlr;
static struct spdk_nvme_ns *g_ns;
static struct spdk_nvme_qpair *g_qpair;
static struct spdk_nvme_transport_id g_trid = {};
static uint32_t g_outstanding;
static void
io_complete(void *arg, const struct spdk_nvme_cpl *cpl)
{
if (spdk_nvme_cpl_is_error(cpl)) {
spdk_nvme_print_completion(spdk_nvme_qpair_get_id(g_qpair),
(struct spdk_nvme_cpl *)cpl);
exit(1);
}
g_outstanding--;
}
#define WRITE_BLOCKS 128
#define FUSED_BLOCKS 1
static void
fused_ordering(uint32_t poll_count)
{
void *cw_buf, *large_buf;
int rc;
int i;
g_qpair = spdk_nvme_ctrlr_alloc_io_qpair(g_ctrlr, NULL, 0);
if (g_qpair == NULL) {
printf("ERROR: spdk_nvme_ctrlr_alloc_io_qpair() failed\n");
exit(1);
}
cw_buf = spdk_zmalloc(FUSED_BLOCKS * 4096, 0x1000, NULL, SPDK_ENV_SOCKET_ID_ANY, SPDK_MALLOC_DMA);
if (cw_buf == NULL) {
printf("ERROR: buffer allocation failed\n");
return;
}
large_buf = spdk_zmalloc(WRITE_BLOCKS * 4096, 0x1000, NULL, SPDK_ENV_SOCKET_ID_ANY,
SPDK_MALLOC_DMA);
if (large_buf == NULL) {
printf("ERROR: buffer allocation failed\n");
return;
}
/* Issue a bunch of relatively large writes - big enough that the data will not fit
* in-capsule - followed by the compare command. Then poll the completion queue a number of
* times matching the poll_count variable. This adds a variable amount of delay between
* the compare and the subsequent fused write submission.
*
* GitHub issue #2428 showed a problem where once the non-in-capsule data had been fetched from
* the host, that request could get sent to the target layer between the two fused commands. This
* variable delay would eventually induce this condition before the fix.
*/
for (i = 0; i < 8; i++) {
rc = spdk_nvme_ns_cmd_write(g_ns, g_qpair, large_buf, 0, WRITE_BLOCKS, io_complete, NULL, 0);
if (rc != 0) {
fprintf(stderr, "starting write I/O failed\n");
exit(1);
}
g_outstanding++;
}
rc = spdk_nvme_ns_cmd_compare(g_ns, g_qpair, cw_buf, 0, FUSED_BLOCKS, io_complete, NULL,
SPDK_NVME_IO_FLAGS_FUSE_FIRST);
if (rc != 0) {
fprintf(stderr, "starting compare I/O failed\n");
exit(1);
}
g_outstanding++;
while (poll_count--) {
spdk_nvme_qpair_process_completions(g_qpair, 0);
}
rc = spdk_nvme_ns_cmd_write(g_ns, g_qpair, cw_buf, 0, FUSED_BLOCKS, io_complete, NULL,
SPDK_NVME_IO_FLAGS_FUSE_SECOND);
if (rc != 0) {
fprintf(stderr, "starting write I/O failed\n");
exit(1);
}
g_outstanding++;
while (g_outstanding) {
spdk_nvme_qpair_process_completions(g_qpair, 0);
}
spdk_nvme_ctrlr_free_io_qpair(g_qpair);
spdk_free(cw_buf);
spdk_free(large_buf);
}
static void
usage(const char *program_name)
{
printf("%s [options]", program_name);
printf("\t\n");
printf("options:\n");
printf("\t[-r remote NVMe over Fabrics target address]\n");
#ifdef DEBUG
printf("\t[-L enable debug logging]\n");
#else
printf("\t[-L enable debug logging (flag disabled, must reconfigure with --enable-debug)]\n");
#endif
}
static int
parse_args(int argc, char **argv, struct spdk_env_opts *env_opts)
{
int op, rc;
while ((op = getopt(argc, argv, "r:L:")) != -1) {
switch (op) {
case 'r':
if (spdk_nvme_transport_id_parse(&g_trid, optarg) != 0) {
fprintf(stderr, "Error parsing transport address\n");
return 1;
}
break;
case 'L':
rc = spdk_log_set_flag(optarg);
if (rc < 0) {
fprintf(stderr, "unknown flag\n");
usage(argv[0]);
exit(EXIT_FAILURE);
}
#ifdef DEBUG
spdk_log_set_print_level(SPDK_LOG_DEBUG);
#endif
break;
default:
usage(argv[0]);
return 1;
}
}
return 0;
}
int
main(int argc, char **argv)
{
int rc, i;
struct spdk_env_opts opts;
struct spdk_nvme_ctrlr_opts ctrlr_opts;
int nsid;
spdk_env_opts_init(&opts);
spdk_log_set_print_level(SPDK_LOG_NOTICE);
rc = parse_args(argc, argv, &opts);
if (rc != 0) {
return rc;
}
opts.name = "fused_ordering";
if (spdk_env_init(&opts) < 0) {
fprintf(stderr, "Unable to initialize SPDK env\n");
return 1;
}
spdk_nvme_ctrlr_get_default_ctrlr_opts(&ctrlr_opts, sizeof(ctrlr_opts));
ctrlr_opts.keep_alive_timeout_ms = 60 * 1000;
g_ctrlr = spdk_nvme_connect(&g_trid, &ctrlr_opts, sizeof(ctrlr_opts));
if (g_ctrlr == NULL) {
fprintf(stderr, "spdk_nvme_connect() failed\n");
rc = 1;
goto exit;
}
printf("Attached to %s\n", g_trid.subnqn);
nsid = spdk_nvme_ctrlr_get_first_active_ns(g_ctrlr);
if (nsid == 0) {
perror("No active namespaces");
exit(1);
}
g_ns = spdk_nvme_ctrlr_get_ns(g_ctrlr, nsid);
printf(" Namespace ID: %d size: %juGB\n", spdk_nvme_ns_get_id(g_ns),
spdk_nvme_ns_get_size(g_ns) / 1000000000);
for (i = 0; i < 1024; i++) {
printf("fused_ordering(%d)\n", i);
fused_ordering(i);
}
exit:
spdk_nvme_detach(g_ctrlr);
spdk_env_fini();
return rc;
}