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>
Change-Id: I4e2608a35d9dfa0395ad74fceebae9faf8cd973c
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/11399
Community-CI: Mellanox Build Bot
Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@mellanox.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Shuhei Matsumoto 2022-02-04 07:14:10 +09:00 committed by Jim Harris
parent c777cfa700
commit 79829ae40b

View File

@ -195,7 +195,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)
@ -957,8 +957,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)) {
bio->io_path->nvme_ns->ana_state_updating = true;
nvme_ctrlr_read_ana_log_page(nvme_ctrlr);
if (nvme_ctrlr_read_ana_log_page(nvme_ctrlr) == 0) {
bio->io_path->nvme_ns->ana_state_updating = true;
}
}
delay_ms = 0;
} else if (spdk_nvme_cpl_is_aborted_by_request(cpl)) {
@ -3120,6 +3121,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)
{
@ -3128,6 +3145,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,
@ -3136,20 +3155,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;
@ -3165,6 +3184,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