bdev/ocssd: request resubmission
If a spdk_bdev_io cannot be completed, because it is sent to a zone that is currently busy, reschedule its submission. This mechanism will be used by appends, as mutliple append commands can be directed to the same zone at the same time. Change-Id: I60da2bd1835380812d22536ea275fb8fed9f8561 Signed-off-by: Konrad Sztyber <konrad.sztyber@intel.com> Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/477437 Reviewed-by: Mateusz Kozlowski <mateusz.kozlowski@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com> Community-CI: Broadcom SPDK FC-NVMe CI <spdk-ci.pdl@broadcom.com> Community-CI: SPDK CI Jenkins <sys_sgci@intel.com> Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
parent
ffd53b6bad
commit
1ad438311e
@ -631,6 +631,13 @@ bdev_nvme_create_cb(void *io_device, void *ctx_buf)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (spdk_nvme_ctrlr_is_ocssd_supported(nvme_bdev_ctrlr->ctrlr)) {
|
||||
if (bdev_ocssd_create_io_channel(ch)) {
|
||||
spdk_nvme_ctrlr_free_io_qpair(ch->qpair);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
ch->poller = spdk_poller_register(bdev_nvme_poll, ch, g_opts.nvme_ioq_poll_period_us);
|
||||
|
||||
TAILQ_INIT(&ch->pending_resets);
|
||||
@ -640,8 +647,13 @@ bdev_nvme_create_cb(void *io_device, void *ctx_buf)
|
||||
static void
|
||||
bdev_nvme_destroy_cb(void *io_device, void *ctx_buf)
|
||||
{
|
||||
struct nvme_bdev_ctrlr *nvme_bdev_ctrlr = io_device;
|
||||
struct nvme_io_channel *ch = ctx_buf;
|
||||
|
||||
if (spdk_nvme_ctrlr_is_ocssd_supported(nvme_bdev_ctrlr->ctrlr)) {
|
||||
bdev_ocssd_destroy_io_channel(ch);
|
||||
}
|
||||
|
||||
spdk_nvme_ctrlr_free_io_qpair(ch->qpair);
|
||||
spdk_poller_unregister(&ch->poller);
|
||||
}
|
||||
|
@ -74,6 +74,11 @@ struct bdev_ocssd_io {
|
||||
};
|
||||
};
|
||||
|
||||
struct ocssd_io_channel {
|
||||
struct spdk_poller *pending_poller;
|
||||
TAILQ_HEAD(, spdk_bdev_io) pending_requests;
|
||||
};
|
||||
|
||||
struct ocssd_bdev {
|
||||
struct nvme_bdev nvme_bdev;
|
||||
struct bdev_ocssd_zone *zones;
|
||||
@ -582,6 +587,63 @@ bdev_ocssd_zone_management(struct spdk_io_channel *ioch, struct spdk_bdev_io *bd
|
||||
}
|
||||
}
|
||||
|
||||
static void bdev_ocssd_submit_request(struct spdk_io_channel *ioch, struct spdk_bdev_io *bdev_io);
|
||||
|
||||
static int
|
||||
bdev_ocssd_poll_pending(void *ctx)
|
||||
{
|
||||
struct spdk_io_channel *ioch = ctx;
|
||||
struct nvme_io_channel *nvme_ioch;
|
||||
struct ocssd_io_channel *ocssd_ioch;
|
||||
struct spdk_bdev_io *bdev_io;
|
||||
TAILQ_HEAD(, spdk_bdev_io) pending_requests;
|
||||
int num_requests = 0;
|
||||
|
||||
nvme_ioch = spdk_io_channel_get_ctx(ioch);
|
||||
ocssd_ioch = nvme_ioch->ocssd_ioch;
|
||||
|
||||
TAILQ_INIT(&pending_requests);
|
||||
TAILQ_SWAP(&ocssd_ioch->pending_requests, &pending_requests, spdk_bdev_io, module_link);
|
||||
|
||||
while ((bdev_io = TAILQ_FIRST(&pending_requests))) {
|
||||
TAILQ_REMOVE(&pending_requests, bdev_io, module_link);
|
||||
bdev_ocssd_submit_request(ioch, bdev_io);
|
||||
num_requests++;
|
||||
}
|
||||
|
||||
if (TAILQ_EMPTY(&ocssd_ioch->pending_requests)) {
|
||||
spdk_poller_unregister(&ocssd_ioch->pending_poller);
|
||||
}
|
||||
|
||||
return num_requests;
|
||||
}
|
||||
|
||||
static void
|
||||
bdev_ocssd_delay_request(struct spdk_io_channel *ioch, struct spdk_bdev_io *bdev_io)
|
||||
{
|
||||
struct nvme_io_channel *nvme_ioch = spdk_io_channel_get_ctx(ioch);
|
||||
struct ocssd_io_channel *ocssd_ioch = nvme_ioch->ocssd_ioch;
|
||||
|
||||
TAILQ_INSERT_TAIL(&ocssd_ioch->pending_requests, bdev_io, module_link);
|
||||
|
||||
if (ocssd_ioch->pending_poller != NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
ocssd_ioch->pending_poller = spdk_poller_register(bdev_ocssd_poll_pending, ioch, 0);
|
||||
if (ocssd_ioch->pending_poller == NULL) {
|
||||
SPDK_ERRLOG("Failed to register pending requests poller\n");
|
||||
|
||||
/* If the poller cannot be registered, complete all of the pending
|
||||
* requests immediately, as we have no means of resubmitting them.
|
||||
*/
|
||||
while ((bdev_io = TAILQ_FIRST(&ocssd_ioch->pending_requests))) {
|
||||
TAILQ_REMOVE(&ocssd_ioch->pending_requests, bdev_io, module_link);
|
||||
spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bdev_ocssd_submit_request(struct spdk_io_channel *ioch, struct spdk_bdev_io *bdev_io)
|
||||
{
|
||||
@ -611,10 +673,16 @@ bdev_ocssd_submit_request(struct spdk_io_channel *ioch, struct spdk_bdev_io *bde
|
||||
}
|
||||
|
||||
if (spdk_unlikely(rc != 0)) {
|
||||
if (rc == -ENOMEM) {
|
||||
switch (rc) {
|
||||
case -ENOMEM:
|
||||
spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_NOMEM);
|
||||
} else {
|
||||
break;
|
||||
case -EAGAIN:
|
||||
bdev_ocssd_delay_request(ioch, bdev_io);
|
||||
break;
|
||||
default:
|
||||
spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1054,4 +1122,23 @@ bdev_ocssd_depopulate_namespace(struct nvme_bdev_ns *ns)
|
||||
ns->type_ctx = NULL;
|
||||
}
|
||||
|
||||
int
|
||||
bdev_ocssd_create_io_channel(struct nvme_io_channel *ioch)
|
||||
{
|
||||
ioch->ocssd_ioch = calloc(1, sizeof(*ioch->ocssd_ioch));
|
||||
if (ioch->ocssd_ioch == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
TAILQ_INIT(&ioch->ocssd_ioch->pending_requests);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
bdev_ocssd_destroy_io_channel(struct nvme_io_channel *ioch)
|
||||
{
|
||||
free(ioch->ocssd_ioch);
|
||||
}
|
||||
|
||||
SPDK_LOG_REGISTER_COMPONENT("bdev_ocssd", SPDK_LOG_BDEV_OCSSD)
|
||||
|
@ -50,4 +50,7 @@ void bdev_ocssd_populate_namespace(struct nvme_bdev_ctrlr *nvme_bdev_ctrlr,
|
||||
void bdev_ocssd_depopulate_namespace(struct nvme_bdev_ns *ns);
|
||||
void bdev_ocssd_namespace_config_json(struct spdk_json_write_ctx *w, struct nvme_bdev_ns *ns);
|
||||
|
||||
int bdev_ocssd_create_io_channel(struct nvme_io_channel *ioch);
|
||||
void bdev_ocssd_destroy_io_channel(struct nvme_io_channel *ioch);
|
||||
|
||||
#endif /* SPDK_BDEV_OCSSD_H */
|
||||
|
@ -128,6 +128,8 @@ struct nvme_async_probe_ctx {
|
||||
uint32_t populates_in_progress;
|
||||
};
|
||||
|
||||
struct ocssd_io_channel;
|
||||
|
||||
struct nvme_io_channel {
|
||||
struct spdk_nvme_qpair *qpair;
|
||||
struct spdk_poller *poller;
|
||||
@ -137,6 +139,8 @@ struct nvme_io_channel {
|
||||
uint64_t spin_ticks;
|
||||
uint64_t start_ticks;
|
||||
uint64_t end_ticks;
|
||||
|
||||
struct ocssd_io_channel *ocssd_ioch;
|
||||
};
|
||||
|
||||
void nvme_ctrlr_populate_namespace_done(struct nvme_async_probe_ctx *ctx,
|
||||
|
@ -53,6 +53,8 @@ DEFINE_STUB_V(spdk_opal_close, (struct spdk_opal_dev *dev));
|
||||
DEFINE_STUB(spdk_opal_revert_poll, int, (struct spdk_opal_dev *dev), 0);
|
||||
DEFINE_STUB_V(spdk_bdev_io_complete_nvme_status, (struct spdk_bdev_io *bdev_io, uint32_t cdw0,
|
||||
int sct, int sc));
|
||||
DEFINE_STUB(spdk_bdev_io_get_io_channel, struct spdk_io_channel *, (struct spdk_bdev_io *bdev_io),
|
||||
NULL);
|
||||
|
||||
struct nvme_request {
|
||||
spdk_nvme_cmd_cb cb_fn;
|
||||
|
Loading…
Reference in New Issue
Block a user