nvme: detach the controller in STUB and flush the admin active requests at last

In the autotest, when calling kill_stub() function, there is error log
like this: "Device 0000:83:00.0 is still attached at shutdown!", so it's
better to detach the controller when exit the stub process.

But after call spdk_nvme_detach() in the stub process, there is another issue:
1. NVMe stub running as the primary process, and it will send 4 AERs.
2. Using NVMe reset tool as the secondary process.

When doing NVMe reset from the secondary process, it will abort all the
outstanding requests, so for the 4 AERs from the primary process, the 4
requests will be added to the active_proc->active_reqs list.

When calling spdk_nvme_detach() to detach a controller, there is a
assertion in the nvme_ctrlr_free_processes() at last to check the
active requests list of this active process data structure.

We can add a check before destructing the controller to poll the
completion queue, so that the active requests list can be flushed.

Change-Id: I0c473e935333a28d16f4c9fb443341fc47c5c24f
Signed-off-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/977
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
This commit is contained in:
Changpeng Liu 2020-02-24 01:02:27 -05:00 committed by Tomasz Zawadzki
parent 9c6d4649eb
commit bad2c8e86c
2 changed files with 35 additions and 0 deletions

View File

@ -2639,6 +2639,7 @@ nvme_ctrlr_destruct(struct spdk_nvme_ctrlr *ctrlr)
SPDK_DEBUGLOG(SPDK_LOG_NVME, "Prepare to destruct SSD: %s\n", ctrlr->trid.traddr);
spdk_nvme_qpair_process_completions(ctrlr->adminq, 0);
nvme_transport_admin_qpair_abort_aers(ctrlr->adminq);
TAILQ_FOREACH_SAFE(qpair, &ctrlr->active_io_qpairs, tailq, tmp) {

View File

@ -41,6 +41,27 @@
static char g_path[256];
static struct spdk_poller *g_poller;
struct ctrlr_entry {
struct spdk_nvme_ctrlr *ctrlr;
struct ctrlr_entry *next;
};
static struct ctrlr_entry *g_controllers = NULL;
static void
cleanup(void)
{
struct ctrlr_entry *ctrlr_entry = g_controllers;
while (ctrlr_entry) {
struct ctrlr_entry *next = ctrlr_entry->next;
spdk_nvme_detach(ctrlr_entry->ctrlr);
free(ctrlr_entry);
ctrlr_entry = next;
}
}
static void
usage(char *executable_name)
{
@ -70,6 +91,17 @@ static void
attach_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
struct spdk_nvme_ctrlr *ctrlr, const struct spdk_nvme_ctrlr_opts *opts)
{
struct ctrlr_entry *entry;
entry = malloc(sizeof(struct ctrlr_entry));
if (entry == NULL) {
fprintf(stderr, "Malloc error\n");
exit(1);
}
entry->ctrlr = ctrlr;
entry->next = g_controllers;
g_controllers = entry;
}
static int
@ -163,6 +195,8 @@ main(int argc, char **argv)
opts.shutdown_cb = stub_shutdown;
ch = spdk_app_start(&opts, stub_start, (void *)(intptr_t)opts.shm_id);
cleanup();
spdk_app_fini();
return ch;