bdev/nvme: Add support for hotplug in bdev/nvme layer.

Change-Id: I4decd60fdb065a1865519013f47b6c32111fa5c4
Signed-off-by: cunyinch <cunyin.chang@intel.com>
This commit is contained in:
cunyinch 2017-03-01 09:23:53 +08:00 committed by Cunyin Chang
parent 77183f9722
commit c932e122b7

View File

@ -68,8 +68,8 @@ struct nvme_ctrlr {
/** linked list pointer for device list */
TAILQ_ENTRY(nvme_ctrlr) tailq;
int id;
int ref;
};
struct nvme_bdev {
@ -116,6 +116,10 @@ static int num_controllers = -1;
static int g_reset_controller_on_timeout = 0;
static int g_timeout = 0;
static int g_nvme_adminq_poll_timeout_us = 0;
static int g_nvme_hotplug_poll_timeout_us = 0;
static int g_nvme_hotplug_poll_core = 0;
static struct spdk_poller *g_hotplug_poller;
static pthread_mutex_t g_bdev_nvme_mutex = PTHREAD_MUTEX_INITIALIZER;
static TAILQ_HEAD(, nvme_ctrlr) g_nvme_ctrlrs = TAILQ_HEAD_INITIALIZER(g_nvme_ctrlrs);
static TAILQ_HEAD(, nvme_bdev) g_nvme_bdevs = TAILQ_HEAD_INITIALIZER(g_nvme_bdevs);
@ -195,7 +199,32 @@ bdev_nvme_poll_adminq(void *arg)
static int
bdev_nvme_destruct(struct spdk_bdev *bdev)
{
bool removable = true;
struct nvme_bdev *nvme_disk = (struct nvme_bdev *)bdev;
struct nvme_ctrlr *nvme_ctrlr = nvme_disk->nvme_ctrlr;
pthread_mutex_lock(&g_bdev_nvme_mutex);
nvme_ctrlr->ref--;
if (nvme_ctrlr->ref != 0) {
removable = false;
}
free(nvme_disk);
if (removable == true) {
TAILQ_REMOVE(&g_nvme_ctrlrs, nvme_ctrlr, tailq);
pthread_mutex_unlock(&g_bdev_nvme_mutex);
spdk_io_device_unregister(nvme_ctrlr->ctrlr);
spdk_poller_unregister(&nvme_ctrlr->adminq_timer_poller, NULL);
spdk_nvme_detach(nvme_ctrlr->ctrlr);
free(nvme_ctrlr);
return 0;
}
pthread_mutex_unlock(&g_bdev_nvme_mutex);
return 0;
}
static int
@ -459,6 +488,15 @@ static const struct spdk_bdev_fn_table nvmelib_fn_table = {
.dump_config_json = bdev_nvme_dump_config_json,
};
static bool
hotplug_probe_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
struct spdk_nvme_ctrlr_opts *opts)
{
SPDK_NOTICELOG("Attaching to %s\n", trid->traddr);
return true;
}
static bool
probe_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
struct spdk_nvme_ctrlr_opts *opts)
@ -532,6 +570,7 @@ attach_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
dev->adminq_timer_poller = NULL;
dev->ctrlr = ctrlr;
dev->ref = 0;
spdk_pci_addr_parse(&dev->pci_addr, trid->traddr);
dev->id = nvme_controller_index++;
@ -564,6 +603,42 @@ nvme_ctrlr_get(struct spdk_pci_addr *addr)
return NULL;
}
static void
remove_cb(void *cb_ctx, struct spdk_nvme_ctrlr *ctrlr)
{
struct nvme_ctrlr *nvme_ctrlr;
struct nvme_bdev *nvme_bdev, *btmp;
TAILQ_HEAD(, nvme_bdev) nvme_bdevs;
TAILQ_INIT(&nvme_bdevs);
pthread_mutex_lock(&g_bdev_nvme_mutex);
TAILQ_FOREACH(nvme_ctrlr, &g_nvme_ctrlrs, tailq) {
if (nvme_ctrlr->ctrlr == ctrlr) {
TAILQ_FOREACH_SAFE(nvme_bdev, &g_nvme_bdevs, link, btmp) {
if (nvme_bdev->nvme_ctrlr == nvme_ctrlr) {
TAILQ_REMOVE(&g_nvme_bdevs, nvme_bdev, link);
TAILQ_INSERT_TAIL(&nvme_bdevs, nvme_bdev, link);
}
}
break;
}
}
pthread_mutex_unlock(&g_bdev_nvme_mutex);
TAILQ_FOREACH_SAFE(nvme_bdev, &nvme_bdevs, link, btmp) {
TAILQ_REMOVE(&nvme_bdevs, nvme_bdev, link);
spdk_bdev_unregister(&nvme_bdev->disk);
}
}
static void
blockdev_nvme_hotplug(void *arg)
{
if (spdk_nvme_probe(NULL, NULL, hotplug_probe_cb, attach_cb, remove_cb) != 0) {
SPDK_ERRLOG("spdk_nvme_probe() failed\n");
}
}
int
spdk_bdev_nvme_create(struct spdk_nvme_transport_id *trid,
const char **names, size_t *count)
@ -678,29 +753,34 @@ bdev_nvme_library_init(void)
g_nvme_adminq_poll_timeout_us = 1000000;
}
g_nvme_hotplug_poll_timeout_us = spdk_conf_section_get_intval(sp, "HotplugPollRate");
if (g_nvme_hotplug_poll_timeout_us <= 0 || g_nvme_hotplug_poll_timeout_us > 100000) {
g_nvme_hotplug_poll_timeout_us = 100000;
}
g_nvme_hotplug_poll_core = spdk_conf_section_get_intval(sp, "HotplugPollCore");
if (g_nvme_hotplug_poll_core <= 0) {
g_nvme_hotplug_poll_core = spdk_app_get_current_core();
}
if (spdk_nvme_probe(NULL, &probe_ctx, probe_cb, attach_cb, NULL)) {
return -1;
}
spdk_poller_register(&g_hotplug_poller, blockdev_nvme_hotplug, NULL,
g_nvme_hotplug_poll_core, g_nvme_hotplug_poll_timeout_us);
return 0;
}
static void
bdev_nvme_library_fini(void)
{
struct nvme_ctrlr *nvme_ctrlr, *ctmp;
struct nvme_bdev *nvme_bdev, *btmp;
TAILQ_FOREACH_SAFE(nvme_bdev, &g_nvme_bdevs, link, btmp) {
TAILQ_REMOVE(&g_nvme_bdevs, nvme_bdev, link);
free(nvme_bdev);
}
TAILQ_FOREACH_SAFE(nvme_ctrlr, &g_nvme_ctrlrs, tailq, ctmp) {
TAILQ_REMOVE(&g_nvme_ctrlrs, nvme_ctrlr, tailq);
spdk_poller_unregister(&nvme_ctrlr->adminq_timer_poller, NULL);
spdk_nvme_detach(nvme_ctrlr->ctrlr);
free(nvme_ctrlr);
bdev_nvme_destruct(&nvme_bdev->disk);
}
}
@ -731,6 +811,7 @@ nvme_ctrlr_create_bdevs(struct nvme_ctrlr *nvme_ctrlr, int ctrlr_id)
bdev->nvme_ctrlr = nvme_ctrlr;
bdev->ns = ns;
nvme_ctrlr->ref++;
snprintf(bdev->disk.name, SPDK_BDEV_MAX_NAME_LENGTH,
"Nvme%dn%d", ctrlr_id, spdk_nvme_ns_get_id(ns));