nvmf/subsystem: New path when we fail to change the subsystem state.
This can happen and we should be prepared for it. Maybe fixes: issue #1416 Signed-off-by: Seth Howell <seth.howell@intel.com> Change-Id: I77f48dbcabf702f88df56ad7e866bbcb830fc239 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/3393 Community-CI: Mellanox Build Bot 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: Michael Haeuptle <michaelhaeuptle@gmail.com> Reviewed-by: Aleksey Marchuk <alexeymar@mellanox.com>
This commit is contained in:
parent
d8190d0288
commit
1e337a1eb2
@ -1386,7 +1386,9 @@ nvmf_poll_group_pause_subsystem(struct spdk_nvmf_poll_group *group,
|
|||||||
goto fini;
|
goto fini;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(sgroup->state == SPDK_NVMF_SUBSYSTEM_ACTIVE);
|
if (sgroup->state == SPDK_NVMF_SUBSYSTEM_PAUSED) {
|
||||||
|
goto fini;
|
||||||
|
}
|
||||||
sgroup->state = SPDK_NVMF_SUBSYSTEM_PAUSING;
|
sgroup->state = SPDK_NVMF_SUBSYSTEM_PAUSING;
|
||||||
|
|
||||||
if (sgroup->io_outstanding > 0) {
|
if (sgroup->io_outstanding > 0) {
|
||||||
@ -1419,7 +1421,9 @@ nvmf_poll_group_resume_subsystem(struct spdk_nvmf_poll_group *group,
|
|||||||
|
|
||||||
sgroup = &group->sgroups[subsystem->id];
|
sgroup = &group->sgroups[subsystem->id];
|
||||||
|
|
||||||
assert(sgroup->state == SPDK_NVMF_SUBSYSTEM_PAUSED);
|
if (sgroup->state == SPDK_NVMF_SUBSYSTEM_ACTIVE) {
|
||||||
|
goto fini;
|
||||||
|
}
|
||||||
|
|
||||||
rc = poll_group_update_subsystem(group, subsystem);
|
rc = poll_group_update_subsystem(group, subsystem);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
|
@ -232,6 +232,8 @@ nvmf_valid_nqn(const char *nqn)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void subsystem_state_change_on_pg(struct spdk_io_channel_iter *i);
|
||||||
|
|
||||||
struct spdk_nvmf_subsystem *
|
struct spdk_nvmf_subsystem *
|
||||||
spdk_nvmf_subsystem_create(struct spdk_nvmf_tgt *tgt,
|
spdk_nvmf_subsystem_create(struct spdk_nvmf_tgt *tgt,
|
||||||
const char *nqn,
|
const char *nqn,
|
||||||
@ -442,6 +444,11 @@ nvmf_subsystem_set_state(struct spdk_nvmf_subsystem *subsystem,
|
|||||||
state == SPDK_NVMF_SUBSYSTEM_DEACTIVATING) {
|
state == SPDK_NVMF_SUBSYSTEM_DEACTIVATING) {
|
||||||
expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVATING;
|
expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVATING;
|
||||||
}
|
}
|
||||||
|
/* This is for the case when resuming the subsystem fails. */
|
||||||
|
if (actual_old_state == SPDK_NVMF_SUBSYSTEM_RESUMING &&
|
||||||
|
state == SPDK_NVMF_SUBSYSTEM_PAUSING) {
|
||||||
|
expected_old_state = SPDK_NVMF_SUBSYSTEM_RESUMING;
|
||||||
|
}
|
||||||
actual_old_state = expected_old_state;
|
actual_old_state = expected_old_state;
|
||||||
__atomic_compare_exchange_n(&subsystem->state, &actual_old_state, state, false,
|
__atomic_compare_exchange_n(&subsystem->state, &actual_old_state, state, false,
|
||||||
__ATOMIC_RELAXED, __ATOMIC_RELAXED);
|
__ATOMIC_RELAXED, __ATOMIC_RELAXED);
|
||||||
@ -453,16 +460,36 @@ nvmf_subsystem_set_state(struct spdk_nvmf_subsystem *subsystem,
|
|||||||
struct subsystem_state_change_ctx {
|
struct subsystem_state_change_ctx {
|
||||||
struct spdk_nvmf_subsystem *subsystem;
|
struct spdk_nvmf_subsystem *subsystem;
|
||||||
|
|
||||||
|
enum spdk_nvmf_subsystem_state original_state;
|
||||||
|
|
||||||
enum spdk_nvmf_subsystem_state requested_state;
|
enum spdk_nvmf_subsystem_state requested_state;
|
||||||
|
|
||||||
spdk_nvmf_subsystem_state_change_done cb_fn;
|
spdk_nvmf_subsystem_state_change_done cb_fn;
|
||||||
void *cb_arg;
|
void *cb_arg;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
subsystem_state_change_revert_done(struct spdk_io_channel_iter *i, int status)
|
||||||
|
{
|
||||||
|
struct subsystem_state_change_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
|
||||||
|
|
||||||
|
/* Nothing to be done here if the state setting fails, we are just screwed. */
|
||||||
|
if (nvmf_subsystem_set_state(ctx->subsystem, ctx->requested_state)) {
|
||||||
|
SPDK_ERRLOG("Unable to revert the subsystem state after operation failure.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->cb_fn) {
|
||||||
|
/* return a failure here. This function only exists in an error path. */
|
||||||
|
ctx->cb_fn(ctx->subsystem, ctx->cb_arg, -1);
|
||||||
|
}
|
||||||
|
free(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
subsystem_state_change_done(struct spdk_io_channel_iter *i, int status)
|
subsystem_state_change_done(struct spdk_io_channel_iter *i, int status)
|
||||||
{
|
{
|
||||||
struct subsystem_state_change_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
|
struct subsystem_state_change_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
|
||||||
|
enum spdk_nvmf_subsystem_state intermediate_state;
|
||||||
|
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
status = nvmf_subsystem_set_state(ctx->subsystem, ctx->requested_state);
|
status = nvmf_subsystem_set_state(ctx->subsystem, ctx->requested_state);
|
||||||
@ -471,6 +498,23 @@ subsystem_state_change_done(struct spdk_io_channel_iter *i, int status)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (status) {
|
||||||
|
intermediate_state = nvmf_subsystem_get_intermediate_state(ctx->requested_state,
|
||||||
|
ctx->original_state);
|
||||||
|
assert(intermediate_state != SPDK_NVMF_SUBSYSTEM_NUM_STATES);
|
||||||
|
|
||||||
|
if (nvmf_subsystem_set_state(ctx->subsystem, intermediate_state)) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
ctx->requested_state = ctx->original_state;
|
||||||
|
spdk_for_each_channel(ctx->subsystem->tgt,
|
||||||
|
subsystem_state_change_on_pg,
|
||||||
|
ctx,
|
||||||
|
subsystem_state_change_revert_done);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
if (ctx->cb_fn) {
|
if (ctx->cb_fn) {
|
||||||
ctx->cb_fn(ctx->subsystem, ctx->cb_arg, status);
|
ctx->cb_fn(ctx->subsystem, ctx->cb_arg, status);
|
||||||
}
|
}
|
||||||
@ -526,15 +570,14 @@ nvmf_subsystem_state_change(struct spdk_nvmf_subsystem *subsystem,
|
|||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
intermediate_state = nvmf_subsystem_get_intermediate_state(subsystem->state, requested_state);
|
intermediate_state = nvmf_subsystem_get_intermediate_state(subsystem->state, requested_state);
|
||||||
if (intermediate_state == SPDK_NVMF_SUBSYSTEM_NUM_STATES) {
|
assert(intermediate_state != SPDK_NVMF_SUBSYSTEM_NUM_STATES);
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx = calloc(1, sizeof(*ctx));
|
ctx = calloc(1, sizeof(*ctx));
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx->original_state = subsystem->state;
|
||||||
rc = nvmf_subsystem_set_state(subsystem, intermediate_state);
|
rc = nvmf_subsystem_set_state(subsystem, intermediate_state);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
free(ctx);
|
free(ctx);
|
||||||
|
Loading…
Reference in New Issue
Block a user