diff --git a/examples/nvme/fio_plugin/README.md b/examples/nvme/fio_plugin/README.md index 9184f1319..445573ae2 100644 --- a/examples/nvme/fio_plugin/README.md +++ b/examples/nvme/fio_plugin/README.md @@ -139,6 +139,17 @@ then you can reset all zones before fio start running its jobs by using the engi --initial_zone_reset=1 +## Zone Append + +When running FIO against a Zoned Namespace you need to specify --iodepth=1 to avoid +"Zone Invalid Write: The write to a zone was not at the write pointer." I/O errors. +However, if your controller supports Zone Append, you can use the engine option: + + --zone_append=1 + +To send zone append commands instead of write commands to the controller. +When using zone append, you will be able to specify a --iodepth greater than 1. + ## Shared Memory Increase If your device has a lot of zones, fio can give you errors such as: diff --git a/examples/nvme/fio_plugin/fio_plugin.c b/examples/nvme/fio_plugin/fio_plugin.c index 03a47d3fb..0807288a5 100644 --- a/examples/nvme/fio_plugin/fio_plugin.c +++ b/examples/nvme/fio_plugin/fio_plugin.c @@ -93,6 +93,7 @@ struct spdk_fio_options { char *digest_enable; int enable_vmd; int initial_zone_reset; + int zone_append; }; struct spdk_fio_request { @@ -130,6 +131,7 @@ struct spdk_fio_qpair { struct spdk_nvme_qpair *qpair; struct spdk_nvme_ns *ns; uint32_t io_flags; + bool zone_append_enabled; bool nvme_pi_enabled; /* True for DIF and false for DIX, and this is valid only if nvme_pi_enabled is true. */ bool extended_lba; @@ -408,6 +410,18 @@ attach_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid, return; } + if (fio_options->zone_append) { + if (spdk_nvme_ns_get_csi(ns) == SPDK_NVME_CSI_ZNS && + spdk_nvme_ctrlr_get_flags(ctrlr) & SPDK_NVME_CTRLR_ZONE_APPEND_SUPPORTED) { + fprintf(stdout, "Using zone append instead of write\n"); + fio_qpair->zone_append_enabled = true; + } else { + SPDK_ERRLOG("zone_append=1 requested, but namespace lacks support\n"); + g_error = true; + return; + } + } + f->real_file_size = spdk_nvme_ns_get_size(fio_qpair->ns); if (f->real_file_size <= 0) { g_error = true; @@ -688,6 +702,12 @@ static void spdk_fio_io_u_free(struct thread_data *td, struct io_u *io_u) } } +static inline uint64_t +fio_offset_to_zslba(unsigned long long offset, struct spdk_nvme_ns *ns) +{ + return (offset / spdk_nvme_zns_ns_get_zone_size(ns)) * spdk_nvme_zns_ns_get_zone_size_sectors(ns); +} + static int fio_extended_lba_setup_pi(struct spdk_fio_qpair *fio_qpair, struct io_u *io_u) { @@ -982,15 +1002,31 @@ spdk_fio_queue(struct thread_data *td, struct io_u *io_u) break; case DDIR_WRITE: if (!g_spdk_enable_sgl) { - rc = spdk_nvme_ns_cmd_write_with_md(ns, fio_qpair->qpair, io_u->buf, md_buf, lba, - lba_count, - spdk_fio_completion_cb, fio_req, - fio_qpair->io_flags, dif_ctx->apptag_mask, dif_ctx->app_tag); + if (!fio_qpair->zone_append_enabled) { + rc = spdk_nvme_ns_cmd_write_with_md(ns, fio_qpair->qpair, io_u->buf, md_buf, lba, + lba_count, + spdk_fio_completion_cb, fio_req, + fio_qpair->io_flags, dif_ctx->apptag_mask, dif_ctx->app_tag); + } else { + uint64_t zslba = fio_offset_to_zslba(io_u->offset, fio_qpair->ns); + rc = spdk_nvme_zns_zone_append_with_md(ns, fio_qpair->qpair, io_u->buf, md_buf, zslba, + lba_count, + spdk_fio_completion_cb, fio_req, + fio_qpair->io_flags, dif_ctx->apptag_mask, dif_ctx->app_tag); + } } else { - rc = spdk_nvme_ns_cmd_writev_with_md(ns, fio_qpair->qpair, lba, - lba_count, spdk_fio_completion_cb, fio_req, fio_qpair->io_flags, - spdk_nvme_io_reset_sgl, spdk_nvme_io_next_sge, md_buf, - dif_ctx->apptag_mask, dif_ctx->app_tag); + if (!fio_qpair->zone_append_enabled) { + rc = spdk_nvme_ns_cmd_writev_with_md(ns, fio_qpair->qpair, lba, + lba_count, spdk_fio_completion_cb, fio_req, fio_qpair->io_flags, + spdk_nvme_io_reset_sgl, spdk_nvme_io_next_sge, md_buf, + dif_ctx->apptag_mask, dif_ctx->app_tag); + } else { + uint64_t zslba = fio_offset_to_zslba(io_u->offset, fio_qpair->ns); + rc = spdk_nvme_zns_zone_appendv_with_md(ns, fio_qpair->qpair, zslba, + lba_count, spdk_fio_completion_cb, fio_req, fio_qpair->io_flags, + spdk_nvme_io_reset_sgl, spdk_nvme_io_next_sge, md_buf, + dif_ctx->apptag_mask, dif_ctx->app_tag); + } } break; default: @@ -1545,6 +1581,16 @@ static struct fio_option options[] = { .category = FIO_OPT_C_ENGINE, .group = FIO_OPT_G_INVALID, }, + { + .name = "zone_append", + .lname = "Use zone append instead of write", + .type = FIO_OPT_INT, + .off1 = offsetof(struct spdk_fio_options, zone_append), + .def = "0", + .help = "Use zone append instead of write (zone_append=1 or zone_append=0)", + .category = FIO_OPT_C_ENGINE, + .group = FIO_OPT_G_INVALID, + }, { .name = NULL, },