nvme: allow user to override controller defaults

Provide a new structure, spdk_nvme_ctrlr_opts, to let the user modify
the default controller initialization options during probe/attach.

Currently, only the number of queue pairs can be modified in this way;
other options will be added later.

Change-Id: Ie27b9429291d93a9353c0d820f0ad467d3b0e7cb
Signed-off-by: Daniel Verkamp <daniel.verkamp@intel.com>
This commit is contained in:
Daniel Verkamp 2016-03-07 10:36:17 -07:00 committed by Benjamin Walker
parent 23f95df80d
commit 4ad99808f2
14 changed files with 85 additions and 32 deletions

View File

@ -771,7 +771,7 @@ parse_args(int argc, char **argv)
}
static bool
probe_cb(void *cb_ctx, struct spdk_pci_device *dev)
probe_cb(void *cb_ctx, struct spdk_pci_device *dev, struct spdk_nvme_ctrlr_opts *opts)
{
if (spdk_pci_device_has_non_uio_driver(dev)) {
fprintf(stderr, "non-uio kernel driver attached to NVMe\n");
@ -788,7 +788,8 @@ probe_cb(void *cb_ctx, struct spdk_pci_device *dev)
}
static void
attach_cb(void *cb_ctx, struct spdk_pci_device *pci_dev, struct spdk_nvme_ctrlr *ctrlr)
attach_cb(void *cb_ctx, struct spdk_pci_device *pci_dev, struct spdk_nvme_ctrlr *ctrlr,
const struct spdk_nvme_ctrlr_opts *opts)
{
print_controller(ctrlr, pci_dev);
spdk_nvme_detach(ctrlr);

View File

@ -96,7 +96,7 @@ cmp_devs(const void *ap, const void *bp)
}
static bool
probe_cb(void *cb_ctx, struct spdk_pci_device *dev)
probe_cb(void *cb_ctx, struct spdk_pci_device *dev, struct spdk_nvme_ctrlr_opts *opts)
{
if (spdk_pci_device_has_non_uio_driver(dev)) {
fprintf(stderr, "non-uio kernel driver attached to NVMe\n");
@ -113,7 +113,8 @@ probe_cb(void *cb_ctx, struct spdk_pci_device *dev)
}
static void
attach_cb(void *cb_ctx, struct spdk_pci_device *pci_dev, struct spdk_nvme_ctrlr *ctrlr)
attach_cb(void *cb_ctx, struct spdk_pci_device *pci_dev, struct spdk_nvme_ctrlr *ctrlr,
const struct spdk_nvme_ctrlr_opts *opts)
{
struct dev *dev;

View File

@ -884,7 +884,7 @@ register_workers(void)
}
static bool
probe_cb(void *cb_ctx, struct spdk_pci_device *dev)
probe_cb(void *cb_ctx, struct spdk_pci_device *dev, struct spdk_nvme_ctrlr_opts *opts)
{
if (spdk_pci_device_has_non_uio_driver(dev)) {
fprintf(stderr, "non-uio kernel driver attached to NVMe\n");
@ -907,7 +907,8 @@ probe_cb(void *cb_ctx, struct spdk_pci_device *dev)
}
static void
attach_cb(void *cb_ctx, struct spdk_pci_device *dev, struct spdk_nvme_ctrlr *ctrlr)
attach_cb(void *cb_ctx, struct spdk_pci_device *dev, struct spdk_nvme_ctrlr *ctrlr,
const struct spdk_nvme_ctrlr_opts *opts)
{
printf("Attached to %04x:%02x:%02x.%02x\n",
spdk_pci_device_get_domain(dev),

View File

@ -382,7 +382,7 @@ reserve_controller(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_qpair *qpair,
}
static bool
probe_cb(void *cb_ctx, struct spdk_pci_device *dev)
probe_cb(void *cb_ctx, struct spdk_pci_device *dev, struct spdk_nvme_ctrlr_opts *opts)
{
if (spdk_pci_device_has_non_uio_driver(dev)) {
fprintf(stderr, "non-uio kernel driver attached to NVMe\n");
@ -399,7 +399,8 @@ probe_cb(void *cb_ctx, struct spdk_pci_device *dev)
}
static void
attach_cb(void *cb_ctx, struct spdk_pci_device *pci_dev, struct spdk_nvme_ctrlr *ctrlr)
attach_cb(void *cb_ctx, struct spdk_pci_device *pci_dev, struct spdk_nvme_ctrlr *ctrlr,
const struct spdk_nvme_ctrlr_opts *opts)
{
struct dev *dev;

View File

@ -56,18 +56,41 @@ extern int32_t spdk_nvme_retry_count;
/** \brief Opaque handle to a controller. Returned by \ref spdk_nvme_probe()'s attach_cb. */
struct spdk_nvme_ctrlr;
/**
* \brief NVMe controller initialization options.
*
* A pointer to this structure will be provided for each probe callback from spdk_nvme_probe() to
* allow the user to request non-default options, and the actual options enabled on the controller
* will be provided during the attach callback.
*/
struct spdk_nvme_ctrlr_opts {
/**
* Number of I/O queues to request (used to set Number of Queues feature)
*/
uint32_t num_io_queues;
};
/**
* Callback for spdk_nvme_probe() enumeration.
*
* \param opts NVMe controller initialization options. This structure will be populated with the
* default values on entry, and the user callback may update any options to request a different
* value. The controller may not support all requested parameters, so the final values will be
* provided during the attach callback.
* \return true to attach to this device.
*/
typedef bool (*spdk_nvme_probe_cb)(void *cb_ctx, struct spdk_pci_device *pci_dev);
typedef bool (*spdk_nvme_probe_cb)(void *cb_ctx, struct spdk_pci_device *pci_dev,
struct spdk_nvme_ctrlr_opts *opts);
/**
* Callback for spdk_nvme_probe() to report a device that has been attached to the userspace NVMe driver.
*
* \param opts NVMe controller initialization options that were actually used. Options may differ
* from the requested options from the probe call depending on what the controller supports.
*/
typedef void (*spdk_nvme_attach_cb)(void *cb_ctx, struct spdk_pci_device *pci_dev,
struct spdk_nvme_ctrlr *ctrlr);
struct spdk_nvme_ctrlr *ctrlr,
const struct spdk_nvme_ctrlr_opts *opts);
/**
* \brief Enumerate the NVMe devices attached to the system and attach the userspace NVMe driver

View File

@ -189,6 +189,7 @@ nvme_enum_cb(void *ctx, struct spdk_pci_device *pci_dev)
{
struct nvme_enum_ctx *enum_ctx = ctx;
struct spdk_nvme_ctrlr *ctrlr;
struct spdk_nvme_ctrlr_opts opts;
/* Verify that this controller is not already attached */
TAILQ_FOREACH(ctrlr, &g_nvme_driver.attached_ctrlrs, tailq) {
@ -200,13 +201,17 @@ nvme_enum_cb(void *ctx, struct spdk_pci_device *pci_dev)
}
}
if (enum_ctx->probe_cb(enum_ctx->cb_ctx, pci_dev)) {
spdk_nvme_ctrlr_opts_set_defaults(&opts);
if (enum_ctx->probe_cb(enum_ctx->cb_ctx, pci_dev, &opts)) {
ctrlr = nvme_attach(pci_dev);
if (ctrlr == NULL) {
nvme_printf(NULL, "nvme_attach() failed\n");
return -1;
}
ctrlr->opts = opts;
TAILQ_INSERT_TAIL(&g_nvme_driver.init_ctrlrs, ctrlr, tailq);
}
@ -268,7 +273,7 @@ spdk_nvme_probe(void *cb_ctx, spdk_nvme_probe_cb probe_cb, spdk_nvme_attach_cb a
* that may take the driver lock, like nvme_detach().
*/
nvme_mutex_unlock(&g_nvme_driver.lock);
attach_cb(cb_ctx, ctrlr->devhandle, ctrlr);
attach_cb(cb_ctx, ctrlr->devhandle, ctrlr, &ctrlr->opts);
nvme_mutex_lock(&g_nvme_driver.lock);
break;

View File

@ -42,6 +42,13 @@
static int nvme_ctrlr_construct_and_submit_aer(struct spdk_nvme_ctrlr *ctrlr,
struct nvme_async_event_request *aer);
void
spdk_nvme_ctrlr_opts_set_defaults(struct spdk_nvme_ctrlr_opts *opts)
{
opts->num_io_queues = DEFAULT_MAX_IO_QUEUES;
}
static int
spdk_nvme_ctrlr_create_qpair(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_qpair *qpair)
{
@ -357,12 +364,12 @@ nvme_ctrlr_construct_io_qpairs(struct spdk_nvme_ctrlr *ctrlr)
ctrlr->max_xfer_size = NVME_MAX_XFER_SIZE;
ctrlr->ioq = calloc(ctrlr->num_io_queues, sizeof(struct spdk_nvme_qpair));
ctrlr->ioq = calloc(ctrlr->opts.num_io_queues, sizeof(struct spdk_nvme_qpair));
if (ctrlr->ioq == NULL)
return -1;
for (i = 0; i < ctrlr->num_io_queues; i++) {
for (i = 0; i < ctrlr->opts.num_io_queues; i++) {
qpair = &ctrlr->ioq[i];
/*
@ -390,7 +397,7 @@ nvme_ctrlr_fail(struct spdk_nvme_ctrlr *ctrlr)
ctrlr->is_failed = true;
nvme_qpair_fail(&ctrlr->adminq);
for (i = 0; i < ctrlr->num_io_queues; i++) {
for (i = 0; i < ctrlr->opts.num_io_queues; i++) {
nvme_qpair_fail(&ctrlr->ioq[i]);
}
}
@ -544,7 +551,7 @@ spdk_nvme_ctrlr_reset(struct spdk_nvme_ctrlr *ctrlr)
/* Disable all queues before disabling the controller hardware. */
nvme_qpair_disable(&ctrlr->adminq);
for (i = 0; i < ctrlr->num_io_queues; i++) {
for (i = 0; i < ctrlr->opts.num_io_queues; i++) {
nvme_qpair_disable(&ctrlr->ioq[i]);
}
@ -616,13 +623,10 @@ nvme_ctrlr_set_num_qpairs(struct spdk_nvme_ctrlr *ctrlr)
struct nvme_completion_poll_status status;
int cq_allocated, sq_allocated;
int rc;
uint32_t max_io_queues;
status.done = false;
max_io_queues = DEFAULT_MAX_IO_QUEUES;
rc = nvme_ctrlr_cmd_set_num_queues(ctrlr, max_io_queues,
rc = nvme_ctrlr_cmd_set_num_queues(ctrlr, ctrlr->opts.num_io_queues,
nvme_completion_poll_cb, &status);
if (rc != 0) {
return rc;
@ -644,7 +648,7 @@ nvme_ctrlr_set_num_qpairs(struct spdk_nvme_ctrlr *ctrlr)
sq_allocated = (status.cpl.cdw0 & 0xFFFF) + 1;
cq_allocated = (status.cpl.cdw0 >> 16) + 1;
ctrlr->num_io_queues = nvme_min(sq_allocated, cq_allocated);
ctrlr->opts.num_io_queues = nvme_min(sq_allocated, cq_allocated);
return 0;
}
@ -1028,7 +1032,7 @@ nvme_ctrlr_destruct(struct spdk_nvme_ctrlr *ctrlr)
nvme_ctrlr_destruct_namespaces(ctrlr);
for (i = 0; i < ctrlr->num_io_queues; i++) {
for (i = 0; i < ctrlr->opts.num_io_queues; i++) {
nvme_qpair_destroy(&ctrlr->ioq[i]);
}

View File

@ -397,8 +397,6 @@ struct spdk_nvme_ctrlr {
/* Opaque handle to associated PCI device. */
struct spdk_pci_device *devhandle;
uint32_t num_io_queues;
/** maximum i/o size in bytes */
uint32_t max_xfer_size;
@ -433,6 +431,8 @@ struct spdk_nvme_ctrlr {
TAILQ_HEAD(, spdk_nvme_qpair) free_io_qpairs;
TAILQ_HEAD(, spdk_nvme_qpair) active_io_qpairs;
struct spdk_nvme_ctrlr_opts opts;
};
struct nvme_driver {
@ -548,4 +548,6 @@ struct nvme_request *nvme_allocate_request_contig(void *buffer, uint32_t payload
void nvme_free_request(struct nvme_request *req);
bool nvme_intel_has_quirk(struct pci_id *id, uint64_t quirk);
void spdk_nvme_ctrlr_opts_set_defaults(struct spdk_nvme_ctrlr_opts *opts);
#endif /* __NVME_INTERNAL_H__ */

View File

@ -188,7 +188,7 @@ static void aer_cb(void *arg, const struct spdk_nvme_cpl *cpl)
static bool
probe_cb(void *cb_ctx, struct spdk_pci_device *dev)
probe_cb(void *cb_ctx, struct spdk_pci_device *dev, struct spdk_nvme_ctrlr_opts *opts)
{
if (spdk_pci_device_has_non_uio_driver(dev)) {
fprintf(stderr, "non-uio kernel driver attached to NVMe\n");
@ -211,7 +211,8 @@ probe_cb(void *cb_ctx, struct spdk_pci_device *dev)
}
static void
attach_cb(void *cb_ctx, struct spdk_pci_device *pci_dev, struct spdk_nvme_ctrlr *ctrlr)
attach_cb(void *cb_ctx, struct spdk_pci_device *pci_dev, struct spdk_nvme_ctrlr *ctrlr,
const struct spdk_nvme_ctrlr_opts *opts)
{
struct dev *dev;

View File

@ -512,7 +512,7 @@ register_workers(void)
static bool
probe_cb(void *cb_ctx, struct spdk_pci_device *dev)
probe_cb(void *cb_ctx, struct spdk_pci_device *dev, struct spdk_nvme_ctrlr_opts *opts)
{
if (spdk_pci_device_has_non_uio_driver(dev)) {
fprintf(stderr, "non-uio kernel driver attached to NVMe\n");
@ -529,7 +529,8 @@ probe_cb(void *cb_ctx, struct spdk_pci_device *dev)
}
static void
attach_cb(void *cb_ctx, struct spdk_pci_device *pci_dev, struct spdk_nvme_ctrlr *ctrlr)
attach_cb(void *cb_ctx, struct spdk_pci_device *pci_dev, struct spdk_nvme_ctrlr *ctrlr,
const struct spdk_nvme_ctrlr_opts *opts)
{
register_ctrlr(ctrlr);
}

View File

@ -402,7 +402,7 @@ writev_readv_tests(struct dev *dev, nvme_build_io_req_fn_t build_io_fn)
}
static bool
probe_cb(void *cb_ctx, struct spdk_pci_device *dev)
probe_cb(void *cb_ctx, struct spdk_pci_device *dev, struct spdk_nvme_ctrlr_opts *opts)
{
if (spdk_pci_device_has_non_uio_driver(dev)) {
fprintf(stderr, "non-uio kernel driver attached to NVMe\n");
@ -425,7 +425,8 @@ probe_cb(void *cb_ctx, struct spdk_pci_device *dev)
}
static void
attach_cb(void *cb_ctx, struct spdk_pci_device *pci_dev, struct spdk_nvme_ctrlr *ctrlr)
attach_cb(void *cb_ctx, struct spdk_pci_device *pci_dev, struct spdk_nvme_ctrlr *ctrlr,
const struct spdk_nvme_ctrlr_opts *opts)
{
struct dev *dev;

View File

@ -65,6 +65,12 @@ nvme_ctrlr_start(struct spdk_nvme_ctrlr *ctrlr)
return 0;
}
void
spdk_nvme_ctrlr_opts_set_defaults(struct spdk_nvme_ctrlr_opts *opts)
{
memset(opts, 0, sizeof(*opts));
}
int main(int argc, char **argv)
{
CU_pSuite suite = NULL;

View File

@ -422,7 +422,7 @@ setup_qpairs(struct spdk_nvme_ctrlr *ctrlr, uint32_t num_io_queues)
SPDK_CU_ASSERT_FATAL(nvme_ctrlr_construct(ctrlr, NULL) == 0);
/* Fake out the parts of ctrlr needed for I/O qpair allocation */
ctrlr->num_io_queues = num_io_queues;
ctrlr->opts.num_io_queues = num_io_queues;
SPDK_CU_ASSERT_FATAL(nvme_ctrlr_construct_io_qpairs(ctrlr) == 0);
}
@ -500,7 +500,7 @@ test_nvme_ctrlr_fail(void)
{
struct spdk_nvme_ctrlr ctrlr = {};
ctrlr.num_io_queues = 0;
ctrlr.opts.num_io_queues = 0;
nvme_ctrlr_fail(&ctrlr);
CU_ASSERT(ctrlr.is_failed == true);

View File

@ -77,6 +77,12 @@ nvme_ctrlr_start(struct spdk_nvme_ctrlr *ctrlr)
return 0;
}
void
spdk_nvme_ctrlr_opts_set_defaults(struct spdk_nvme_ctrlr_opts *opts)
{
memset(opts, 0, sizeof(*opts));
}
uint32_t
spdk_nvme_ns_get_sector_size(struct spdk_nvme_ns *ns)
{