Merge pull request #654 from Open-CAS/fix-flapping-merge
Porting fix-flapping patches from v21.6.4 by arutk
This commit is contained in:
commit
9a956f59cd
@ -83,7 +83,7 @@
|
||||
/**
|
||||
* Maximum value of a valid core sequence number
|
||||
*/
|
||||
#define OCF_SEQ_NO_MAX (65535UL)
|
||||
#define OCF_SEQ_NO_MAX ((1ULL << (sizeof(ocf_core_id_t) * 8)) - 1)
|
||||
/*
|
||||
* Invalid value of core sequence number
|
||||
*/
|
||||
|
@ -92,30 +92,6 @@ typedef void (*ocf_metadata_probe_end_t)(void *priv, int error,
|
||||
void ocf_metadata_probe(ocf_ctx_t ctx, ocf_volume_t volume,
|
||||
ocf_metadata_probe_end_t cmpl, void *priv);
|
||||
|
||||
/**
|
||||
* @brief Metadata probe for cores completion callback
|
||||
*
|
||||
* @param[in] priv Completion context
|
||||
* @param[in] error Error code (zero on success)
|
||||
* @param[in] num_cores Number of cores in cache metadata
|
||||
*/
|
||||
typedef void (*ocf_metadata_probe_cores_end_t)(void *priv, int error,
|
||||
unsigned int num_cores);
|
||||
|
||||
/**
|
||||
* @brief Probe cache device for associated cores
|
||||
*
|
||||
* @param[in] ctx handle to object designating ocf context
|
||||
* @param[in] volume Cache volume
|
||||
* @param[in,out] uuids Array of uuids
|
||||
* @param[in] uuid_count Size of @uuid array
|
||||
* @param[in] cmpl Completion callback
|
||||
* @param[in] priv Completion context
|
||||
*/
|
||||
void ocf_metadata_probe_cores(ocf_ctx_t ctx, ocf_volume_t volume,
|
||||
struct ocf_volume_uuid *uuids, uint32_t uuid_count,
|
||||
ocf_metadata_probe_cores_end_t cmpl, void *priv);
|
||||
|
||||
/**
|
||||
* @brief Check if sectors in cache line before given address are invalid
|
||||
*
|
||||
|
@ -286,3 +286,10 @@ void ocf_engine_hndl_ops_req(struct ocf_request *req)
|
||||
|
||||
ocf_engine_push_req_back(req, true);
|
||||
}
|
||||
|
||||
bool ocf_req_cache_mode_has_lazy_write(ocf_req_cache_mode_t mode)
|
||||
{
|
||||
return ocf_cache_mode_is_valid((ocf_cache_mode_t)mode) &&
|
||||
ocf_mngt_cache_mode_has_lazy_write(
|
||||
(ocf_cache_mode_t)mode);
|
||||
}
|
||||
|
@ -52,17 +52,7 @@ static inline const char *ocf_get_io_iface_name(ocf_cache_mode_t cache_mode)
|
||||
return iface ? iface->name : "Unknown";
|
||||
}
|
||||
|
||||
static inline bool ocf_cache_mode_is_valid(ocf_cache_mode_t mode)
|
||||
{
|
||||
return mode >= ocf_cache_mode_wt && mode < ocf_cache_mode_max;
|
||||
}
|
||||
|
||||
static inline bool ocf_req_cache_mode_has_lazy_write(ocf_req_cache_mode_t mode)
|
||||
{
|
||||
return ocf_cache_mode_is_valid((ocf_cache_mode_t)mode) &&
|
||||
ocf_mngt_cache_mode_has_lazy_write(
|
||||
(ocf_cache_mode_t)mode);
|
||||
}
|
||||
bool ocf_req_cache_mode_has_lazy_write(ocf_req_cache_mode_t mode);
|
||||
|
||||
bool ocf_fallback_pt_is_on(ocf_cache_t cache);
|
||||
|
||||
|
@ -1609,6 +1609,13 @@ void ocf_metadata_error(struct ocf_cache *cache)
|
||||
cache->device->metadata_error = -1;
|
||||
}
|
||||
|
||||
struct ocf_metadata_load_properties_ctx
|
||||
{
|
||||
ocf_cache_t cache;
|
||||
ocf_metadata_load_properties_end_t cmpl;
|
||||
void *priv;
|
||||
};
|
||||
|
||||
static void ocf_metadata_load_properties_cmpl(
|
||||
struct ocf_metadata_read_sb_ctx *context)
|
||||
{
|
||||
@ -1656,310 +1663,6 @@ void ocf_metadata_zero_superblock(ocf_cache_t cache,
|
||||
cmpl, context);
|
||||
}
|
||||
|
||||
/* metadata segment data + iterators */
|
||||
struct query_cores_data
|
||||
{
|
||||
/* array of data */
|
||||
ctx_data_t *data;
|
||||
/* current metadata entry counter */
|
||||
uint32_t entry;
|
||||
/* number of entries per page */
|
||||
uint32_t entries_in_page;
|
||||
};
|
||||
|
||||
/* query cores context */
|
||||
struct query_cores_context
|
||||
{
|
||||
ocf_ctx_t ctx;
|
||||
|
||||
struct ocf_superblock_config superblock;
|
||||
struct ocf_metadata_uuid muuid;
|
||||
|
||||
struct {
|
||||
struct query_cores_data core_uuids;
|
||||
struct query_cores_data core_config;
|
||||
struct query_cores_data superblock;
|
||||
} data;
|
||||
|
||||
env_atomic count;
|
||||
env_atomic error;
|
||||
|
||||
/* OCF entry point parameters */
|
||||
struct {
|
||||
struct ocf_volume_uuid *uuids;
|
||||
uint32_t uuids_count;
|
||||
void *priv;
|
||||
ocf_metadata_query_cores_end_t cmpl;
|
||||
} params;
|
||||
};
|
||||
|
||||
/* copy next metadata entry from data to memory buffer */
|
||||
static void ocf_metadata_query_cores_data_read(ocf_ctx_t ctx,
|
||||
struct query_cores_data *data,
|
||||
void *buf, uint32_t size)
|
||||
{
|
||||
if (data->entry > 0 && data->entry % data->entries_in_page == 0) {
|
||||
ctx_data_seek_check(ctx, data->data,
|
||||
ctx_data_seek_current,
|
||||
PAGE_SIZE - data->entries_in_page * size);
|
||||
}
|
||||
|
||||
ctx_data_rd_check(ctx, buf, data->data, size);
|
||||
|
||||
++data->entry;
|
||||
}
|
||||
|
||||
static void ocf_metadata_query_cores_end(struct query_cores_context *context,
|
||||
int error)
|
||||
{
|
||||
ocf_ctx_t ctx = context->ctx;
|
||||
unsigned i, core_idx;
|
||||
struct ocf_metadata_uuid *muuid = &context->muuid;
|
||||
struct ocf_core_meta_config core_config;
|
||||
unsigned core_count = 0;
|
||||
unsigned long valid_core_bitmap[(OCF_CORE_MAX /
|
||||
(sizeof(unsigned long) * 8)) + 1];
|
||||
unsigned out_cores;
|
||||
|
||||
if (error)
|
||||
env_atomic_cmpxchg(&context->error, 0, error);
|
||||
|
||||
if (env_atomic_dec_return(&context->count))
|
||||
return;
|
||||
|
||||
error = env_atomic_read(&context->error);
|
||||
if (error)
|
||||
goto exit;
|
||||
|
||||
/* read superblock */
|
||||
ctx_data_rd_check(ctx, &context->superblock,
|
||||
context->data.superblock.data,
|
||||
sizeof(context->superblock));
|
||||
|
||||
if (context->superblock.magic_number != CACHE_MAGIC_NUMBER) {
|
||||
error = -OCF_ERR_NO_METADATA;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
env_memset(&valid_core_bitmap, sizeof(valid_core_bitmap), 0);
|
||||
|
||||
/* read valid cores from core config segment */
|
||||
for (i = 0; i < OCF_CORE_MAX; i++) {
|
||||
ocf_metadata_query_cores_data_read(ctx,
|
||||
&context->data.core_config,
|
||||
&core_config, sizeof(core_config));
|
||||
if (core_config.valid) {
|
||||
env_bit_set(i, valid_core_bitmap);
|
||||
++core_count;
|
||||
}
|
||||
}
|
||||
|
||||
/* read core uuids */
|
||||
out_cores = OCF_MIN(core_count, context->params.uuids_count);
|
||||
for (i = 0, core_idx = 0; i < OCF_CORE_MAX && core_idx < out_cores;
|
||||
i++) {
|
||||
ocf_metadata_query_cores_data_read(ctx,
|
||||
&context->data.core_uuids,
|
||||
muuid, sizeof(*muuid));
|
||||
|
||||
if (!env_bit_test(i, valid_core_bitmap))
|
||||
continue;
|
||||
|
||||
if (muuid->size > OCF_VOLUME_UUID_MAX_SIZE) {
|
||||
error = -OCF_ERR_INVAL;
|
||||
goto exit;
|
||||
}
|
||||
if (muuid->size > context->params.uuids[core_idx].size) {
|
||||
error = -OCF_ERR_INVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
error = env_memcpy(context->params.uuids[core_idx].data,
|
||||
context->params.uuids[core_idx].size,
|
||||
muuid->data, muuid->size);
|
||||
if (error)
|
||||
goto exit;
|
||||
context->params.uuids[core_idx].size = muuid->size;
|
||||
|
||||
++core_idx;
|
||||
}
|
||||
|
||||
exit:
|
||||
/* provide actual core count to completion */
|
||||
context->params.cmpl(context->params.priv, error, core_count);
|
||||
|
||||
/* free data */
|
||||
ctx_data_free(ctx, context->data.core_uuids.data);
|
||||
ctx_data_free(ctx, context->data.core_config.data);
|
||||
ctx_data_free(ctx, context->data.superblock.data);
|
||||
|
||||
env_secure_free(context, sizeof(*context));
|
||||
}
|
||||
|
||||
static void ocf_metadata_query_cores_end_io(struct ocf_io *io, int error)
|
||||
{
|
||||
struct query_cores_context *context = io->priv1;
|
||||
|
||||
ocf_io_put(io);
|
||||
ocf_metadata_query_cores_end(context, error);
|
||||
}
|
||||
|
||||
static int ocf_metadata_query_cores_io(ocf_volume_t volume,
|
||||
struct query_cores_context *context, ctx_data_t *data,
|
||||
uint32_t offset, uint64_t page, uint32_t num_pages)
|
||||
{
|
||||
struct ocf_io *io;
|
||||
int err;
|
||||
|
||||
env_atomic_inc(&context->count);
|
||||
|
||||
/* Allocate new IO */
|
||||
io = ocf_volume_new_io(volume, NULL,
|
||||
PAGES_TO_BYTES(page),
|
||||
PAGES_TO_BYTES(num_pages),
|
||||
OCF_READ, 0, 0);
|
||||
if (!io) {
|
||||
err = -OCF_ERR_NO_MEM;
|
||||
goto exit_error;
|
||||
}
|
||||
|
||||
/* Setup IO */
|
||||
ocf_io_set_cmpl(io, context, NULL,
|
||||
ocf_metadata_query_cores_end_io);
|
||||
err = ocf_io_set_data(io, data, PAGES_TO_BYTES(offset));
|
||||
if (err) {
|
||||
ocf_io_put(io);
|
||||
goto exit_error;
|
||||
}
|
||||
|
||||
ocf_volume_submit_io(io);
|
||||
|
||||
return 0;
|
||||
|
||||
exit_error:
|
||||
env_atomic_dec(&context->count);
|
||||
return err;
|
||||
}
|
||||
|
||||
int ocf_metadata_query_cores_segment_io(
|
||||
struct query_cores_context *context,
|
||||
ocf_ctx_t owner,
|
||||
ocf_volume_t volume,
|
||||
enum ocf_metadata_segment_id segment,
|
||||
struct ocf_metadata_ctrl *ctrl,
|
||||
struct query_cores_data *segment_data)
|
||||
{
|
||||
uint32_t pages_left;
|
||||
uint32_t pages;
|
||||
uint32_t addr;
|
||||
uint32_t offset;
|
||||
uint32_t io_count;
|
||||
uint32_t i;
|
||||
uint32_t max_pages_per_io;
|
||||
int err = 0;
|
||||
unsigned int max_io_size = ocf_volume_get_max_io_size(volume);
|
||||
|
||||
if (!max_io_size) {
|
||||
err = -OCF_ERR_INVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
max_pages_per_io = max_io_size / PAGE_SIZE;
|
||||
|
||||
/* Allocate data */
|
||||
segment_data->data = ctx_data_alloc(owner,
|
||||
ctrl->raw_desc[segment].ssd_pages);
|
||||
if (!segment_data->data) {
|
||||
err = -OCF_ERR_NO_MEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
segment_data->entries_in_page = ctrl->raw_desc[segment].entries_in_page;
|
||||
|
||||
io_count = OCF_DIV_ROUND_UP(ctrl->raw_desc[segment].ssd_pages,
|
||||
max_pages_per_io);
|
||||
|
||||
/* submit segment data I/O */
|
||||
pages_left = ctrl->raw_desc[segment].ssd_pages;
|
||||
addr = ctrl->raw_desc[segment].ssd_pages_offset;
|
||||
offset = 0;
|
||||
i = 0;
|
||||
while (pages_left) {
|
||||
ENV_BUG_ON(i >= io_count);
|
||||
|
||||
pages = OCF_MIN(pages_left, max_pages_per_io);
|
||||
|
||||
err = ocf_metadata_query_cores_io(volume, context,
|
||||
segment_data->data, offset, addr, pages);
|
||||
if (err)
|
||||
goto exit;
|
||||
|
||||
addr += pages;
|
||||
offset += pages;
|
||||
pages_left -= pages;
|
||||
++i;
|
||||
}
|
||||
|
||||
exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
void ocf_metadata_query_cores(ocf_ctx_t owner, ocf_volume_t volume,
|
||||
struct ocf_volume_uuid *uuid, uint32_t count,
|
||||
ocf_metadata_query_cores_end_t cmpl, void *priv)
|
||||
{
|
||||
struct ocf_metadata_ctrl *ctrl = NULL;
|
||||
struct query_cores_context *context;
|
||||
int err;
|
||||
|
||||
if (count > OCF_CORE_MAX)
|
||||
OCF_CMPL_RET(priv, -OCF_ERR_INVAL, 0);
|
||||
|
||||
/* intialize query context */
|
||||
context = env_secure_alloc(sizeof(*context));
|
||||
if (!context)
|
||||
OCF_CMPL_RET(priv, -OCF_ERR_NO_MEM, 0);
|
||||
|
||||
ENV_BUG_ON(env_memset(context, sizeof(*context), 0));
|
||||
context->ctx = owner;
|
||||
context->params.cmpl = cmpl;
|
||||
context->params.priv = priv;
|
||||
context->params.uuids = uuid;
|
||||
context->params.uuids_count = count;
|
||||
env_atomic_set(&context->count, 1);
|
||||
|
||||
ctrl = ocf_metadata_ctrl_init(false);
|
||||
if (!ctrl) {
|
||||
err = -OCF_ERR_NO_MEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* superblock I/O */
|
||||
err = ocf_metadata_query_cores_segment_io(context, owner,
|
||||
volume, metadata_segment_sb_config, ctrl,
|
||||
&context->data.superblock);
|
||||
if (err)
|
||||
goto exit;
|
||||
|
||||
/* core config I/O */
|
||||
err = ocf_metadata_query_cores_segment_io(context, owner,
|
||||
volume, metadata_segment_core_uuid, ctrl,
|
||||
&context->data.core_uuids);
|
||||
if (err)
|
||||
goto exit;
|
||||
|
||||
/* core uuid I/O */
|
||||
err = ocf_metadata_query_cores_segment_io(context, owner,
|
||||
volume, metadata_segment_core_config, ctrl,
|
||||
&context->data.core_config);
|
||||
if (err)
|
||||
goto exit;
|
||||
exit:
|
||||
env_vfree(ctrl);
|
||||
ocf_metadata_query_cores_end(context, err);
|
||||
}
|
||||
|
||||
|
||||
static void ocf_metadata_probe_cmpl(struct ocf_metadata_read_sb_ctx *context)
|
||||
{
|
||||
struct ocf_metadata_probe_status status;
|
||||
@ -2005,35 +1708,4 @@ void ocf_metadata_probe(ocf_ctx_t ctx, ocf_volume_t volume,
|
||||
OCF_CMPL_RET(priv, result, NULL);
|
||||
}
|
||||
|
||||
/* completion context for query_cores */
|
||||
struct ocf_metadata_query_cores_context
|
||||
{
|
||||
ocf_metadata_probe_cores_end_t cmpl;
|
||||
void *priv;
|
||||
};
|
||||
|
||||
static void ocf_metadata_probe_cores_end(void *_context, int error,
|
||||
unsigned num_cores)
|
||||
{
|
||||
struct ocf_metadata_query_cores_context *context = _context;
|
||||
|
||||
context->cmpl(context->priv, error, num_cores);
|
||||
env_vfree(context);
|
||||
}
|
||||
|
||||
void ocf_metadata_probe_cores(ocf_ctx_t ctx, ocf_volume_t volume,
|
||||
struct ocf_volume_uuid *uuids, uint32_t uuids_count,
|
||||
ocf_metadata_probe_cores_end_t cmpl, void *priv)
|
||||
{
|
||||
struct ocf_metadata_query_cores_context *context;
|
||||
|
||||
context = env_vzalloc(sizeof(*context));
|
||||
if (!context)
|
||||
OCF_CMPL_RET(priv, -OCF_ERR_NO_MEM, 0);
|
||||
|
||||
context->cmpl = cmpl;
|
||||
context->priv = priv;
|
||||
|
||||
ocf_metadata_query_cores(ctx, volume, uuids, uuids_count,
|
||||
ocf_metadata_probe_cores_end, context);
|
||||
}
|
||||
|
@ -98,55 +98,115 @@ static void ocf_metadata_store_segment(ocf_pipeline_t pipeline,
|
||||
ocf_pipeline_next(pipeline);
|
||||
}
|
||||
|
||||
static void ocf_metadata_check_crc_sb_config(ocf_pipeline_t pipeline,
|
||||
void *priv, ocf_pipeline_arg_t arg)
|
||||
|
||||
#define ocf_log_invalid_superblock(param) \
|
||||
ocf_log(ctx, log_err, \
|
||||
"Loading %s: invalid %s\n", \
|
||||
ocf_metadata_segment_names[ \
|
||||
metadata_segment_sb_config], \
|
||||
param);
|
||||
|
||||
|
||||
int ocf_metadata_validate_superblock(ocf_ctx_t ctx,
|
||||
struct ocf_superblock_config *superblock)
|
||||
{
|
||||
struct ocf_metadata_context *context = priv;
|
||||
struct ocf_metadata_ctrl *ctrl;
|
||||
struct ocf_superblock_config *sb_config;
|
||||
ocf_cache_t cache = context->cache;
|
||||
int segment = metadata_segment_sb_config;
|
||||
uint32_t crc;
|
||||
|
||||
ctrl = (struct ocf_metadata_ctrl *)cache->metadata.priv;
|
||||
sb_config = METADATA_MEM_POOL(ctrl, metadata_segment_sb_config);
|
||||
|
||||
crc = env_crc32(0, (void *)sb_config,
|
||||
offsetof(struct ocf_superblock_config, checksum));
|
||||
|
||||
if (crc != sb_config->checksum[segment]) {
|
||||
/* Checksum does not match */
|
||||
ocf_cache_log(cache, log_err,
|
||||
"Loading %s ERROR, invalid checksum\n",
|
||||
ocf_metadata_segment_names[segment]);
|
||||
OCF_PL_FINISH_RET(pipeline, -OCF_ERR_INVAL);
|
||||
if (superblock->magic_number != CACHE_MAGIC_NUMBER) {
|
||||
ocf_log(ctx, log_info, "Cannot detect pre-existing metadata\n");
|
||||
return -OCF_ERR_NO_METADATA;
|
||||
}
|
||||
|
||||
ocf_pipeline_next(pipeline);
|
||||
if (METADATA_VERSION() != superblock->metadata_version) {
|
||||
ocf_log(ctx, log_err, "Metadata version mismatch!\n");
|
||||
return -OCF_ERR_METADATA_VER;
|
||||
}
|
||||
|
||||
crc = env_crc32(0, (void *)superblock,
|
||||
offsetof(struct ocf_superblock_config, checksum));
|
||||
|
||||
if (crc != superblock->checksum[metadata_segment_sb_config]) {
|
||||
ocf_log_invalid_superblock("checksum");
|
||||
return -OCF_ERR_INVAL;
|
||||
}
|
||||
|
||||
if (superblock->clean_shutdown > ocf_metadata_clean_shutdown) {
|
||||
ocf_log_invalid_superblock("shutdown status");
|
||||
return -OCF_ERR_INVAL;
|
||||
}
|
||||
|
||||
if (superblock->dirty_flushed > DIRTY_FLUSHED) {
|
||||
ocf_log_invalid_superblock("flush status");
|
||||
return -OCF_ERR_INVAL;
|
||||
}
|
||||
|
||||
if (superblock->flapping_idx > 1) {
|
||||
ocf_log_invalid_superblock("flapping index");
|
||||
return -OCF_ERR_INVAL;
|
||||
}
|
||||
|
||||
if (superblock->cache_mode < 0 ||
|
||||
superblock->cache_mode >= ocf_cache_mode_max) {
|
||||
ocf_log_invalid_superblock("cache mode");
|
||||
return -OCF_ERR_INVAL;
|
||||
}
|
||||
|
||||
if (env_strnlen(superblock->name, sizeof(superblock->name)) >=
|
||||
OCF_CACHE_NAME_SIZE) {
|
||||
ocf_log_invalid_superblock("name");
|
||||
return -OCF_ERR_INVAL;
|
||||
}
|
||||
|
||||
if (superblock->valid_parts_no > OCF_USER_IO_CLASS_MAX) {
|
||||
ocf_log_invalid_superblock("partition count");
|
||||
return -OCF_ERR_INVAL;
|
||||
}
|
||||
|
||||
if (!ocf_cache_line_size_is_valid(superblock->line_size)) {
|
||||
ocf_log_invalid_superblock("cache line size");
|
||||
return -OCF_ERR_INVAL;
|
||||
}
|
||||
|
||||
if ((unsigned)superblock->metadata_layout >= ocf_metadata_layout_max) {
|
||||
ocf_log_invalid_superblock("metadata layout");
|
||||
return -OCF_ERR_INVAL;
|
||||
}
|
||||
|
||||
if (superblock->core_count > OCF_CORE_MAX) {
|
||||
ocf_log_invalid_superblock("core count");
|
||||
return -OCF_ERR_INVAL;
|
||||
}
|
||||
|
||||
if (superblock->cleaning_policy_type < 0 ||
|
||||
superblock->cleaning_policy_type >= ocf_cleaning_max) {
|
||||
ocf_log_invalid_superblock("cleaning policy");
|
||||
return -OCF_ERR_INVAL;
|
||||
}
|
||||
|
||||
if (superblock->promotion_policy_type < 0 ||
|
||||
superblock->promotion_policy_type >=
|
||||
ocf_promotion_max) {
|
||||
ocf_log_invalid_superblock("promotion policy");
|
||||
return -OCF_ERR_INVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ocf_metadata_load_superblock_post(ocf_pipeline_t pipeline,
|
||||
static void _ocf_metadata_validate_superblock(ocf_pipeline_t pipeline,
|
||||
void *priv, ocf_pipeline_arg_t arg)
|
||||
{
|
||||
struct ocf_metadata_context *context = priv;
|
||||
struct ocf_metadata_ctrl *ctrl;
|
||||
struct ocf_superblock_config *sb_config;
|
||||
ocf_cache_t cache = context->cache;
|
||||
struct ocf_superblock_config *superblock;
|
||||
int ret;
|
||||
|
||||
ctrl = (struct ocf_metadata_ctrl *)cache->metadata.priv;
|
||||
sb_config = METADATA_MEM_POOL(ctrl, metadata_segment_sb_config);
|
||||
ctrl = (struct ocf_metadata_ctrl *)context->ctrl;
|
||||
superblock = METADATA_MEM_POOL(ctrl, metadata_segment_sb_config);
|
||||
|
||||
if (sb_config->core_count > OCF_CORE_MAX) {
|
||||
ocf_cache_log(cache, log_err,
|
||||
"Loading cache state ERROR, invalid cores count\n");
|
||||
OCF_PL_FINISH_RET(pipeline, -OCF_ERR_INVAL);
|
||||
}
|
||||
|
||||
if (sb_config->valid_parts_no > OCF_USER_IO_CLASS_MAX) {
|
||||
ocf_cache_log(cache, log_err,
|
||||
"Loading cache state ERROR, invalid partition count\n");
|
||||
OCF_PL_FINISH_RET(pipeline, -OCF_ERR_INVAL);
|
||||
}
|
||||
ret = ocf_metadata_validate_superblock(context->cache->owner, superblock);
|
||||
if (ret)
|
||||
OCF_PL_FINISH_RET(pipeline, ret);
|
||||
|
||||
ocf_pipeline_next(pipeline);
|
||||
}
|
||||
@ -206,16 +266,6 @@ struct ocf_pipeline_arg ocf_metadata_load_sb_store_segment_args[] = {
|
||||
};
|
||||
|
||||
struct ocf_pipeline_arg ocf_metadata_load_sb_load_segment_args[] = {
|
||||
OCF_PL_ARG_INT(metadata_segment_sb_config),
|
||||
OCF_PL_ARG_INT(metadata_segment_sb_runtime),
|
||||
OCF_PL_ARG_INT(metadata_segment_part_config),
|
||||
OCF_PL_ARG_INT(metadata_segment_part_runtime),
|
||||
OCF_PL_ARG_INT(metadata_segment_core_config),
|
||||
OCF_PL_ARG_INT(metadata_segment_core_uuid),
|
||||
OCF_PL_ARG_TERMINATOR(),
|
||||
};
|
||||
|
||||
struct ocf_pipeline_arg ocf_metadata_load_sb_check_crc_args[] = {
|
||||
OCF_PL_ARG_INT(metadata_segment_sb_runtime),
|
||||
OCF_PL_ARG_INT(metadata_segment_part_config),
|
||||
OCF_PL_ARG_INT(metadata_segment_part_runtime),
|
||||
@ -230,12 +280,13 @@ struct ocf_pipeline_properties ocf_metadata_load_sb_pipeline_props = {
|
||||
.steps = {
|
||||
OCF_PL_STEP_FOREACH(ocf_metadata_store_segment,
|
||||
ocf_metadata_load_sb_store_segment_args),
|
||||
OCF_PL_STEP_ARG_INT(ocf_metadata_load_segment,
|
||||
metadata_segment_sb_config),
|
||||
OCF_PL_STEP(_ocf_metadata_validate_superblock),
|
||||
OCF_PL_STEP_FOREACH(ocf_metadata_load_segment,
|
||||
ocf_metadata_load_sb_load_segment_args),
|
||||
OCF_PL_STEP(ocf_metadata_check_crc_sb_config),
|
||||
OCF_PL_STEP_FOREACH(ocf_metadata_check_crc,
|
||||
ocf_metadata_load_sb_check_crc_args),
|
||||
OCF_PL_STEP(ocf_metadata_load_superblock_post),
|
||||
ocf_metadata_load_sb_load_segment_args),
|
||||
OCF_PL_STEP_TERMINATOR(),
|
||||
},
|
||||
};
|
||||
@ -282,14 +333,6 @@ void ocf_metadata_load_superblock(ocf_cache_t cache, ocf_metadata_end_t cmpl,
|
||||
}
|
||||
|
||||
struct ocf_pipeline_arg ocf_metadata_load_sb_recov_load_segment_args[] = {
|
||||
OCF_PL_ARG_INT(metadata_segment_sb_config),
|
||||
OCF_PL_ARG_INT(metadata_segment_part_config),
|
||||
OCF_PL_ARG_INT(metadata_segment_core_config),
|
||||
OCF_PL_ARG_INT(metadata_segment_core_uuid),
|
||||
OCF_PL_ARG_TERMINATOR(),
|
||||
};
|
||||
|
||||
struct ocf_pipeline_arg ocf_metadata_load_sb_recov_check_crc_args[] = {
|
||||
OCF_PL_ARG_INT(metadata_segment_part_config),
|
||||
OCF_PL_ARG_INT(metadata_segment_core_config),
|
||||
OCF_PL_ARG_INT(metadata_segment_core_uuid),
|
||||
@ -302,12 +345,13 @@ struct ocf_pipeline_properties ocf_metadata_load_sb_recov_pipeline_props = {
|
||||
.steps = {
|
||||
OCF_PL_STEP_FOREACH(ocf_metadata_store_segment,
|
||||
ocf_metadata_load_sb_store_segment_args),
|
||||
OCF_PL_STEP_ARG_INT(ocf_metadata_load_segment,
|
||||
metadata_segment_sb_config),
|
||||
OCF_PL_STEP(_ocf_metadata_validate_superblock),
|
||||
OCF_PL_STEP_FOREACH(ocf_metadata_load_segment,
|
||||
ocf_metadata_load_sb_recov_load_segment_args),
|
||||
OCF_PL_STEP(ocf_metadata_check_crc_sb_config),
|
||||
OCF_PL_STEP_FOREACH(ocf_metadata_check_crc,
|
||||
ocf_metadata_load_sb_recov_check_crc_args),
|
||||
OCF_PL_STEP(ocf_metadata_load_superblock_post),
|
||||
ocf_metadata_load_sb_recov_load_segment_args),
|
||||
OCF_PL_STEP_TERMINATOR(),
|
||||
},
|
||||
};
|
||||
@ -587,47 +631,6 @@ unsigned ocf_metadata_superblock_get_next_flapping_idx(
|
||||
return (sb->config->flapping_idx + 1) % 2;
|
||||
}
|
||||
|
||||
int ocf_metadata_validate_superblock(ocf_ctx_t ctx,
|
||||
struct ocf_superblock_config *superblock)
|
||||
{
|
||||
if (superblock->magic_number != CACHE_MAGIC_NUMBER) {
|
||||
ocf_log(ctx, log_info, "Cannot detect pre-existing metadata\n");
|
||||
return -OCF_ERR_NO_METADATA;
|
||||
}
|
||||
|
||||
if (METADATA_VERSION() != superblock->metadata_version) {
|
||||
ocf_log(ctx, log_err, "Metadata version mismatch!\n");
|
||||
return -OCF_ERR_METADATA_VER;
|
||||
}
|
||||
|
||||
if (!ocf_cache_line_size_is_valid(superblock->line_size)) {
|
||||
ocf_log(ctx, log_err, "ERROR: Invalid cache line size!\n");
|
||||
return -OCF_ERR_INVAL;
|
||||
}
|
||||
|
||||
if ((unsigned)superblock->metadata_layout >= ocf_metadata_layout_max) {
|
||||
ocf_log(ctx, log_err, "ERROR: Invalid metadata layout!\n");
|
||||
return -OCF_ERR_INVAL;
|
||||
}
|
||||
|
||||
if (superblock->cache_mode >= ocf_cache_mode_max) {
|
||||
ocf_log(ctx, log_err, "ERROR: Invalid cache mode!\n");
|
||||
return -OCF_ERR_INVAL;
|
||||
}
|
||||
|
||||
if (superblock->clean_shutdown > ocf_metadata_clean_shutdown) {
|
||||
ocf_log(ctx, log_err, "ERROR: Invalid shutdown status!\n");
|
||||
return -OCF_ERR_INVAL;
|
||||
}
|
||||
|
||||
if (superblock->dirty_flushed > DIRTY_FLUSHED) {
|
||||
ocf_log(ctx, log_err, "ERROR: Invalid flush status!\n");
|
||||
return -OCF_ERR_INVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ocf_metadata_read_sb_complete(struct ocf_io *io, int error)
|
||||
{
|
||||
struct ocf_metadata_read_sb_ctx *context = io->priv1;
|
||||
@ -710,51 +713,6 @@ err_io:
|
||||
return result;
|
||||
}
|
||||
|
||||
static void ocf_metadata_sb_crc_recovery_finish(ocf_pipeline_t pipeline,
|
||||
void *priv, int error)
|
||||
{
|
||||
struct ocf_metadata_context *context = priv;
|
||||
|
||||
context->cmpl(context->priv, error);
|
||||
ocf_pipeline_destroy(pipeline);
|
||||
}
|
||||
|
||||
struct ocf_pipeline_properties ocf_metadata_sb_crc_recovery_pipeline_props = {
|
||||
.priv_size = sizeof(struct ocf_metadata_context),
|
||||
.finish = ocf_metadata_sb_crc_recovery_finish,
|
||||
.steps = {
|
||||
OCF_PL_STEP(ocf_metadata_check_crc_sb_config),
|
||||
OCF_PL_STEP_FOREACH(ocf_metadata_check_crc,
|
||||
ocf_metadata_load_sb_check_crc_args),
|
||||
OCF_PL_STEP_TERMINATOR(),
|
||||
},
|
||||
};
|
||||
|
||||
void ocf_metadata_sb_crc_recovery(ocf_cache_t cache,
|
||||
ocf_metadata_end_t cmpl, void *priv)
|
||||
{
|
||||
struct ocf_metadata_context *context;
|
||||
ocf_pipeline_t pipeline;
|
||||
int result;
|
||||
|
||||
OCF_DEBUG_TRACE(cache);
|
||||
|
||||
result = ocf_pipeline_create(&pipeline, cache,
|
||||
&ocf_metadata_sb_crc_recovery_pipeline_props);
|
||||
if (result)
|
||||
OCF_CMPL_RET(priv, result);
|
||||
|
||||
context = ocf_pipeline_get_priv(pipeline);
|
||||
|
||||
context->cmpl = cmpl;
|
||||
context->priv = priv;
|
||||
context->pipeline = pipeline;
|
||||
context->cache = cache;
|
||||
context->ctrl = cache->metadata.priv;
|
||||
|
||||
ocf_pipeline_next(pipeline);
|
||||
}
|
||||
|
||||
void ocf_metadata_sb_zero(struct ocf_metadata_segment *self,
|
||||
ocf_metadata_end_t cmpl, void *priv)
|
||||
{
|
||||
|
@ -39,6 +39,11 @@ int ocf_cache_set_name(ocf_cache_t cache, const char *src, size_t src_size)
|
||||
src, src_size);
|
||||
}
|
||||
|
||||
bool ocf_cache_mode_is_valid(ocf_cache_mode_t mode)
|
||||
{
|
||||
return mode >= ocf_cache_mode_wt && mode < ocf_cache_mode_max;
|
||||
}
|
||||
|
||||
const char *ocf_cache_get_name(ocf_cache_t cache)
|
||||
{
|
||||
OCF_CHECK_NULL(cache);
|
||||
|
@ -179,4 +179,6 @@ int ocf_cache_set_name(ocf_cache_t cache, const char *src, size_t src_size);
|
||||
|
||||
int ocf_cache_volume_type_init(ocf_ctx_t ctx);
|
||||
|
||||
bool ocf_cache_mode_is_valid(ocf_cache_mode_t mode);
|
||||
|
||||
#endif /* __OCF_CACHE_PRIV_H__ */
|
||||
|
Loading…
Reference in New Issue
Block a user