lib/nvmf: add synchronization to subsystem state change.
This is important to avoid doubling up on state changes and hitting asserts. Signed-off-by: Seth Howell <seth.howell@intel.com> Change-Id: If8797ea13a5c224cee85e53e9b2542012423b37f Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/3759 Community-CI: Broadcom CI Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com> Reviewed-by: Aleksey Marchuk <alexeymar@mellanox.com>
This commit is contained in:
parent
bd16f57472
commit
8ff8bf0713
@ -488,11 +488,17 @@ static void
|
|||||||
nvmf_tgt_subsystem_stop_next(struct spdk_nvmf_subsystem *subsystem,
|
nvmf_tgt_subsystem_stop_next(struct spdk_nvmf_subsystem *subsystem,
|
||||||
void *cb_arg, int status)
|
void *cb_arg, int status)
|
||||||
{
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
subsystem = spdk_nvmf_subsystem_get_next(subsystem);
|
subsystem = spdk_nvmf_subsystem_get_next(subsystem);
|
||||||
if (subsystem) {
|
if (subsystem) {
|
||||||
spdk_nvmf_subsystem_stop(subsystem,
|
rc = spdk_nvmf_subsystem_stop(subsystem,
|
||||||
nvmf_tgt_subsystem_stop_next,
|
nvmf_tgt_subsystem_stop_next,
|
||||||
cb_arg);
|
cb_arg);
|
||||||
|
if (rc) {
|
||||||
|
nvmf_tgt_subsystem_stop_next(subsystem, cb_arg, 0);
|
||||||
|
fprintf(stderr, "Unable to stop NVMe-oF subsystem. Trying others.\n");
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -506,12 +512,17 @@ static void
|
|||||||
nvmf_tgt_stop_subsystems(struct nvmf_target *nvmf_tgt)
|
nvmf_tgt_stop_subsystems(struct nvmf_target *nvmf_tgt)
|
||||||
{
|
{
|
||||||
struct spdk_nvmf_subsystem *subsystem;
|
struct spdk_nvmf_subsystem *subsystem;
|
||||||
|
int rc;
|
||||||
|
|
||||||
subsystem = spdk_nvmf_subsystem_get_first(nvmf_tgt->tgt);
|
subsystem = spdk_nvmf_subsystem_get_first(nvmf_tgt->tgt);
|
||||||
if (spdk_likely(subsystem)) {
|
if (spdk_likely(subsystem)) {
|
||||||
spdk_nvmf_subsystem_stop(subsystem,
|
rc = spdk_nvmf_subsystem_stop(subsystem,
|
||||||
nvmf_tgt_subsystem_stop_next,
|
nvmf_tgt_subsystem_stop_next,
|
||||||
NULL);
|
NULL);
|
||||||
|
if (rc) {
|
||||||
|
nvmf_tgt_subsystem_stop_next(subsystem, NULL, 0);
|
||||||
|
fprintf(stderr, "Unable to stop NVMe-oF subsystem. Trying others.\n");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
g_target_state = NVMF_FINI_POLL_GROUPS;
|
g_target_state = NVMF_FINI_POLL_GROUPS;
|
||||||
}
|
}
|
||||||
@ -531,10 +542,17 @@ static void
|
|||||||
nvmf_tgt_subsystem_start_next(struct spdk_nvmf_subsystem *subsystem,
|
nvmf_tgt_subsystem_start_next(struct spdk_nvmf_subsystem *subsystem,
|
||||||
void *cb_arg, int status)
|
void *cb_arg, int status)
|
||||||
{
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
subsystem = spdk_nvmf_subsystem_get_next(subsystem);
|
subsystem = spdk_nvmf_subsystem_get_next(subsystem);
|
||||||
if (subsystem) {
|
if (subsystem) {
|
||||||
spdk_nvmf_subsystem_start(subsystem, nvmf_tgt_subsystem_start_next,
|
rc = spdk_nvmf_subsystem_start(subsystem, nvmf_tgt_subsystem_start_next,
|
||||||
cb_arg);
|
cb_arg);
|
||||||
|
if (rc) {
|
||||||
|
g_target_state = NVMF_FINI_STOP_SUBSYSTEMS;
|
||||||
|
fprintf(stderr, "Unable to start NVMe-oF subsystem. shutting down app.\n");
|
||||||
|
nvmf_target_advance_state();
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -548,6 +566,7 @@ static void
|
|||||||
nvmf_tgt_start_subsystems(struct nvmf_target *nvmf_tgt)
|
nvmf_tgt_start_subsystems(struct nvmf_target *nvmf_tgt)
|
||||||
{
|
{
|
||||||
struct spdk_nvmf_subsystem *subsystem;
|
struct spdk_nvmf_subsystem *subsystem;
|
||||||
|
int rc;
|
||||||
|
|
||||||
/* Subsystem is the NVM subsystem which is a combine of namespaces
|
/* Subsystem is the NVM subsystem which is a combine of namespaces
|
||||||
* except the discovery subsystem which is used for discovery service.
|
* except the discovery subsystem which is used for discovery service.
|
||||||
@ -560,9 +579,13 @@ nvmf_tgt_start_subsystems(struct nvmf_target *nvmf_tgt)
|
|||||||
* Start subsystem means make it from inactive to active that means
|
* Start subsystem means make it from inactive to active that means
|
||||||
* subsystem start to work or it can be accessed.
|
* subsystem start to work or it can be accessed.
|
||||||
*/
|
*/
|
||||||
spdk_nvmf_subsystem_start(subsystem,
|
rc = spdk_nvmf_subsystem_start(subsystem,
|
||||||
nvmf_tgt_subsystem_start_next,
|
nvmf_tgt_subsystem_start_next,
|
||||||
NULL);
|
NULL);
|
||||||
|
if (rc) {
|
||||||
|
fprintf(stderr, "Unable to start NVMe-oF subsystem. shutting down app.\n");
|
||||||
|
g_target_state = NVMF_FINI_STOP_SUBSYSTEMS;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
g_target_state = NVMF_INIT_START_ACCEPTOR;
|
g_target_state = NVMF_INIT_START_ACCEPTOR;
|
||||||
}
|
}
|
||||||
|
@ -260,6 +260,9 @@ struct spdk_nvmf_subsystem {
|
|||||||
char sn[SPDK_NVME_CTRLR_SN_LEN + 1];
|
char sn[SPDK_NVME_CTRLR_SN_LEN + 1];
|
||||||
char mn[SPDK_NVME_CTRLR_MN_LEN + 1];
|
char mn[SPDK_NVME_CTRLR_MN_LEN + 1];
|
||||||
|
|
||||||
|
/* boolean for state change synchronization. */
|
||||||
|
bool changing_state;
|
||||||
|
|
||||||
/* Array of pointers to namespaces of size max_nsid indexed by nsid - 1 */
|
/* Array of pointers to namespaces of size max_nsid indexed by nsid - 1 */
|
||||||
struct spdk_nvmf_ns **ns;
|
struct spdk_nvmf_ns **ns;
|
||||||
uint32_t max_nsid;
|
uint32_t max_nsid;
|
||||||
|
@ -496,6 +496,7 @@ rpc_nvmf_delete_subsystem(struct spdk_jsonrpc_request *request,
|
|||||||
struct rpc_delete_subsystem req = { 0 };
|
struct rpc_delete_subsystem req = { 0 };
|
||||||
struct spdk_nvmf_subsystem *subsystem;
|
struct spdk_nvmf_subsystem *subsystem;
|
||||||
struct spdk_nvmf_tgt *tgt;
|
struct spdk_nvmf_tgt *tgt;
|
||||||
|
int rc;
|
||||||
|
|
||||||
if (spdk_json_decode_object(params, rpc_delete_subsystem_decoders,
|
if (spdk_json_decode_object(params, rpc_delete_subsystem_decoders,
|
||||||
SPDK_COUNTOF(rpc_delete_subsystem_decoders),
|
SPDK_COUNTOF(rpc_delete_subsystem_decoders),
|
||||||
@ -523,9 +524,18 @@ rpc_nvmf_delete_subsystem(struct spdk_jsonrpc_request *request,
|
|||||||
|
|
||||||
free_rpc_delete_subsystem(&req);
|
free_rpc_delete_subsystem(&req);
|
||||||
|
|
||||||
spdk_nvmf_subsystem_stop(subsystem,
|
rc = spdk_nvmf_subsystem_stop(subsystem,
|
||||||
rpc_nvmf_subsystem_stopped,
|
rpc_nvmf_subsystem_stopped,
|
||||||
request);
|
request);
|
||||||
|
if (rc == -EBUSY) {
|
||||||
|
SPDK_ERRLOG("Subsystem currently in another state change try again later.\n");
|
||||||
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||||
|
"Subsystem currently in another state change try again later.");
|
||||||
|
} else if (rc != 0) {
|
||||||
|
SPDK_ERRLOG("Unable to change state on subsystem. rc=%d\n", rc);
|
||||||
|
spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||||
|
"Unable to change state on subsystem. rc=%d", rc);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -770,6 +780,7 @@ rpc_nvmf_subsystem_add_listener(struct spdk_jsonrpc_request *request,
|
|||||||
struct nvmf_rpc_listener_ctx *ctx;
|
struct nvmf_rpc_listener_ctx *ctx;
|
||||||
struct spdk_nvmf_subsystem *subsystem;
|
struct spdk_nvmf_subsystem *subsystem;
|
||||||
struct spdk_nvmf_tgt *tgt;
|
struct spdk_nvmf_tgt *tgt;
|
||||||
|
int rc;
|
||||||
|
|
||||||
ctx = calloc(1, sizeof(*ctx));
|
ctx = calloc(1, sizeof(*ctx));
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
@ -817,8 +828,14 @@ rpc_nvmf_subsystem_add_listener(struct spdk_jsonrpc_request *request,
|
|||||||
|
|
||||||
ctx->op = NVMF_RPC_LISTEN_ADD;
|
ctx->op = NVMF_RPC_LISTEN_ADD;
|
||||||
|
|
||||||
if (spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_listen_paused, ctx)) {
|
rc = spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_listen_paused, ctx);
|
||||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
|
if (rc != 0) {
|
||||||
|
if (rc == -EBUSY) {
|
||||||
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||||
|
"subsystem busy, retry later.\n");
|
||||||
|
} else {
|
||||||
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
|
||||||
|
}
|
||||||
nvmf_rpc_listener_ctx_free(ctx);
|
nvmf_rpc_listener_ctx_free(ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -832,6 +849,7 @@ rpc_nvmf_subsystem_remove_listener(struct spdk_jsonrpc_request *request,
|
|||||||
struct nvmf_rpc_listener_ctx *ctx;
|
struct nvmf_rpc_listener_ctx *ctx;
|
||||||
struct spdk_nvmf_subsystem *subsystem;
|
struct spdk_nvmf_subsystem *subsystem;
|
||||||
struct spdk_nvmf_tgt *tgt;
|
struct spdk_nvmf_tgt *tgt;
|
||||||
|
int rc;
|
||||||
|
|
||||||
ctx = calloc(1, sizeof(*ctx));
|
ctx = calloc(1, sizeof(*ctx));
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
@ -887,8 +905,14 @@ rpc_nvmf_subsystem_remove_listener(struct spdk_jsonrpc_request *request,
|
|||||||
|
|
||||||
ctx->op = NVMF_RPC_LISTEN_REMOVE;
|
ctx->op = NVMF_RPC_LISTEN_REMOVE;
|
||||||
|
|
||||||
if (spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_listen_paused, ctx)) {
|
rc = spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_listen_paused, ctx);
|
||||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
|
if (rc != 0) {
|
||||||
|
if (rc == -EBUSY) {
|
||||||
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||||
|
"subsystem busy, retry later.\n");
|
||||||
|
} else {
|
||||||
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
|
||||||
|
}
|
||||||
nvmf_rpc_listener_ctx_free(ctx);
|
nvmf_rpc_listener_ctx_free(ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1062,6 +1086,7 @@ rpc_nvmf_subsystem_add_ns(struct spdk_jsonrpc_request *request,
|
|||||||
struct nvmf_rpc_ns_ctx *ctx;
|
struct nvmf_rpc_ns_ctx *ctx;
|
||||||
struct spdk_nvmf_subsystem *subsystem;
|
struct spdk_nvmf_subsystem *subsystem;
|
||||||
struct spdk_nvmf_tgt *tgt;
|
struct spdk_nvmf_tgt *tgt;
|
||||||
|
int rc;
|
||||||
|
|
||||||
ctx = calloc(1, sizeof(*ctx));
|
ctx = calloc(1, sizeof(*ctx));
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
@ -1098,8 +1123,14 @@ rpc_nvmf_subsystem_add_ns(struct spdk_jsonrpc_request *request,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_ns_paused, ctx)) {
|
rc = spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_ns_paused, ctx);
|
||||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
|
if (rc != 0) {
|
||||||
|
if (rc == -EBUSY) {
|
||||||
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||||
|
"subsystem busy, retry later.\n");
|
||||||
|
} else {
|
||||||
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
|
||||||
|
}
|
||||||
nvmf_rpc_ns_ctx_free(ctx);
|
nvmf_rpc_ns_ctx_free(ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1178,6 +1209,7 @@ rpc_nvmf_subsystem_remove_ns(struct spdk_jsonrpc_request *request,
|
|||||||
struct nvmf_rpc_remove_ns_ctx *ctx;
|
struct nvmf_rpc_remove_ns_ctx *ctx;
|
||||||
struct spdk_nvmf_subsystem *subsystem;
|
struct spdk_nvmf_subsystem *subsystem;
|
||||||
struct spdk_nvmf_tgt *tgt;
|
struct spdk_nvmf_tgt *tgt;
|
||||||
|
int rc;
|
||||||
|
|
||||||
ctx = calloc(1, sizeof(*ctx));
|
ctx = calloc(1, sizeof(*ctx));
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
@ -1214,8 +1246,14 @@ rpc_nvmf_subsystem_remove_ns(struct spdk_jsonrpc_request *request,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_remove_ns_paused, ctx)) {
|
rc = spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_remove_ns_paused, ctx);
|
||||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
|
if (rc != 0) {
|
||||||
|
if (rc == -EBUSY) {
|
||||||
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||||
|
"subsystem busy, retry later.\n");
|
||||||
|
} else {
|
||||||
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
|
||||||
|
}
|
||||||
nvmf_rpc_remove_ns_ctx_free(ctx);
|
nvmf_rpc_remove_ns_ctx_free(ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1316,6 +1354,7 @@ rpc_nvmf_subsystem_add_host(struct spdk_jsonrpc_request *request,
|
|||||||
struct nvmf_rpc_host_ctx *ctx;
|
struct nvmf_rpc_host_ctx *ctx;
|
||||||
struct spdk_nvmf_subsystem *subsystem;
|
struct spdk_nvmf_subsystem *subsystem;
|
||||||
struct spdk_nvmf_tgt *tgt;
|
struct spdk_nvmf_tgt *tgt;
|
||||||
|
int rc;
|
||||||
|
|
||||||
ctx = calloc(1, sizeof(*ctx));
|
ctx = calloc(1, sizeof(*ctx));
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
@ -1353,8 +1392,14 @@ rpc_nvmf_subsystem_add_host(struct spdk_jsonrpc_request *request,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_host_paused, ctx)) {
|
rc = spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_host_paused, ctx);
|
||||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
|
if (rc != 0) {
|
||||||
|
if (rc == -EBUSY) {
|
||||||
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||||
|
"subsystem busy, retry later.\n");
|
||||||
|
} else {
|
||||||
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
|
||||||
|
}
|
||||||
nvmf_rpc_host_ctx_free(ctx);
|
nvmf_rpc_host_ctx_free(ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1367,6 +1412,7 @@ rpc_nvmf_subsystem_remove_host(struct spdk_jsonrpc_request *request,
|
|||||||
struct nvmf_rpc_host_ctx *ctx;
|
struct nvmf_rpc_host_ctx *ctx;
|
||||||
struct spdk_nvmf_subsystem *subsystem;
|
struct spdk_nvmf_subsystem *subsystem;
|
||||||
struct spdk_nvmf_tgt *tgt;
|
struct spdk_nvmf_tgt *tgt;
|
||||||
|
int rc;
|
||||||
|
|
||||||
ctx = calloc(1, sizeof(*ctx));
|
ctx = calloc(1, sizeof(*ctx));
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
@ -1404,8 +1450,14 @@ rpc_nvmf_subsystem_remove_host(struct spdk_jsonrpc_request *request,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_host_paused, ctx)) {
|
rc = spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_host_paused, ctx);
|
||||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
|
if (rc != 0) {
|
||||||
|
if (rc == -EBUSY) {
|
||||||
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||||
|
"subsystem busy, retry later.\n");
|
||||||
|
} else {
|
||||||
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
|
||||||
|
}
|
||||||
nvmf_rpc_host_ctx_free(ctx);
|
nvmf_rpc_host_ctx_free(ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1426,6 +1478,7 @@ rpc_nvmf_subsystem_allow_any_host(struct spdk_jsonrpc_request *request,
|
|||||||
struct nvmf_rpc_host_ctx *ctx;
|
struct nvmf_rpc_host_ctx *ctx;
|
||||||
struct spdk_nvmf_subsystem *subsystem;
|
struct spdk_nvmf_subsystem *subsystem;
|
||||||
struct spdk_nvmf_tgt *tgt;
|
struct spdk_nvmf_tgt *tgt;
|
||||||
|
int rc;
|
||||||
|
|
||||||
ctx = calloc(1, sizeof(*ctx));
|
ctx = calloc(1, sizeof(*ctx));
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
@ -1463,8 +1516,14 @@ rpc_nvmf_subsystem_allow_any_host(struct spdk_jsonrpc_request *request,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_host_paused, ctx)) {
|
rc = spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_host_paused, ctx);
|
||||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
|
if (rc != 0) {
|
||||||
|
if (rc == -EBUSY) {
|
||||||
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||||
|
"subsystem busy, retry later.\n");
|
||||||
|
} else {
|
||||||
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
|
||||||
|
}
|
||||||
nvmf_rpc_host_ctx_free(ctx);
|
nvmf_rpc_host_ctx_free(ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -478,6 +478,7 @@ subsystem_state_change_revert_done(struct spdk_io_channel_iter *i, int status)
|
|||||||
SPDK_ERRLOG("Unable to revert the subsystem state after operation failure.\n");
|
SPDK_ERRLOG("Unable to revert the subsystem state after operation failure.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx->subsystem->changing_state = false;
|
||||||
if (ctx->cb_fn) {
|
if (ctx->cb_fn) {
|
||||||
/* return a failure here. This function only exists in an error path. */
|
/* return a failure here. This function only exists in an error path. */
|
||||||
ctx->cb_fn(ctx->subsystem, ctx->cb_arg, -1);
|
ctx->cb_fn(ctx->subsystem, ctx->cb_arg, -1);
|
||||||
@ -515,6 +516,7 @@ subsystem_state_change_done(struct spdk_io_channel_iter *i, int status)
|
|||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
ctx->subsystem->changing_state = false;
|
||||||
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);
|
||||||
}
|
}
|
||||||
@ -569,11 +571,16 @@ nvmf_subsystem_state_change(struct spdk_nvmf_subsystem *subsystem,
|
|||||||
enum spdk_nvmf_subsystem_state intermediate_state;
|
enum spdk_nvmf_subsystem_state intermediate_state;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
if (__sync_val_compare_and_swap(&subsystem->changing_state, false, true)) {
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
intermediate_state = nvmf_subsystem_get_intermediate_state(subsystem->state, requested_state);
|
intermediate_state = nvmf_subsystem_get_intermediate_state(subsystem->state, requested_state);
|
||||||
assert(intermediate_state != SPDK_NVMF_SUBSYSTEM_NUM_STATES);
|
assert(intermediate_state != SPDK_NVMF_SUBSYSTEM_NUM_STATES);
|
||||||
|
|
||||||
ctx = calloc(1, sizeof(*ctx));
|
ctx = calloc(1, sizeof(*ctx));
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
|
subsystem->changing_state = false;
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -581,6 +588,7 @@ nvmf_subsystem_state_change(struct spdk_nvmf_subsystem *subsystem,
|
|||||||
rc = nvmf_subsystem_set_state(subsystem, intermediate_state);
|
rc = nvmf_subsystem_set_state(subsystem, intermediate_state);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
free(ctx);
|
free(ctx);
|
||||||
|
subsystem->changing_state = false;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1060,51 +1068,118 @@ spdk_nvmf_subsystem_remove_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t ns
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct subsystem_ns_change_ctx {
|
||||||
|
struct spdk_nvmf_subsystem *subsystem;
|
||||||
|
spdk_nvmf_subsystem_state_change_done cb_fn;
|
||||||
|
uint32_t nsid;
|
||||||
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_nvmf_ns_hot_remove(struct spdk_nvmf_subsystem *subsystem,
|
_nvmf_ns_hot_remove(struct spdk_nvmf_subsystem *subsystem,
|
||||||
void *cb_arg, int status)
|
void *cb_arg, int status)
|
||||||
{
|
{
|
||||||
struct spdk_nvmf_ns *ns = cb_arg;
|
struct subsystem_ns_change_ctx *ctx = cb_arg;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = spdk_nvmf_subsystem_remove_ns(subsystem, ns->opts.nsid);
|
rc = spdk_nvmf_subsystem_remove_ns(subsystem, ctx->nsid);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
SPDK_ERRLOG("Failed to make changes to NVME-oF subsystem with id: %u\n", subsystem->id);
|
SPDK_ERRLOG("Failed to make changes to NVME-oF subsystem with id: %u\n", subsystem->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
spdk_nvmf_subsystem_resume(subsystem, NULL, NULL);
|
spdk_nvmf_subsystem_resume(subsystem, NULL, NULL);
|
||||||
|
|
||||||
|
free(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
nvmf_ns_change_msg(void *ns_ctx)
|
||||||
|
{
|
||||||
|
struct subsystem_ns_change_ctx *ctx = ns_ctx;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = spdk_nvmf_subsystem_pause(ctx->subsystem, ctx->cb_fn, ctx);
|
||||||
|
if (rc) {
|
||||||
|
if (rc == -EBUSY) {
|
||||||
|
/* Try again, this is not a permanent situation. */
|
||||||
|
spdk_thread_send_msg(spdk_get_thread(), nvmf_ns_change_msg, ctx);
|
||||||
|
} else {
|
||||||
|
free(ctx);
|
||||||
|
SPDK_ERRLOG("Unable to pause subsystem to process namespace removal!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
nvmf_ns_hot_remove(void *remove_ctx)
|
nvmf_ns_hot_remove(void *remove_ctx)
|
||||||
{
|
{
|
||||||
struct spdk_nvmf_ns *ns = remove_ctx;
|
struct spdk_nvmf_ns *ns = remove_ctx;
|
||||||
|
struct subsystem_ns_change_ctx *ns_ctx;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = spdk_nvmf_subsystem_pause(ns->subsystem, _nvmf_ns_hot_remove, ns);
|
/* We have to allocate a new context because this op
|
||||||
|
* is asynchronous and we could lose the ns in the middle.
|
||||||
|
*/
|
||||||
|
ns_ctx = calloc(1, sizeof(struct subsystem_ns_change_ctx));
|
||||||
|
if (!ns_ctx) {
|
||||||
|
SPDK_ERRLOG("Unable to allocate context to process namespace removal!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ns_ctx->subsystem = ns->subsystem;
|
||||||
|
ns_ctx->nsid = ns->opts.nsid;
|
||||||
|
ns_ctx->cb_fn = _nvmf_ns_hot_remove;
|
||||||
|
|
||||||
|
rc = spdk_nvmf_subsystem_pause(ns->subsystem, _nvmf_ns_hot_remove, ns_ctx);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
SPDK_ERRLOG("Unable to pause subsystem to process namespace removal!\n");
|
if (rc == -EBUSY) {
|
||||||
|
/* Try again, this is not a permanent situation. */
|
||||||
|
spdk_thread_send_msg(spdk_get_thread(), nvmf_ns_change_msg, ns_ctx);
|
||||||
|
} else {
|
||||||
|
SPDK_ERRLOG("Unable to pause subsystem to process namespace removal!\n");
|
||||||
|
free(ns_ctx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_nvmf_ns_resize(struct spdk_nvmf_subsystem *subsystem, void *cb_arg, int status)
|
_nvmf_ns_resize(struct spdk_nvmf_subsystem *subsystem, void *cb_arg, int status)
|
||||||
{
|
{
|
||||||
struct spdk_nvmf_ns *ns = cb_arg;
|
struct subsystem_ns_change_ctx *ctx = cb_arg;
|
||||||
|
|
||||||
nvmf_subsystem_ns_changed(subsystem, ns->opts.nsid);
|
nvmf_subsystem_ns_changed(subsystem, ctx->nsid);
|
||||||
spdk_nvmf_subsystem_resume(subsystem, NULL, NULL);
|
spdk_nvmf_subsystem_resume(subsystem, NULL, NULL);
|
||||||
|
|
||||||
|
free(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
nvmf_ns_resize(void *event_ctx)
|
nvmf_ns_resize(void *event_ctx)
|
||||||
{
|
{
|
||||||
struct spdk_nvmf_ns *ns = event_ctx;
|
struct spdk_nvmf_ns *ns = event_ctx;
|
||||||
|
struct subsystem_ns_change_ctx *ns_ctx;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = spdk_nvmf_subsystem_pause(ns->subsystem, _nvmf_ns_resize, ns);
|
/* We have to allocate a new context because this op
|
||||||
|
* is asynchronous and we could lose the ns in the middle.
|
||||||
|
*/
|
||||||
|
ns_ctx = calloc(1, sizeof(struct subsystem_ns_change_ctx));
|
||||||
|
if (!ns_ctx) {
|
||||||
|
SPDK_ERRLOG("Unable to allocate context to process namespace removal!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ns_ctx->subsystem = ns->subsystem;
|
||||||
|
ns_ctx->nsid = ns->opts.nsid;
|
||||||
|
ns_ctx->cb_fn = _nvmf_ns_resize;
|
||||||
|
|
||||||
|
rc = spdk_nvmf_subsystem_pause(ns->subsystem, _nvmf_ns_resize, ns_ctx);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
|
if (rc == -EBUSY) {
|
||||||
|
/* Try again, this is not a permanent situation. */
|
||||||
|
spdk_thread_send_msg(spdk_get_thread(), nvmf_ns_change_msg, ns_ctx);
|
||||||
|
}
|
||||||
SPDK_ERRLOG("Unable to pause subsystem to process namespace resize!\n");
|
SPDK_ERRLOG("Unable to pause subsystem to process namespace resize!\n");
|
||||||
|
free(ns_ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,9 +224,15 @@ nvmf_tgt_subsystem_started(struct spdk_nvmf_subsystem *subsystem,
|
|||||||
void *cb_arg, int status)
|
void *cb_arg, int status)
|
||||||
{
|
{
|
||||||
subsystem = spdk_nvmf_subsystem_get_next(subsystem);
|
subsystem = spdk_nvmf_subsystem_get_next(subsystem);
|
||||||
|
int rc;
|
||||||
|
|
||||||
if (subsystem) {
|
if (subsystem) {
|
||||||
spdk_nvmf_subsystem_start(subsystem, nvmf_tgt_subsystem_started, NULL);
|
rc = spdk_nvmf_subsystem_start(subsystem, nvmf_tgt_subsystem_started, NULL);
|
||||||
|
if (rc) {
|
||||||
|
g_tgt_state = NVMF_TGT_FINI_STOP_SUBSYSTEMS;
|
||||||
|
SPDK_ERRLOG("Unable to start NVMe-oF subsystem. Stopping app.\n");
|
||||||
|
nvmf_tgt_advance_state();
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,9 +245,14 @@ nvmf_tgt_subsystem_stopped(struct spdk_nvmf_subsystem *subsystem,
|
|||||||
void *cb_arg, int status)
|
void *cb_arg, int status)
|
||||||
{
|
{
|
||||||
subsystem = spdk_nvmf_subsystem_get_next(subsystem);
|
subsystem = spdk_nvmf_subsystem_get_next(subsystem);
|
||||||
|
int rc;
|
||||||
|
|
||||||
if (subsystem) {
|
if (subsystem) {
|
||||||
spdk_nvmf_subsystem_stop(subsystem, nvmf_tgt_subsystem_stopped, NULL);
|
rc = spdk_nvmf_subsystem_stop(subsystem, nvmf_tgt_subsystem_stopped, NULL);
|
||||||
|
if (rc) {
|
||||||
|
SPDK_ERRLOG("Unable to stop NVMe-oF subsystem. Trying others.\n");
|
||||||
|
nvmf_tgt_subsystem_stopped(subsystem, NULL, 0);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,6 +367,7 @@ nvmf_tgt_advance_state(void)
|
|||||||
{
|
{
|
||||||
enum nvmf_tgt_state prev_state;
|
enum nvmf_tgt_state prev_state;
|
||||||
int rc = -1;
|
int rc = -1;
|
||||||
|
int ret;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
prev_state = g_tgt_state;
|
prev_state = g_tgt_state;
|
||||||
@ -388,7 +400,11 @@ nvmf_tgt_advance_state(void)
|
|||||||
subsystem = spdk_nvmf_subsystem_get_first(g_spdk_nvmf_tgt);
|
subsystem = spdk_nvmf_subsystem_get_first(g_spdk_nvmf_tgt);
|
||||||
|
|
||||||
if (subsystem) {
|
if (subsystem) {
|
||||||
spdk_nvmf_subsystem_start(subsystem, nvmf_tgt_subsystem_started, NULL);
|
ret = spdk_nvmf_subsystem_start(subsystem, nvmf_tgt_subsystem_started, NULL);
|
||||||
|
if (ret) {
|
||||||
|
SPDK_ERRLOG("Unable to start NVMe-oF subsystem. Stopping app.\n");
|
||||||
|
g_tgt_state = NVMF_TGT_FINI_STOP_SUBSYSTEMS;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
g_tgt_state = NVMF_TGT_INIT_START_ACCEPTOR;
|
g_tgt_state = NVMF_TGT_INIT_START_ACCEPTOR;
|
||||||
}
|
}
|
||||||
@ -408,7 +424,10 @@ nvmf_tgt_advance_state(void)
|
|||||||
subsystem = spdk_nvmf_subsystem_get_first(g_spdk_nvmf_tgt);
|
subsystem = spdk_nvmf_subsystem_get_first(g_spdk_nvmf_tgt);
|
||||||
|
|
||||||
if (subsystem) {
|
if (subsystem) {
|
||||||
spdk_nvmf_subsystem_stop(subsystem, nvmf_tgt_subsystem_stopped, NULL);
|
ret = spdk_nvmf_subsystem_stop(subsystem, nvmf_tgt_subsystem_stopped, NULL);
|
||||||
|
if (ret) {
|
||||||
|
nvmf_tgt_subsystem_stopped(subsystem, NULL, 0);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
g_tgt_state = NVMF_TGT_FINI_DESTROY_POLL_GROUPS;
|
g_tgt_state = NVMF_TGT_FINI_DESTROY_POLL_GROUPS;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user