lib/nvmf: Add an internal API nvmf_subsystem_set_ana_state()
Add an internal API nvmf_subsystem_set_ana_state() to change the ANA state of the subsystem listener whose trid matches. ANA optimized state, ANA non-optimized state, and ANA inaccessible state are supported. ANA change state is not used and ANA persistent loss state is not supported. After changing the ANA state of the subsystem listener, on each poll group, controllers, whose the subsystem listener match, send ANA change notice. Initiators query ANA log page anyway if they receive ANA change notification. False positive notification should be avoided but is acceptable. To avoid any concurrency conflict, simply compare ctrlr->listener and the passed listener. It may be better to execute nvmf_subsystem_set_ana_state() on the subsystem thread but currently the RPC thread adds and removes a listener to and from the subsystem, respectively, and the subsystem has been suspended while executing nvmf_subsystem_set_ana_state(). Hence we keep this as a future enhancement. Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Change-Id: If1910b79dd33d904114e258ae2c5e868947cdc52 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/4079 Community-CI: Broadcom CI Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Anil Veerabhadrappa <anil.veerabhadrappa@broadcom.com>
This commit is contained in:
parent
523f2a85d3
commit
071d80f37b
@ -96,6 +96,7 @@ struct spdk_nvmf_subsystem_listener {
|
||||
struct spdk_nvme_transport_id *trid;
|
||||
struct spdk_nvmf_transport *transport;
|
||||
enum spdk_nvme_ana_state ana_state;
|
||||
uint64_t ana_state_change_count;
|
||||
TAILQ_ENTRY(spdk_nvmf_subsystem_listener) link;
|
||||
};
|
||||
|
||||
@ -337,6 +338,10 @@ struct spdk_nvmf_subsystem_listener *nvmf_subsystem_find_listener(
|
||||
struct spdk_nvmf_listener *nvmf_transport_find_listener(
|
||||
struct spdk_nvmf_transport *transport,
|
||||
const struct spdk_nvme_transport_id *trid);
|
||||
void nvmf_subsystem_set_ana_state(struct spdk_nvmf_subsystem *subsystem,
|
||||
const struct spdk_nvme_transport_id *trid,
|
||||
enum spdk_nvme_ana_state ana_state,
|
||||
spdk_nvmf_tgt_subsystem_listen_done_fn cb_fn, void *cb_arg);
|
||||
|
||||
int nvmf_ctrlr_async_event_ns_notice(struct spdk_nvmf_ctrlr *ctrlr);
|
||||
int nvmf_ctrlr_async_event_ana_change_notice(struct spdk_nvmf_ctrlr *ctrlr);
|
||||
|
@ -2664,3 +2664,103 @@ spdk_nvmf_subsystem_set_ana_reporting(struct spdk_nvmf_subsystem *subsystem,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct subsystem_listener_update_ctx {
|
||||
struct spdk_nvmf_subsystem_listener *listener;
|
||||
|
||||
spdk_nvmf_tgt_subsystem_listen_done_fn cb_fn;
|
||||
void *cb_arg;
|
||||
};
|
||||
|
||||
static void
|
||||
subsystem_listener_update_done(struct spdk_io_channel_iter *i, int status)
|
||||
{
|
||||
struct subsystem_listener_update_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
|
||||
|
||||
if (ctx->cb_fn) {
|
||||
ctx->cb_fn(ctx->cb_arg, status);
|
||||
}
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
subsystem_listener_update_on_pg(struct spdk_io_channel_iter *i)
|
||||
{
|
||||
struct subsystem_listener_update_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
|
||||
struct spdk_nvmf_subsystem_listener *listener;
|
||||
struct spdk_nvmf_poll_group *group;
|
||||
struct spdk_nvmf_ctrlr *ctrlr;
|
||||
|
||||
listener = ctx->listener;
|
||||
group = spdk_io_channel_get_ctx(spdk_io_channel_iter_get_channel(i));
|
||||
|
||||
TAILQ_FOREACH(ctrlr, &listener->subsystem->ctrlrs, link) {
|
||||
if (ctrlr->admin_qpair->group == group && ctrlr->listener == listener) {
|
||||
nvmf_ctrlr_async_event_ana_change_notice(ctrlr);
|
||||
}
|
||||
}
|
||||
|
||||
spdk_for_each_channel_continue(i, 0);
|
||||
}
|
||||
|
||||
void
|
||||
nvmf_subsystem_set_ana_state(struct spdk_nvmf_subsystem *subsystem,
|
||||
const struct spdk_nvme_transport_id *trid,
|
||||
enum spdk_nvme_ana_state ana_state,
|
||||
spdk_nvmf_tgt_subsystem_listen_done_fn cb_fn, void *cb_arg)
|
||||
{
|
||||
struct spdk_nvmf_subsystem_listener *listener;
|
||||
struct subsystem_listener_update_ctx *ctx;
|
||||
|
||||
assert(cb_fn != NULL);
|
||||
assert(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
|
||||
subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED);
|
||||
|
||||
if (!subsystem->ana_reporting) {
|
||||
SPDK_ERRLOG("ANA reporting is disabled\n");
|
||||
cb_fn(cb_arg, -EINVAL);
|
||||
return;
|
||||
}
|
||||
|
||||
/* ANA Change state is not used, ANA Persistent Loss state
|
||||
* is not supported yet.
|
||||
*/
|
||||
if (!(ana_state == SPDK_NVME_ANA_OPTIMIZED_STATE ||
|
||||
ana_state == SPDK_NVME_ANA_NON_OPTIMIZED_STATE ||
|
||||
ana_state == SPDK_NVME_ANA_INACCESSIBLE_STATE)) {
|
||||
SPDK_ERRLOG("ANA state %d is not supported\n", ana_state);
|
||||
cb_fn(cb_arg, -ENOTSUP);
|
||||
return;
|
||||
}
|
||||
|
||||
listener = nvmf_subsystem_find_listener(subsystem, trid);
|
||||
if (!listener) {
|
||||
SPDK_ERRLOG("Unable to find listener.\n");
|
||||
cb_fn(cb_arg, -EINVAL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (listener->ana_state == ana_state) {
|
||||
cb_fn(cb_arg, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
ctx = calloc(1, sizeof(*ctx));
|
||||
if (!ctx) {
|
||||
SPDK_ERRLOG("Unable to allocate context\n");
|
||||
cb_fn(cb_arg, -ENOMEM);
|
||||
return;
|
||||
}
|
||||
|
||||
listener->ana_state = ana_state;
|
||||
listener->ana_state_change_count++;
|
||||
|
||||
ctx->listener = listener;
|
||||
ctx->cb_fn = cb_fn;
|
||||
ctx->cb_arg = cb_arg;
|
||||
|
||||
spdk_for_each_channel(subsystem->tgt,
|
||||
subsystem_listener_update_on_pg,
|
||||
ctx,
|
||||
subsystem_listener_update_done);
|
||||
}
|
||||
|
@ -123,6 +123,8 @@ DEFINE_STUB(spdk_bdev_get_block_size, uint32_t, (const struct spdk_bdev *bdev),
|
||||
DEFINE_STUB(spdk_bdev_get_num_blocks, uint64_t, (const struct spdk_bdev *bdev), 1024);
|
||||
|
||||
DEFINE_STUB(nvmf_ctrlr_async_event_ns_notice, int, (struct spdk_nvmf_ctrlr *ctrlr), 0);
|
||||
DEFINE_STUB(nvmf_ctrlr_async_event_ana_change_notice, int,
|
||||
(struct spdk_nvmf_ctrlr *ctrlr), 0);
|
||||
DEFINE_STUB_V(spdk_nvme_trid_populate_transport, (struct spdk_nvme_transport_id *trid,
|
||||
enum spdk_nvme_transport_type trtype));
|
||||
DEFINE_STUB_V(spdk_nvmf_ctrlr_data_init, (struct spdk_nvmf_transport_opts *opts,
|
||||
|
Loading…
Reference in New Issue
Block a user