bdev/nvme: Set ana_state_updating only after starting read ANA log page

In a test case, test/nvmf/host/failover.sh, we got ANA error even if
the target did not enable ANA reporting.

We marked the corresponding namespace as ANA state updating but we had
no way to clear it.

Check if we can read ANA log page before setting the flag.

If read ANA log page failed, disable ANA feature until the nvme_ctrlr
is created again. In this operation, all ana_state_updating flags are
cleared.

Fixes #2335

Signed-off-by: Shuhei Matsumoto <smatsumoto@nvidia.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/11399 (master)

(cherry picked from commit 79829ae40b)
Change-Id: I4e2608a35d9dfa0395ad74fceebae9faf8cd973c
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/12466
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Shuhei Matsumoto <smatsumoto@nvidia.com>
This commit is contained in:
Shuhei Matsumoto 2022-02-04 07:14:10 +09:00 committed by Keith Lucas
parent e6668d8df6
commit c10889dc78

View File

@ -194,7 +194,7 @@ static void bdev_nvme_reset_io(struct nvme_bdev_channel *nbdev_ch, struct nvme_b
static int bdev_nvme_reset(struct nvme_ctrlr *nvme_ctrlr);
static int bdev_nvme_failover(struct nvme_ctrlr *nvme_ctrlr, bool remove);
static void remove_cb(void *cb_ctx, struct spdk_nvme_ctrlr *ctrlr);
static void nvme_ctrlr_read_ana_log_page(struct nvme_ctrlr *nvme_ctrlr);
static int nvme_ctrlr_read_ana_log_page(struct nvme_ctrlr *nvme_ctrlr);
static int
nvme_ns_cmp(struct nvme_ns *ns1, struct nvme_ns *ns2)
@ -956,8 +956,9 @@ bdev_nvme_io_complete_nvme_status(struct nvme_bdev_io *bio,
!nvme_ctrlr_is_available(nvme_ctrlr)) {
nbdev_ch->current_io_path = NULL;
if (spdk_nvme_cpl_is_ana_error(cpl)) {
if (nvme_ctrlr_read_ana_log_page(nvme_ctrlr) == 0) {
bio->io_path->nvme_ns->ana_state_updating = true;
nvme_ctrlr_read_ana_log_page(nvme_ctrlr);
}
}
delay_ms = 0;
} else if (spdk_nvme_cpl_is_aborted_by_request(cpl)) {
@ -3119,6 +3120,22 @@ bdev_nvme_clear_io_path_cache_done(struct spdk_io_channel_iter *i, int status)
nvme_ctrlr_unregister(nvme_ctrlr);
}
static void
bdev_nvme_disable_read_ana_log_page(struct nvme_ctrlr *nvme_ctrlr)
{
struct nvme_ns *nvme_ns;
free(nvme_ctrlr->ana_log_page);
nvme_ctrlr->ana_log_page = NULL;
for (nvme_ns = nvme_ctrlr_get_first_active_ns(nvme_ctrlr);
nvme_ns != NULL;
nvme_ns = nvme_ctrlr_get_next_active_ns(nvme_ctrlr, nvme_ns)) {
nvme_ns->ana_state_updating = false;
nvme_ns->ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE;
}
}
static void
nvme_ctrlr_read_ana_log_page_done(void *ctx, const struct spdk_nvme_cpl *cpl)
{
@ -3127,6 +3144,8 @@ nvme_ctrlr_read_ana_log_page_done(void *ctx, const struct spdk_nvme_cpl *cpl)
if (cpl != NULL && spdk_nvme_cpl_is_success(cpl)) {
bdev_nvme_parse_ana_log_page(nvme_ctrlr, nvme_ctrlr_set_ana_states,
nvme_ctrlr);
} else {
bdev_nvme_disable_read_ana_log_page(nvme_ctrlr);
}
spdk_for_each_channel(nvme_ctrlr,
@ -3135,20 +3154,20 @@ nvme_ctrlr_read_ana_log_page_done(void *ctx, const struct spdk_nvme_cpl *cpl)
bdev_nvme_clear_io_path_cache_done);
}
static void
static int
nvme_ctrlr_read_ana_log_page(struct nvme_ctrlr *nvme_ctrlr)
{
int rc;
if (nvme_ctrlr->ana_log_page == NULL) {
return;
return -EINVAL;
}
pthread_mutex_lock(&nvme_ctrlr->mutex);
if (!nvme_ctrlr_is_available(nvme_ctrlr) ||
nvme_ctrlr->ana_log_page_updating) {
pthread_mutex_unlock(&nvme_ctrlr->mutex);
return;
return -EBUSY;
}
nvme_ctrlr->ana_log_page_updating = true;
@ -3164,6 +3183,8 @@ nvme_ctrlr_read_ana_log_page(struct nvme_ctrlr *nvme_ctrlr)
if (rc != 0) {
nvme_ctrlr_read_ana_log_page_done(nvme_ctrlr, NULL);
}
return rc;
}
static void