Commit 99f838a3 authored by Daniel Verkamp's avatar Daniel Verkamp
Browse files

nvme: add support for NS Optimal IO Boundary



An optional field was added in NVMe 1.3 to indicate the optimal I/O
boundary that should not be crossed for best performance.  This is
equivalent to the existing Intel-specific stripe size quirk.

Add support for the new NOIOB field and move the current quirk-based
code so it is updated in nvme_ns_identify_update().

Change-Id: Ifc4974f51dcd59e7f24565d8d5159b036458c6e5
Signed-off-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
Reviewed-on: https://review.gerrithub.io/373132


Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
parent 6552b6da
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -20,6 +20,12 @@ currently only supported by NVMe block devices.

The AIO bdev now allows the user to override the auto-detected block size.

### NVMe driver

The NVMe driver now recognizes the NVMe 1.3 Namespace Optimal I/O Boundary field.
NVMe 1.3 devices may report an optimal I/O boundary, which the driver will take
into account when splitting I/O requests.

## v17.07: Build system improvements, userspace vhost-blk target, and GPT bdev

### Build System
+9 −0
Original line number Diff line number Diff line
@@ -919,6 +919,15 @@ bool spdk_nvme_ns_supports_extended_lba(struct spdk_nvme_ns *ns);
enum spdk_nvme_dealloc_logical_block_read_value spdk_nvme_ns_get_dealloc_logical_block_read_value(
	struct spdk_nvme_ns *ns);

/**
 * \brief Get the optimal I/O boundary, in blocks, for the given namespace.
 *
 * \return Optimal granularity of I/O commands, in blocks, or 0 if no optimal granularity is reported.
 *
 * Read and write commands should not cross the optimal I/O boundary for best performance.
 */
uint32_t spdk_nvme_ns_get_optimal_io_boundary(struct spdk_nvme_ns *ns);

/**
 * \brief Namespace command support flags.
 */
+0 −1
Original line number Diff line number Diff line
@@ -288,7 +288,6 @@ struct spdk_nvme_qpair {

struct spdk_nvme_ns {
	struct spdk_nvme_ctrlr		*ctrlr;
	uint32_t			stripe_size;
	uint32_t			sector_size;

	/*
+20 −8
Original line number Diff line number Diff line
@@ -63,7 +63,6 @@ int nvme_ns_identify_update(struct spdk_nvme_ns *ns)
		/* This can occur if the namespace is not active. Simply zero the
		 * namespace data and continue. */
		memset(nsdata, 0, sizeof(*nsdata));
		ns->stripe_size = 0;
		ns->sector_size = 0;
		ns->extended_lba_size = 0;
		ns->md_size = 0;
@@ -86,7 +85,20 @@ int nvme_ns_identify_update(struct spdk_nvme_ns *ns)
	}

	ns->sectors_per_max_io = spdk_nvme_ns_get_max_io_xfer_size(ns) / ns->extended_lba_size;
	ns->sectors_per_stripe = ns->stripe_size / ns->sector_size;

	if (nsdata->noiob) {
		ns->sectors_per_stripe = nsdata->noiob;
		SPDK_TRACELOG(SPDK_TRACE_NVME, "ns %u optimal IO boundary %" PRIu32 " blocks\n",
			      ns->id, ns->sectors_per_stripe);
	} else if (ns->ctrlr->quirks & NVME_INTEL_QUIRK_STRIPING &&
		   ns->ctrlr->cdata.vs[3] != 0) {
		ns->sectors_per_stripe = (1ULL << ns->ctrlr->cdata.vs[3]) * ns->ctrlr->min_page_size /
					 ns->sector_size;
		SPDK_TRACELOG(SPDK_TRACE_NVME, "ns %u stripe size quirk %" PRIu32 " blocks\n",
			      ns->id, ns->sectors_per_stripe);
	} else {
		ns->sectors_per_stripe = 0;
	}

	if (ns->ctrlr->cdata.oncs.dsm) {
		ns->flags |= SPDK_NVME_NS_DEALLOCATE_SUPPORTED;
@@ -198,6 +210,12 @@ enum spdk_nvme_dealloc_logical_block_read_value spdk_nvme_ns_get_dealloc_logical
	}
}

uint32_t
spdk_nvme_ns_get_optimal_io_boundary(struct spdk_nvme_ns *ns)
{
	return ns->sectors_per_stripe;
}

int nvme_ns_construct(struct spdk_nvme_ns *ns, uint16_t id,
		      struct spdk_nvme_ctrlr *ctrlr)
{
@@ -205,12 +223,6 @@ int nvme_ns_construct(struct spdk_nvme_ns *ns, uint16_t id,

	ns->ctrlr = ctrlr;
	ns->id = id;
	ns->stripe_size = 0;

	if (ctrlr->quirks & NVME_INTEL_QUIRK_STRIPING &&
	    ctrlr->cdata.vs[3] != 0) {
		ns->stripe_size = (1 << ctrlr->cdata.vs[3]) * ctrlr->min_page_size;
	}

	return nvme_ns_identify_update(ns);
}
+2 −1
Original line number Diff line number Diff line
@@ -39,6 +39,8 @@

#include "lib/test_env.c"

SPDK_LOG_REGISTER_TRACE_FLAG("nvme", SPDK_TRACE_NVME)

int
nvme_ctrlr_cmd_identify_namespace(struct spdk_nvme_ctrlr *ctrlr, uint16_t nsid, void *payload,
				  spdk_nvme_cmd_cb cb_fn, void *cb_arg)
@@ -66,7 +68,6 @@ test_nvme_ns_construct(void)

	nvme_ns_construct(&ns, id, &ctrlr);
	CU_ASSERT(ns.id == 1);
	CU_ASSERT(ns.stripe_size == 0);
}

int main(int argc, char **argv)
Loading