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:
parent
5d82fa6af7
commit
97d1311fb0
@ -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->is_cache) {
|
||||
if (base->parent->state.doing_finish) {
|
||||
return;
|
||||
}
|
||||
|
||||
SPDK_NOTICELOG("Deinitializing '%s' because its %s device '%s' was removed\n",
|
||||
base->parent->name, base->is_cache ? "cache" : "core", bdev->name);
|
||||
|
||||
SPDK_NOTICELOG("Deinitializing '%s' because its core device '%s' was removed\n",
|
||||
base->parent->name, base->name);
|
||||
vbdev_ocf_delete(base->parent);
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -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",
|
||||
|
Loading…
Reference in New Issue
Block a user