ocf: multicore support

This patch adds support for many-to-one configuration
  for OCF bdev. Meaning that one cache instance can
  be used to cache multiple core devices.

Without this change, it is not possible
  to attach core device to existing cache instance.

Change-Id: Idfce023c08b6d41490d590a8abb51f626252cd4d
Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/444277
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
This commit is contained in:
Vitaliy Mysak 2019-02-11 17:26:31 +00:00 committed by Jim Harris
parent 5d82fa6af7
commit 97d1311fb0
2 changed files with 102 additions and 9 deletions

View File

@ -68,6 +68,47 @@ free_vbdev(struct vbdev_ocf *vbdev)
free(vbdev);
}
/* Get existing cache base
* that is attached to other vbdev */
static struct vbdev_ocf_base *
get_other_cache_base(struct vbdev_ocf_base *base)
{
struct vbdev_ocf *vbdev;
TAILQ_FOREACH(vbdev, &g_ocf_vbdev_head, tailq) {
if (&vbdev->cache == base || !vbdev->cache.attached) {
continue;
}
if (!strcmp(vbdev->cache.name, base->name)) {
return &vbdev->cache;
}
}
return NULL;
}
/* Get existing OCF cache instance
* that is started by other vbdev */
static ocf_cache_t
get_other_cache_instance(struct vbdev_ocf *vbdev)
{
struct vbdev_ocf *cmp;
TAILQ_FOREACH(cmp, &g_ocf_vbdev_head, tailq) {
if (cmp->state.doing_finish || cmp == vbdev) {
continue;
}
if (strcmp(cmp->cache.name, vbdev->cache.name)) {
continue;
}
if (cmp->ocf_cache) {
return cmp->ocf_cache;
}
}
return NULL;
}
/* Stop OCF cache object
* vbdev_ocf is not operational after this */
static int
@ -87,6 +128,13 @@ stop_vbdev(struct vbdev_ocf *vbdev)
return -EINVAL;
}
if (get_other_cache_instance(vbdev)) {
SPDK_NOTICELOG("Not stopping cache instance '%s'"
" because it is referenced by other OCF bdev\n",
vbdev->cache.name);
return 0;
}
rc = ocf_mngt_cache_lock(vbdev->ocf_cache);
if (rc) {
return rc;
@ -119,6 +167,11 @@ remove_base(struct vbdev_ocf_base *base)
assert(base->attached);
if (base->is_cache && get_other_cache_base(base)) {
base->attached = false;
return 0;
}
/* Release OCF-part */
if (base->parent->ocf_cache && ocf_cache_is_running(base->parent->ocf_cache)) {
if (base->is_cache) {
@ -474,8 +527,21 @@ static struct spdk_bdev_fn_table cache_dev_fn_table = {
static int
start_cache(struct vbdev_ocf *vbdev)
{
ocf_cache_t existing;
int rc;
if (vbdev->ocf_cache) {
return -EALREADY;
}
existing = get_other_cache_instance(vbdev);
if (existing) {
SPDK_NOTICELOG("OCF bdev %s connects to existing cache device %s\n",
vbdev->name, vbdev->cache.name);
vbdev->ocf_cache = existing;
return 0;
}
rc = ocf_mngt_cache_start(vbdev_ocf_ctx, &vbdev->ocf_cache, &vbdev->cfg.cache);
if (rc) {
SPDK_ERRLOG("Failed to start cache instance\n");
@ -678,6 +744,7 @@ init_vbdev_config(struct vbdev_ocf *vbdev)
cfg->core.volume_type = SPDK_OBJECT;
cfg->device.volume_type = SPDK_OBJECT;
cfg->core.core_id = OCF_CORE_MAX;
cfg->device.uuid.size = strlen(vbdev->cache.name) + 1;
cfg->device.uuid.data = vbdev->cache.name;
@ -832,21 +899,36 @@ vbdev_ocf_module_fini(void)
}
/* When base device gets unpluged this is called
* We will unregister cache vbdev here */
* We will unregister cache vbdev here
* When cache device is removed, we delete every OCF bdev that used it */
static void
hotremove_cb(void *ctx)
{
struct vbdev_ocf_base *base = ctx;
struct spdk_bdev *bdev = base->bdev;
struct vbdev_ocf *vbdev;
if (base->parent->state.doing_finish) {
if (!base->is_cache) {
if (base->parent->state.doing_finish) {
return;
}
SPDK_NOTICELOG("Deinitializing '%s' because its core device '%s' was removed\n",
base->parent->name, base->name);
vbdev_ocf_delete(base->parent);
return;
}
SPDK_NOTICELOG("Deinitializing '%s' because its %s device '%s' was removed\n",
base->parent->name, base->is_cache ? "cache" : "core", bdev->name);
vbdev_ocf_delete(base->parent);
TAILQ_FOREACH(vbdev, &g_ocf_vbdev_head, tailq) {
if (vbdev->state.doing_finish) {
continue;
}
if (strcmp(base->name, vbdev->cache.name) == 0) {
SPDK_NOTICELOG("Deinitializing '%s' because"
" its cache device '%s' was removed\n",
vbdev->name, base->name);
vbdev_ocf_delete(vbdev);
}
}
}
/* Open base SPDK bdev and claim it */
@ -859,6 +941,17 @@ attach_base(struct vbdev_ocf_base *base)
return -EALREADY;
}
/* If base cache bdev was already opened by other vbdev,
* we just copy its descriptor here */
if (base->is_cache) {
struct vbdev_ocf_base *existing = get_other_cache_base(base);
if (existing) {
base->desc = existing->desc;
base->attached = true;
return 0;
}
}
status = spdk_bdev_open(base->bdev, true, hotremove_cb, base, &base->desc);
if (status) {
SPDK_ERRLOG("Unable to open device '%s' for writing\n", base->name);
@ -954,7 +1047,7 @@ vbdev_ocf_examine(struct spdk_bdev *bdev)
if (!strcmp(bdev_name, vbdev->cache.name)) {
create_from_bdevs(vbdev, bdev, NULL);
break;
continue;
}
if (!strcmp(bdev_name, vbdev->core.name)) {
create_from_bdevs(vbdev, NULL, bdev);

View File

@ -200,7 +200,7 @@ spdk_rpc_get_ocf_stats(struct spdk_jsonrpc_request *request, const struct spdk_j
goto end;
}
status = vbdev_ocf_stats_get(vbdev->ocf_cache, 0, &stats);
status = vbdev_ocf_stats_get(vbdev->ocf_cache, vbdev->core.id, &stats);
if (status) {
spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
"Could not get stats: %s",