221 lines
4.0 KiB
C
221 lines
4.0 KiB
C
/*
|
|
* Copyright(c) 2012-2018 Intel Corporation
|
|
* SPDX-License-Identifier: BSD-3-Clause-Clear
|
|
*/
|
|
|
|
#include "ocf/ocf.h"
|
|
#include "ocf_ctx_priv.h"
|
|
#include "ocf_priv.h"
|
|
#include "ocf_volume_priv.h"
|
|
#include "ocf_request.h"
|
|
#include "ocf_logger_priv.h"
|
|
#include "ocf_core_priv.h"
|
|
#include "mngt/ocf_mngt_core_pool_priv.h"
|
|
|
|
/*
|
|
*
|
|
*/
|
|
int ocf_ctx_register_volume_type(ocf_ctx_t ctx, uint8_t type_id,
|
|
const struct ocf_volume_properties *properties)
|
|
{
|
|
int result = 0;
|
|
|
|
if (!ctx || !properties)
|
|
return -EINVAL;
|
|
|
|
env_mutex_lock(&ctx->lock);
|
|
|
|
if (type_id >= OCF_VOLUME_TYPE_MAX || ctx->volume_type[type_id]) {
|
|
env_mutex_unlock(&ctx->lock);
|
|
result = -EINVAL;
|
|
goto err;
|
|
}
|
|
|
|
ocf_volume_type_init(&ctx->volume_type[type_id], properties);
|
|
if (!ctx->volume_type[type_id])
|
|
result = -EINVAL;
|
|
|
|
env_mutex_unlock(&ctx->lock);
|
|
|
|
if (result)
|
|
goto err;
|
|
|
|
ocf_log(ctx, log_debug, "'%s' volume operations registered\n",
|
|
properties->name);
|
|
return 0;
|
|
|
|
err:
|
|
ocf_log(ctx, log_err, "Failed to register volume operations '%s'\n",
|
|
properties->name);
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
*
|
|
*/
|
|
void ocf_ctx_unregister_volume_type(ocf_ctx_t ctx, uint8_t type_id)
|
|
{
|
|
OCF_CHECK_NULL(ctx);
|
|
|
|
env_mutex_lock(&ctx->lock);
|
|
|
|
if (type_id < OCF_VOLUME_TYPE_MAX && ctx->volume_type[type_id]) {
|
|
ocf_volume_type_deinit(ctx->volume_type[type_id]);
|
|
ctx->volume_type[type_id] = NULL;
|
|
}
|
|
|
|
env_mutex_unlock(&ctx->lock);
|
|
}
|
|
|
|
/*
|
|
*
|
|
*/
|
|
ocf_volume_type_t ocf_ctx_get_volume_type(ocf_ctx_t ctx, uint8_t type_id)
|
|
{
|
|
OCF_CHECK_NULL(ctx);
|
|
|
|
if (type_id >= OCF_VOLUME_TYPE_MAX)
|
|
return NULL;
|
|
|
|
return ctx->volume_type[type_id];
|
|
}
|
|
|
|
/*
|
|
*
|
|
*/
|
|
int ocf_ctx_get_volume_type_id(ocf_ctx_t ctx, ocf_volume_type_t type)
|
|
{
|
|
int i;
|
|
|
|
OCF_CHECK_NULL(ctx);
|
|
|
|
for (i = 0; i < OCF_VOLUME_TYPE_MAX; ++i) {
|
|
if (ctx->volume_type[i] == type)
|
|
return i;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
*
|
|
*/
|
|
int ocf_ctx_volume_create(ocf_ctx_t ctx, ocf_volume_t *volume,
|
|
struct ocf_volume_uuid *uuid, uint8_t type_id)
|
|
{
|
|
OCF_CHECK_NULL(ctx);
|
|
|
|
if (type_id >= OCF_VOLUME_TYPE_MAX)
|
|
return -EINVAL;
|
|
|
|
return ocf_volume_create(volume, ctx->volume_type[type_id], uuid);
|
|
}
|
|
|
|
static void check_ops_provided(const struct ocf_ctx_ops *ops)
|
|
{
|
|
ENV_BUG_ON(!ops->data.alloc);
|
|
ENV_BUG_ON(!ops->data.free);
|
|
ENV_BUG_ON(!ops->data.mlock);
|
|
ENV_BUG_ON(!ops->data.munlock);
|
|
ENV_BUG_ON(!ops->data.read);
|
|
ENV_BUG_ON(!ops->data.write);
|
|
ENV_BUG_ON(!ops->data.zero);
|
|
ENV_BUG_ON(!ops->data.seek);
|
|
ENV_BUG_ON(!ops->data.copy);
|
|
ENV_BUG_ON(!ops->data.secure_erase);
|
|
|
|
ENV_BUG_ON(!ops->cleaner.init);
|
|
ENV_BUG_ON(!ops->cleaner.kick);
|
|
ENV_BUG_ON(!ops->cleaner.stop);
|
|
|
|
ENV_BUG_ON(!ops->metadata_updater.init);
|
|
ENV_BUG_ON(!ops->metadata_updater.kick);
|
|
ENV_BUG_ON(!ops->metadata_updater.stop);
|
|
}
|
|
|
|
/*
|
|
*
|
|
*/
|
|
int ocf_ctx_create(ocf_ctx_t *ctx, const struct ocf_ctx_config *cfg)
|
|
{
|
|
ocf_ctx_t ocf_ctx;
|
|
int ret;
|
|
|
|
OCF_CHECK_NULL(ctx);
|
|
OCF_CHECK_NULL(cfg);
|
|
|
|
check_ops_provided(&cfg->ops);
|
|
|
|
ocf_ctx = env_zalloc(sizeof(*ocf_ctx), ENV_MEM_NORMAL);
|
|
if (!ocf_ctx)
|
|
return -ENOMEM;
|
|
|
|
INIT_LIST_HEAD(&ocf_ctx->caches);
|
|
env_atomic_set(&ocf_ctx->ref_count, 1);
|
|
ret = env_mutex_init(&ocf_ctx->lock);
|
|
if (ret)
|
|
goto err_ctx;
|
|
|
|
ocf_ctx->ops = &cfg->ops;
|
|
ocf_ctx->cfg = cfg;
|
|
|
|
ocf_logger_init(&ocf_ctx->logger, &cfg->ops.logger, cfg->logger_priv);
|
|
|
|
ret = ocf_logger_open(&ocf_ctx->logger);
|
|
if (ret)
|
|
goto err_ctx;
|
|
|
|
ret = ocf_req_allocator_init(ocf_ctx);
|
|
if (ret)
|
|
goto err_logger;
|
|
|
|
ret = ocf_core_volume_type_init(ocf_ctx);
|
|
if (ret)
|
|
goto err_utils;
|
|
|
|
ocf_mngt_core_pool_init(ocf_ctx);
|
|
|
|
*ctx = ocf_ctx;
|
|
|
|
return 0;
|
|
|
|
err_utils:
|
|
ocf_req_allocator_deinit(ocf_ctx);
|
|
err_logger:
|
|
ocf_logger_close(&ocf_ctx->logger);
|
|
err_ctx:
|
|
env_free(ocf_ctx);
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
*
|
|
*/
|
|
void ocf_ctx_get(ocf_ctx_t ctx)
|
|
{
|
|
OCF_CHECK_NULL(ctx);
|
|
|
|
env_atomic_inc(&ctx->ref_count);
|
|
}
|
|
|
|
/*
|
|
*
|
|
*/
|
|
void ocf_ctx_put(ocf_ctx_t ctx)
|
|
{
|
|
OCF_CHECK_NULL(ctx);
|
|
|
|
if (env_atomic_dec_return(&ctx->ref_count))
|
|
return;
|
|
|
|
env_mutex_lock(&ctx->lock);
|
|
ENV_BUG_ON(!list_empty(&ctx->caches));
|
|
env_mutex_unlock(&ctx->lock);
|
|
|
|
ocf_mngt_core_pool_deinit(ctx);
|
|
ocf_core_volume_type_deinit(ctx);
|
|
ocf_req_allocator_deinit(ctx);
|
|
ocf_logger_close(&ctx->logger);
|
|
env_free(ctx);
|
|
}
|