channel: Make spdk_for_each_channel support async operations
While iterating, allow the user to perform asynchronous operations. To continue iteration, the user is expected to call spdk_for_each_channel_continue. Change-Id: Ifd7d03d5fbf17cf13843704274b036d49ca0484a Signed-off-by: Ben Walker <benjamin.walker@intel.com> Reviewed-on: https://review.gerrithub.io/391309 Tested-by: SPDK Automated Test System <sys_sgsw@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com> Reviewed-by: Dariusz Stojaczyk <dariuszx.stojaczyk@intel.com>
This commit is contained in:
parent
250f8e07bc
commit
5165aee686
@ -22,6 +22,10 @@ framework (include/spdk/event.h) to the I/O channel library
|
|||||||
(include/spdk/io_channel.h). This allows code that doesn't depend on the event
|
(include/spdk/io_channel.h). This allows code that doesn't depend on the event
|
||||||
framework to request registration and unregistration of pollers.
|
framework to request registration and unregistration of pollers.
|
||||||
|
|
||||||
|
spdk_for_each_channel() now allows asynchronous operations during iteration.
|
||||||
|
Instead of immediately continuing the interation upon returning from the iteration
|
||||||
|
callback, the user must call spdk_for_each_channel_continue() to resume iteration.
|
||||||
|
|
||||||
### Block Device Abstraction Layer (bdev)
|
### Block Device Abstraction Layer (bdev)
|
||||||
|
|
||||||
The poller abstraction was removed from the bdev layer. There is now a general purpose
|
The poller abstraction was removed from the bdev layer. There is now a general purpose
|
||||||
|
@ -48,6 +48,7 @@ extern "C" {
|
|||||||
|
|
||||||
struct spdk_thread;
|
struct spdk_thread;
|
||||||
struct spdk_io_channel;
|
struct spdk_io_channel;
|
||||||
|
struct spdk_io_channel_iter;
|
||||||
struct spdk_poller;
|
struct spdk_poller;
|
||||||
|
|
||||||
typedef void (*spdk_thread_fn)(void *ctx);
|
typedef void (*spdk_thread_fn)(void *ctx);
|
||||||
@ -66,9 +67,8 @@ typedef void (*spdk_io_channel_destroy_cb)(void *io_device, void *ctx_buf);
|
|||||||
|
|
||||||
typedef void (*spdk_io_device_unregister_cb)(void *io_device);
|
typedef void (*spdk_io_device_unregister_cb)(void *io_device);
|
||||||
|
|
||||||
typedef int (*spdk_channel_msg)(void *io_device, struct spdk_io_channel *ch,
|
typedef void (*spdk_channel_msg)(struct spdk_io_channel_iter *i);
|
||||||
void *ctx);
|
typedef void (*spdk_channel_for_each_cpl)(struct spdk_io_channel_iter *i, int status);
|
||||||
typedef void (*spdk_channel_for_each_cpl)(void *io_device, void *ctx, int status);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Initializes the calling thread for I/O channel allocation.
|
* \brief Initializes the calling thread for I/O channel allocation.
|
||||||
@ -216,7 +216,8 @@ struct spdk_thread *spdk_io_channel_get_thread(struct spdk_io_channel *ch);
|
|||||||
* asynchronously, so fn may be called after spdk_for_each_channel returns.
|
* asynchronously, so fn may be called after spdk_for_each_channel returns.
|
||||||
* 'fn' will be called on the correct thread for each channel. 'fn' will be
|
* 'fn' will be called on the correct thread for each channel. 'fn' will be
|
||||||
* called for each channel serially, such that two calls to 'fn' will not
|
* called for each channel serially, such that two calls to 'fn' will not
|
||||||
* overlap in time.
|
* overlap in time. After 'fn' has been called, call
|
||||||
|
* spdk_for_each_channel_continue() to continue iterating.
|
||||||
*
|
*
|
||||||
* Once 'fn' has been called on each channel, 'cpl' will be called
|
* Once 'fn' has been called on each channel, 'cpl' will be called
|
||||||
* on the thread that spdk_for_each_channel was initially called from.
|
* on the thread that spdk_for_each_channel was initially called from.
|
||||||
@ -224,6 +225,14 @@ struct spdk_thread *spdk_io_channel_get_thread(struct spdk_io_channel *ch);
|
|||||||
void spdk_for_each_channel(void *io_device, spdk_channel_msg fn, void *ctx,
|
void spdk_for_each_channel(void *io_device, spdk_channel_msg fn, void *ctx,
|
||||||
spdk_channel_for_each_cpl cpl);
|
spdk_channel_for_each_cpl cpl);
|
||||||
|
|
||||||
|
void *spdk_io_channel_iter_get_io_device(struct spdk_io_channel_iter *i);
|
||||||
|
|
||||||
|
struct spdk_io_channel *spdk_io_channel_iter_get_channel(struct spdk_io_channel_iter *i);
|
||||||
|
|
||||||
|
void *spdk_io_channel_iter_get_ctx(struct spdk_io_channel_iter *i);
|
||||||
|
|
||||||
|
void spdk_for_each_channel_continue(struct spdk_io_channel_iter *i, int status);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -232,25 +232,27 @@ bdev_aio_poll(void *arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
_bdev_aio_get_io_inflight(void *io_device, struct spdk_io_channel *ch,
|
_bdev_aio_get_io_inflight(struct spdk_io_channel_iter *i)
|
||||||
void *ctx)
|
|
||||||
{
|
{
|
||||||
|
struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(i);
|
||||||
struct bdev_aio_io_channel *aio_ch = spdk_io_channel_get_ctx(ch);
|
struct bdev_aio_io_channel *aio_ch = spdk_io_channel_get_ctx(ch);
|
||||||
|
|
||||||
if (aio_ch->io_inflight) {
|
if (aio_ch->io_inflight) {
|
||||||
return -1;
|
spdk_for_each_channel_continue(i, -1);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
|
spdk_for_each_channel_continue(i, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bdev_aio_reset_retry_timer(void *arg);
|
bdev_aio_reset_retry_timer(void *arg);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_bdev_aio_get_io_inflight_done(void *io_device, void *ctx, int status)
|
_bdev_aio_get_io_inflight_done(struct spdk_io_channel_iter *i, int status)
|
||||||
{
|
{
|
||||||
struct file_disk *fdisk = ctx;
|
struct file_disk *fdisk = spdk_io_channel_iter_get_ctx(i);
|
||||||
|
|
||||||
if (status == -1) {
|
if (status == -1) {
|
||||||
fdisk->reset_retry_timer = spdk_poller_register(bdev_aio_reset_retry_timer, fdisk, 500);
|
fdisk->reset_retry_timer = spdk_poller_register(bdev_aio_reset_retry_timer, fdisk, 500);
|
||||||
|
@ -1310,9 +1310,9 @@ spdk_bdev_flush_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_spdk_bdev_reset_dev(void *io_device, void *ctx, int status)
|
_spdk_bdev_reset_dev(struct spdk_io_channel_iter *i, int status)
|
||||||
{
|
{
|
||||||
struct spdk_bdev_channel *ch = ctx;
|
struct spdk_bdev_channel *ch = spdk_io_channel_iter_get_ctx(i);
|
||||||
struct spdk_bdev_io *bdev_io;
|
struct spdk_bdev_io *bdev_io;
|
||||||
|
|
||||||
bdev_io = TAILQ_FIRST(&ch->queued_resets);
|
bdev_io = TAILQ_FIRST(&ch->queued_resets);
|
||||||
@ -1320,13 +1320,14 @@ _spdk_bdev_reset_dev(void *io_device, void *ctx, int status)
|
|||||||
spdk_bdev_io_submit_reset(bdev_io);
|
spdk_bdev_io_submit_reset(bdev_io);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
_spdk_bdev_reset_freeze_channel(void *io_device, struct spdk_io_channel *ch,
|
_spdk_bdev_reset_freeze_channel(struct spdk_io_channel_iter *i)
|
||||||
void *ctx)
|
|
||||||
{
|
{
|
||||||
|
struct spdk_io_channel *ch;
|
||||||
struct spdk_bdev_channel *channel;
|
struct spdk_bdev_channel *channel;
|
||||||
struct spdk_bdev_mgmt_channel *mgmt_channel;
|
struct spdk_bdev_mgmt_channel *mgmt_channel;
|
||||||
|
|
||||||
|
ch = spdk_io_channel_iter_get_channel(i);
|
||||||
channel = spdk_io_channel_get_ctx(ch);
|
channel = spdk_io_channel_get_ctx(ch);
|
||||||
mgmt_channel = spdk_io_channel_get_ctx(channel->mgmt_channel);
|
mgmt_channel = spdk_io_channel_get_ctx(channel->mgmt_channel);
|
||||||
|
|
||||||
@ -1336,7 +1337,7 @@ _spdk_bdev_reset_freeze_channel(void *io_device, struct spdk_io_channel *ch,
|
|||||||
_spdk_bdev_abort_buf_io(&mgmt_channel->need_buf_small, channel);
|
_spdk_bdev_abort_buf_io(&mgmt_channel->need_buf_small, channel);
|
||||||
_spdk_bdev_abort_buf_io(&mgmt_channel->need_buf_large, channel);
|
_spdk_bdev_abort_buf_io(&mgmt_channel->need_buf_large, channel);
|
||||||
|
|
||||||
return 0;
|
spdk_for_each_channel_continue(i, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1583,9 +1584,9 @@ _spdk_bdev_io_complete(void *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_spdk_bdev_reset_complete(void *io_device, void *ctx, int status)
|
_spdk_bdev_reset_complete(struct spdk_io_channel_iter *i, int status)
|
||||||
{
|
{
|
||||||
struct spdk_bdev_io *bdev_io = ctx;
|
struct spdk_bdev_io *bdev_io = spdk_io_channel_iter_get_ctx(i);
|
||||||
|
|
||||||
if (bdev_io->u.reset.ch_ref != NULL) {
|
if (bdev_io->u.reset.ch_ref != NULL) {
|
||||||
spdk_put_io_channel(bdev_io->u.reset.ch_ref);
|
spdk_put_io_channel(bdev_io->u.reset.ch_ref);
|
||||||
@ -1595,9 +1596,10 @@ _spdk_bdev_reset_complete(void *io_device, void *ctx, int status)
|
|||||||
_spdk_bdev_io_complete(bdev_io);
|
_spdk_bdev_io_complete(bdev_io);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
_spdk_bdev_unfreeze_channel(void *io_device, struct spdk_io_channel *_ch, void *ctx)
|
_spdk_bdev_unfreeze_channel(struct spdk_io_channel_iter *i)
|
||||||
{
|
{
|
||||||
|
struct spdk_io_channel *_ch = spdk_io_channel_iter_get_channel(i);
|
||||||
struct spdk_bdev_channel *ch = spdk_io_channel_get_ctx(_ch);
|
struct spdk_bdev_channel *ch = spdk_io_channel_get_ctx(_ch);
|
||||||
|
|
||||||
ch->flags &= ~BDEV_CH_RESET_IN_PROGRESS;
|
ch->flags &= ~BDEV_CH_RESET_IN_PROGRESS;
|
||||||
@ -1605,7 +1607,7 @@ _spdk_bdev_unfreeze_channel(void *io_device, struct spdk_io_channel *_ch, void *
|
|||||||
_spdk_bdev_channel_start_reset(ch);
|
_spdk_bdev_channel_start_reset(ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
spdk_for_each_channel_continue(i, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -271,35 +271,38 @@ bdev_nvme_flush(struct nvme_bdev *nbdev, struct nvme_bdev_io *bio,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_bdev_nvme_reset_done(void *io_device, void *ctx, int status)
|
_bdev_nvme_reset_done(struct spdk_io_channel_iter *i, int status)
|
||||||
{
|
{
|
||||||
|
void *ctx = spdk_io_channel_iter_get_ctx(i);
|
||||||
int rc = SPDK_BDEV_IO_STATUS_SUCCESS;
|
int rc = SPDK_BDEV_IO_STATUS_SUCCESS;
|
||||||
|
|
||||||
if (status) {
|
if (status) {
|
||||||
rc = SPDK_BDEV_IO_STATUS_FAILED;
|
rc = SPDK_BDEV_IO_STATUS_FAILED;
|
||||||
}
|
}
|
||||||
spdk_bdev_io_complete(spdk_bdev_io_from_ctx(ctx), rc);
|
spdk_bdev_io_complete(spdk_bdev_io_from_ctx(ctx), rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
_bdev_nvme_reset_create_qpair(void *io_device, struct spdk_io_channel *ch,
|
_bdev_nvme_reset_create_qpair(struct spdk_io_channel_iter *i)
|
||||||
void *ctx)
|
|
||||||
{
|
{
|
||||||
struct spdk_nvme_ctrlr *ctrlr = io_device;
|
struct spdk_nvme_ctrlr *ctrlr = spdk_io_channel_iter_get_io_device(i);
|
||||||
struct nvme_io_channel *nvme_ch = spdk_io_channel_get_ctx(ch);
|
struct spdk_io_channel *_ch = spdk_io_channel_iter_get_channel(i);
|
||||||
|
struct nvme_io_channel *nvme_ch = spdk_io_channel_get_ctx(_ch);
|
||||||
|
|
||||||
nvme_ch->qpair = spdk_nvme_ctrlr_alloc_io_qpair(ctrlr, NULL, 0);
|
nvme_ch->qpair = spdk_nvme_ctrlr_alloc_io_qpair(ctrlr, NULL, 0);
|
||||||
if (!nvme_ch->qpair) {
|
if (!nvme_ch->qpair) {
|
||||||
return -1;
|
spdk_for_each_channel_continue(i, -1);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
spdk_for_each_channel_continue(i, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_bdev_nvme_reset(void *io_device, void *ctx, int status)
|
_bdev_nvme_reset(struct spdk_io_channel_iter *i, int status)
|
||||||
{
|
{
|
||||||
struct spdk_nvme_ctrlr *ctrlr = io_device;
|
struct spdk_nvme_ctrlr *ctrlr = spdk_io_channel_iter_get_io_device(i);
|
||||||
struct nvme_bdev_io *bio = ctx;
|
struct nvme_bdev_io *bio = spdk_io_channel_iter_get_ctx(i);
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (status) {
|
if (status) {
|
||||||
@ -316,16 +319,16 @@ _bdev_nvme_reset(void *io_device, void *ctx, int status)
|
|||||||
/* Recreate all of the I/O queue pairs */
|
/* Recreate all of the I/O queue pairs */
|
||||||
spdk_for_each_channel(ctrlr,
|
spdk_for_each_channel(ctrlr,
|
||||||
_bdev_nvme_reset_create_qpair,
|
_bdev_nvme_reset_create_qpair,
|
||||||
ctx,
|
bio,
|
||||||
_bdev_nvme_reset_done);
|
_bdev_nvme_reset_done);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
_bdev_nvme_reset_destroy_qpair(void *io_device, struct spdk_io_channel *ch,
|
_bdev_nvme_reset_destroy_qpair(struct spdk_io_channel_iter *i)
|
||||||
void *ctx)
|
|
||||||
{
|
{
|
||||||
|
struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(i);
|
||||||
struct nvme_io_channel *nvme_ch = spdk_io_channel_get_ctx(ch);
|
struct nvme_io_channel *nvme_ch = spdk_io_channel_get_ctx(ch);
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
@ -334,7 +337,7 @@ _bdev_nvme_reset_destroy_qpair(void *io_device, struct spdk_io_channel *ch,
|
|||||||
nvme_ch->qpair = NULL;
|
nvme_ch->qpair = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
spdk_for_each_channel_continue(i, rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -216,22 +216,23 @@ struct spdk_nvmf_tgt_listen_ctx {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
spdk_nvmf_tgt_listen_done(void *io_device, void *c, int status)
|
spdk_nvmf_tgt_listen_done(struct spdk_io_channel_iter *i, int status)
|
||||||
{
|
{
|
||||||
free(c);
|
void *ctx = spdk_io_channel_iter_get_ctx(i);
|
||||||
|
|
||||||
|
free(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
spdk_nvmf_tgt_listen_add_transport(void *io_device,
|
spdk_nvmf_tgt_listen_add_transport(struct spdk_io_channel_iter *i)
|
||||||
struct spdk_io_channel *ch,
|
|
||||||
void *c)
|
|
||||||
{
|
{
|
||||||
struct spdk_nvmf_tgt_listen_ctx *ctx = c;
|
struct spdk_nvmf_tgt_listen_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
|
||||||
struct spdk_nvmf_poll_group *group;
|
struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(i);
|
||||||
|
struct spdk_nvmf_poll_group *group = spdk_io_channel_get_ctx(ch);
|
||||||
|
int rc;
|
||||||
|
|
||||||
group = spdk_io_channel_get_ctx(ch);
|
rc = spdk_nvmf_poll_group_add_transport(group, ctx->transport);
|
||||||
|
spdk_for_each_channel_continue(i, rc);
|
||||||
return spdk_nvmf_poll_group_add_transport(group, ctx->transport);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -71,21 +71,20 @@ spdk_nvmf_valid_nqn(const char *nqn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
spdk_nvmf_subsystem_create_done(void *io_device, void *ctx, int status)
|
spdk_nvmf_subsystem_create_done(struct spdk_io_channel_iter *i, int status)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
spdk_nvmf_subsystem_add_to_poll_group(void *io_device,
|
spdk_nvmf_subsystem_add_to_poll_group(struct spdk_io_channel_iter *i)
|
||||||
struct spdk_io_channel *ch,
|
|
||||||
void *ctx)
|
|
||||||
{
|
{
|
||||||
struct spdk_nvmf_poll_group *group;
|
struct spdk_nvmf_subsystem *subsystem = spdk_io_channel_iter_get_ctx(i);
|
||||||
struct spdk_nvmf_subsystem *subsystem = ctx;
|
struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(i);
|
||||||
|
struct spdk_nvmf_poll_group *group = spdk_io_channel_get_ctx(ch);
|
||||||
|
int rc;
|
||||||
|
|
||||||
group = spdk_io_channel_get_ctx(ch);
|
rc = spdk_nvmf_poll_group_add_subsystem(group, subsystem);
|
||||||
|
spdk_for_each_channel_continue(i, rc);
|
||||||
return spdk_nvmf_poll_group_add_subsystem(group, subsystem);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct spdk_nvmf_subsystem *
|
struct spdk_nvmf_subsystem *
|
||||||
@ -167,10 +166,10 @@ spdk_nvmf_create_subsystem(struct spdk_nvmf_tgt *tgt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
spdk_nvmf_subsystem_delete_done(void *io_device, void *ctx, int status)
|
spdk_nvmf_subsystem_delete_done(struct spdk_io_channel_iter *i, int status)
|
||||||
{
|
{
|
||||||
struct spdk_nvmf_tgt *tgt = io_device;
|
struct spdk_nvmf_tgt *tgt = spdk_io_channel_iter_get_io_device(i);
|
||||||
struct spdk_nvmf_subsystem *subsystem = ctx;
|
struct spdk_nvmf_subsystem *subsystem = spdk_io_channel_iter_get_ctx(i);
|
||||||
struct spdk_nvmf_ns *ns;
|
struct spdk_nvmf_ns *ns;
|
||||||
|
|
||||||
for (ns = spdk_nvmf_subsystem_get_first_ns(subsystem); ns != NULL;
|
for (ns = spdk_nvmf_subsystem_get_first_ns(subsystem); ns != NULL;
|
||||||
@ -189,17 +188,17 @@ spdk_nvmf_subsystem_delete_done(void *io_device, void *ctx, int status)
|
|||||||
free(subsystem);
|
free(subsystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
spdk_nvmf_subsystem_remove_from_poll_group(void *io_device,
|
spdk_nvmf_subsystem_remove_from_poll_group(struct spdk_io_channel_iter *i)
|
||||||
struct spdk_io_channel *ch,
|
|
||||||
void *ctx)
|
|
||||||
{
|
{
|
||||||
struct spdk_nvmf_poll_group *group;
|
struct spdk_nvmf_subsystem *subsystem = spdk_io_channel_iter_get_ctx(i);
|
||||||
struct spdk_nvmf_subsystem *subsystem = ctx;
|
struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(i);
|
||||||
|
struct spdk_nvmf_poll_group *group = spdk_io_channel_get_ctx(ch);
|
||||||
|
int rc;
|
||||||
|
|
||||||
group = spdk_io_channel_get_ctx(ch);
|
rc = spdk_nvmf_poll_group_remove_subsystem(group, subsystem);
|
||||||
|
|
||||||
return spdk_nvmf_poll_group_remove_subsystem(group, subsystem);
|
spdk_for_each_channel_continue(i, rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -433,22 +432,24 @@ struct spdk_nvmf_subsystem_add_ns_ctx {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
spdk_nvmf_subsystem_add_ns_done(void *io_device, void *ctx, int status)
|
spdk_nvmf_subsystem_add_ns_done(struct spdk_io_channel_iter *i, int status)
|
||||||
{
|
{
|
||||||
|
void *ctx = spdk_io_channel_iter_get_ctx(i);
|
||||||
|
|
||||||
free(ctx);
|
free(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
spdk_nvmf_subsystem_ns_update_poll_group(void *io_device,
|
spdk_nvmf_subsystem_ns_update_poll_group(struct spdk_io_channel_iter *i)
|
||||||
struct spdk_io_channel *ch,
|
|
||||||
void *c)
|
|
||||||
{
|
{
|
||||||
struct spdk_nvmf_poll_group *group;
|
struct spdk_nvmf_subsystem_add_ns_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
|
||||||
struct spdk_nvmf_subsystem_add_ns_ctx *ctx = c;
|
struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(i);
|
||||||
|
struct spdk_nvmf_poll_group *group = spdk_io_channel_get_ctx(ch);
|
||||||
|
int rc;
|
||||||
|
|
||||||
group = spdk_io_channel_get_ctx(ch);
|
rc = spdk_nvmf_poll_group_add_ns(group, ctx->subsystem, ctx->ns);
|
||||||
|
|
||||||
return spdk_nvmf_poll_group_add_ns(group, ctx->subsystem, ctx->ns);
|
spdk_for_each_channel_continue(i, rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
|
@ -514,12 +514,13 @@ spdk_io_channel_get_thread(struct spdk_io_channel *ch)
|
|||||||
return ch->thread;
|
return ch->thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct call_channel {
|
struct spdk_io_channel_iter {
|
||||||
void *io_device;
|
void *io_device;
|
||||||
struct io_device *dev;
|
struct io_device *dev;
|
||||||
spdk_channel_msg fn;
|
spdk_channel_msg fn;
|
||||||
int status;
|
int status;
|
||||||
void *ctx;
|
void *ctx;
|
||||||
|
struct spdk_io_channel *ch;
|
||||||
|
|
||||||
struct spdk_thread *cur_thread;
|
struct spdk_thread *cur_thread;
|
||||||
|
|
||||||
@ -527,64 +528,59 @@ struct call_channel {
|
|||||||
spdk_channel_for_each_cpl cpl;
|
spdk_channel_for_each_cpl cpl;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void *
|
||||||
|
spdk_io_channel_iter_get_io_device(struct spdk_io_channel_iter *i)
|
||||||
|
{
|
||||||
|
return i->io_device;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct spdk_io_channel *
|
||||||
|
spdk_io_channel_iter_get_channel(struct spdk_io_channel_iter *i)
|
||||||
|
{
|
||||||
|
return i->ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
spdk_io_channel_iter_get_ctx(struct spdk_io_channel_iter *i)
|
||||||
|
{
|
||||||
|
return i->ctx;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_call_completion(void *ctx)
|
_call_completion(void *ctx)
|
||||||
{
|
{
|
||||||
struct call_channel *ch_ctx = ctx;
|
struct spdk_io_channel_iter *i = ctx;
|
||||||
|
|
||||||
if (ch_ctx->cpl != NULL) {
|
if (i->cpl != NULL) {
|
||||||
ch_ctx->cpl(ch_ctx->io_device, ch_ctx->ctx, ch_ctx->status);
|
i->cpl(i, i->status);
|
||||||
}
|
}
|
||||||
free(ch_ctx);
|
free(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_call_channel(void *ctx)
|
_call_channel(void *ctx)
|
||||||
{
|
{
|
||||||
struct call_channel *ch_ctx = ctx;
|
struct spdk_io_channel_iter *i = ctx;
|
||||||
struct spdk_thread *thread;
|
|
||||||
struct spdk_io_channel *ch;
|
struct spdk_io_channel *ch;
|
||||||
|
|
||||||
thread = ch_ctx->cur_thread;
|
|
||||||
pthread_mutex_lock(&g_devlist_mutex);
|
|
||||||
TAILQ_FOREACH(ch, &thread->io_channels, tailq) {
|
|
||||||
if (ch->dev->io_device == ch_ctx->io_device) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&g_devlist_mutex);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* It is possible that the channel was deleted before this
|
* It is possible that the channel was deleted before this
|
||||||
* message had a chance to execute. If so, skip calling
|
* message had a chance to execute. If so, skip calling
|
||||||
* the fn() on this thread.
|
* the fn() on this thread.
|
||||||
*/
|
*/
|
||||||
if (ch != NULL) {
|
|
||||||
ch_ctx->status = ch_ctx->fn(ch_ctx->io_device, ch, ch_ctx->ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_lock(&g_devlist_mutex);
|
pthread_mutex_lock(&g_devlist_mutex);
|
||||||
if (ch_ctx->status) {
|
TAILQ_FOREACH(ch, &i->cur_thread->io_channels, tailq) {
|
||||||
goto end;
|
if (ch->dev->io_device == i->io_device) {
|
||||||
}
|
break;
|
||||||
thread = TAILQ_NEXT(thread, tailq);
|
|
||||||
while (thread) {
|
|
||||||
TAILQ_FOREACH(ch, &thread->io_channels, tailq) {
|
|
||||||
if (ch->dev->io_device == ch_ctx->io_device) {
|
|
||||||
ch_ctx->cur_thread = thread;
|
|
||||||
pthread_mutex_unlock(&g_devlist_mutex);
|
|
||||||
spdk_thread_send_msg(thread, _call_channel, ch_ctx);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
thread = TAILQ_NEXT(thread, tailq);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
|
||||||
ch_ctx->dev->for_each_count--;
|
|
||||||
pthread_mutex_unlock(&g_devlist_mutex);
|
pthread_mutex_unlock(&g_devlist_mutex);
|
||||||
|
|
||||||
spdk_thread_send_msg(ch_ctx->orig_thread, _call_completion, ch_ctx);
|
if (ch) {
|
||||||
|
i->fn(i);
|
||||||
|
} else {
|
||||||
|
spdk_for_each_channel_continue(i, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -593,38 +589,75 @@ spdk_for_each_channel(void *io_device, spdk_channel_msg fn, void *ctx,
|
|||||||
{
|
{
|
||||||
struct spdk_thread *thread;
|
struct spdk_thread *thread;
|
||||||
struct spdk_io_channel *ch;
|
struct spdk_io_channel *ch;
|
||||||
struct call_channel *ch_ctx;
|
struct spdk_io_channel_iter *i;
|
||||||
|
|
||||||
ch_ctx = calloc(1, sizeof(*ch_ctx));
|
i = calloc(1, sizeof(*i));
|
||||||
if (!ch_ctx) {
|
if (!i) {
|
||||||
SPDK_ERRLOG("Unable to allocate context\n");
|
SPDK_ERRLOG("Unable to allocate iterator\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ch_ctx->io_device = io_device;
|
i->io_device = io_device;
|
||||||
ch_ctx->fn = fn;
|
i->fn = fn;
|
||||||
ch_ctx->ctx = ctx;
|
i->ctx = ctx;
|
||||||
ch_ctx->cpl = cpl;
|
i->cpl = cpl;
|
||||||
|
|
||||||
pthread_mutex_lock(&g_devlist_mutex);
|
pthread_mutex_lock(&g_devlist_mutex);
|
||||||
ch_ctx->orig_thread = _get_thread();
|
i->orig_thread = _get_thread();
|
||||||
|
|
||||||
TAILQ_FOREACH(thread, &g_threads, tailq) {
|
TAILQ_FOREACH(thread, &g_threads, tailq) {
|
||||||
TAILQ_FOREACH(ch, &thread->io_channels, tailq) {
|
TAILQ_FOREACH(ch, &thread->io_channels, tailq) {
|
||||||
if (ch->dev->io_device == io_device) {
|
if (ch->dev->io_device == io_device) {
|
||||||
ch->dev->for_each_count++;
|
ch->dev->for_each_count++;
|
||||||
ch_ctx->dev = ch->dev;
|
i->dev = ch->dev;
|
||||||
ch_ctx->cur_thread = thread;
|
i->cur_thread = thread;
|
||||||
|
i->ch = ch;
|
||||||
pthread_mutex_unlock(&g_devlist_mutex);
|
pthread_mutex_unlock(&g_devlist_mutex);
|
||||||
spdk_thread_send_msg(thread, _call_channel, ch_ctx);
|
spdk_thread_send_msg(thread, _call_channel, i);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(ch_ctx);
|
|
||||||
|
|
||||||
pthread_mutex_unlock(&g_devlist_mutex);
|
pthread_mutex_unlock(&g_devlist_mutex);
|
||||||
|
|
||||||
cpl(io_device, ctx, 0);
|
cpl(i, 0);
|
||||||
|
|
||||||
|
free(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
spdk_for_each_channel_continue(struct spdk_io_channel_iter *i, int status)
|
||||||
|
{
|
||||||
|
struct spdk_thread *thread;
|
||||||
|
struct spdk_io_channel *ch;
|
||||||
|
|
||||||
|
assert(i->cur_thread == spdk_get_thread());
|
||||||
|
|
||||||
|
i->status = status;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&g_devlist_mutex);
|
||||||
|
if (status) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
thread = TAILQ_NEXT(i->cur_thread, tailq);
|
||||||
|
while (thread) {
|
||||||
|
TAILQ_FOREACH(ch, &thread->io_channels, tailq) {
|
||||||
|
if (ch->dev->io_device == i->io_device) {
|
||||||
|
i->cur_thread = thread;
|
||||||
|
i->ch = ch;
|
||||||
|
pthread_mutex_unlock(&g_devlist_mutex);
|
||||||
|
spdk_thread_send_msg(thread, _call_channel, i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
thread = TAILQ_NEXT(thread, tailq);
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
i->dev->for_each_count--;
|
||||||
|
i->ch = NULL;
|
||||||
|
pthread_mutex_unlock(&g_devlist_mutex);
|
||||||
|
|
||||||
|
spdk_thread_send_msg(i->orig_thread, _call_completion, i);
|
||||||
}
|
}
|
||||||
|
@ -146,18 +146,19 @@ channel_destroy(void *io_device, void *ctx_buf)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
channel_msg(void *io_device, struct spdk_io_channel *ch, void *ctx)
|
channel_msg(struct spdk_io_channel_iter *i)
|
||||||
{
|
{
|
||||||
|
struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(i);
|
||||||
int *count = spdk_io_channel_get_ctx(ch);
|
int *count = spdk_io_channel_get_ctx(ch);
|
||||||
|
|
||||||
(*count)++;
|
(*count)++;
|
||||||
|
|
||||||
return 0;
|
spdk_for_each_channel_continue(i, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
channel_cpl(void *io_device, void *ctx, int status)
|
channel_cpl(struct spdk_io_channel_iter *i, int status)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,20 +216,20 @@ struct unreg_ctx {
|
|||||||
bool foreach_done;
|
bool foreach_done;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static void
|
||||||
unreg_ch_done(void *io_device, struct spdk_io_channel *_ch, void *_ctx)
|
unreg_ch_done(struct spdk_io_channel_iter *i)
|
||||||
{
|
{
|
||||||
struct unreg_ctx *ctx = _ctx;
|
struct unreg_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
|
||||||
|
|
||||||
ctx->ch_done = true;
|
ctx->ch_done = true;
|
||||||
|
|
||||||
return 0;
|
spdk_for_each_channel_continue(i, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
unreg_foreach_done(void *io_device, void *_ctx, int status)
|
unreg_foreach_done(struct spdk_io_channel_iter *i, int status)
|
||||||
{
|
{
|
||||||
struct unreg_ctx *ctx = _ctx;
|
struct unreg_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
|
||||||
|
|
||||||
ctx->foreach_done = true;
|
ctx->foreach_done = true;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user