Many open source projects have moved to using SPDX identifiers to specify license information, reducing the amount of boilerplate code in every source file. This patch replaces the bulk of SPDK .c, .cpp and Makefiles with the BSD-3-Clause identifier. Almost all of these files share the exact same license text, and this patch only modifies the files that contain the most common license text. There can be slight variations because the third clause contains company names - most say "Intel Corporation", but there are instances for Nvidia, Samsung, Eideticom and even "the copyright holder". Used a bash script to automate replacement of the license text with SPDX identifier which is checked into scripts/spdx.sh. Signed-off-by: Jim Harris <james.r.harris@intel.com> Change-Id: Iaa88ab5e92ea471691dc298cfe41ebfb5d169780 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/12904 Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com> Community-CI: Mellanox Build Bot Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Aleksey Marchuk <alexeymar@nvidia.com> Reviewed-by: Changpeng Liu <changpeng.liu@intel.com> Reviewed-by: Dong Yi <dongx.yi@intel.com> Reviewed-by: Konrad Sztyber <konrad.sztyber@intel.com> Reviewed-by: Paul Luse <paul.e.luse@intel.com> Reviewed-by: <qun.wan@intel.com>
204 lines
4.9 KiB
C
204 lines
4.9 KiB
C
/* SPDX-License-Identifier: BSD-3-Clause
|
|
* Copyright (c) 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;
|
|
}
|