
Change license to BSD-3-Clause Signed-off-by: Rafal Stefanowski <rafal.stefanowski@intel.com>
160 lines
4.2 KiB
C
160 lines
4.2 KiB
C
/*
|
|
* Copyright(c) 2020-2021 Intel Corporation
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
#include "metadata_internal.h"
|
|
#include "metadata_superblock.h"
|
|
#include "metadata_raw.h"
|
|
|
|
int ocf_metadata_segment_init_in_place(
|
|
struct ocf_metadata_segment *segment,
|
|
struct ocf_cache *cache,
|
|
struct ocf_metadata_raw *raw,
|
|
ocf_flush_page_synch_t lock_page_pfn,
|
|
ocf_flush_page_synch_t unlock_page_pfn,
|
|
struct ocf_metadata_segment *superblock)
|
|
{
|
|
int result;
|
|
|
|
result = ocf_metadata_raw_init(cache, lock_page_pfn, unlock_page_pfn, raw);
|
|
if (result)
|
|
return result;
|
|
|
|
segment->raw = raw;
|
|
segment->superblock = superblock;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
int ocf_metadata_segment_init(
|
|
struct ocf_metadata_segment **self,
|
|
struct ocf_cache *cache,
|
|
struct ocf_metadata_raw *raw,
|
|
ocf_flush_page_synch_t lock_page_pfn,
|
|
ocf_flush_page_synch_t unlock_page_pfn,
|
|
struct ocf_metadata_segment *superblock)
|
|
{
|
|
struct ocf_metadata_segment *segment;
|
|
int result;
|
|
|
|
segment = env_vzalloc(sizeof(*segment));
|
|
if (!segment)
|
|
return -OCF_ERR_NO_MEM;
|
|
|
|
result = ocf_metadata_segment_init_in_place(segment,
|
|
cache, raw, lock_page_pfn, unlock_page_pfn,
|
|
superblock);
|
|
|
|
if (result)
|
|
env_vfree(segment);
|
|
else
|
|
*self = segment;
|
|
|
|
return result;
|
|
}
|
|
|
|
void ocf_metadata_segment_destroy(struct ocf_cache *cache,
|
|
struct ocf_metadata_segment *self)
|
|
{
|
|
if (!self)
|
|
return;
|
|
|
|
ocf_metadata_raw_deinit(cache, self->raw);
|
|
env_vfree(self);
|
|
}
|
|
|
|
static void ocf_metadata_generic_complete(void *priv, int error)
|
|
{
|
|
struct ocf_metadata_context *context = priv;
|
|
|
|
OCF_PL_NEXT_ON_SUCCESS_RET(context->pipeline, error);
|
|
}
|
|
|
|
static void ocf_metadata_check_crc_skip(ocf_pipeline_t pipeline,
|
|
void *priv, ocf_pipeline_arg_t arg, bool skip_on_dirty_shutdown)
|
|
{
|
|
struct ocf_metadata_context *context = priv;
|
|
int segment_id = ocf_pipeline_arg_get_int(arg);
|
|
struct ocf_metadata_segment *segment = context->ctrl->segment[segment_id];
|
|
ocf_cache_t cache = context->cache;
|
|
uint32_t crc;
|
|
uint32_t superblock_crc;
|
|
bool clean_shutdown;
|
|
|
|
clean_shutdown = ocf_metadata_superblock_get_clean_shutdown(
|
|
segment->superblock);
|
|
if (!clean_shutdown && skip_on_dirty_shutdown)
|
|
OCF_PL_NEXT_RET(pipeline);
|
|
|
|
crc = ocf_metadata_raw_checksum(cache, segment->raw);
|
|
superblock_crc = ocf_metadata_superblock_get_checksum(segment->superblock,
|
|
segment_id);
|
|
|
|
if (crc != superblock_crc) {
|
|
/* Checksum does not match */
|
|
if (!clean_shutdown) {
|
|
ocf_cache_log(cache, log_warn,
|
|
"Loading %s WARNING, invalid checksum\n",
|
|
ocf_metadata_segment_names[segment_id]);
|
|
} else {
|
|
ocf_cache_log(cache, log_err,
|
|
"Loading %s ERROR, invalid checksum\n",
|
|
ocf_metadata_segment_names[segment_id]);
|
|
OCF_PL_FINISH_RET(pipeline, -OCF_ERR_INVAL);
|
|
}
|
|
}
|
|
|
|
ocf_pipeline_next(pipeline);
|
|
}
|
|
|
|
void ocf_metadata_check_crc(ocf_pipeline_t pipeline,
|
|
void *priv, ocf_pipeline_arg_t arg)
|
|
{
|
|
ocf_metadata_check_crc_skip(pipeline, priv, arg, false);
|
|
}
|
|
|
|
void ocf_metadata_check_crc_if_clean(ocf_pipeline_t pipeline,
|
|
void *priv, ocf_pipeline_arg_t arg)
|
|
{
|
|
ocf_metadata_check_crc_skip(pipeline, priv, arg, true);
|
|
}
|
|
|
|
|
|
void ocf_metadata_calculate_crc(ocf_pipeline_t pipeline,
|
|
void *priv, ocf_pipeline_arg_t arg)
|
|
{
|
|
struct ocf_metadata_context *context = priv;
|
|
int segment_id = ocf_pipeline_arg_get_int(arg);
|
|
struct ocf_metadata_segment *segment = context->ctrl->segment[segment_id];
|
|
|
|
ocf_metadata_superblock_set_checksum(segment->superblock, segment_id,
|
|
ocf_metadata_raw_checksum(context->cache, segment->raw));
|
|
|
|
ocf_pipeline_next(pipeline);
|
|
}
|
|
|
|
void ocf_metadata_flush_segment(ocf_pipeline_t pipeline,
|
|
void *priv, ocf_pipeline_arg_t arg)
|
|
{
|
|
struct ocf_metadata_context *context = priv;
|
|
int segment = ocf_pipeline_arg_get_int(arg);
|
|
struct ocf_metadata_ctrl *ctrl = context->ctrl;
|
|
ocf_cache_t cache = context->cache;
|
|
|
|
ocf_metadata_raw_flush_all(cache, &ctrl->raw_desc[segment],
|
|
ocf_metadata_generic_complete, context);
|
|
}
|
|
|
|
void ocf_metadata_load_segment(ocf_pipeline_t pipeline,
|
|
void *priv, ocf_pipeline_arg_t arg)
|
|
{
|
|
struct ocf_metadata_context *context = priv;
|
|
int segment = ocf_pipeline_arg_get_int(arg);
|
|
struct ocf_metadata_ctrl *ctrl = context->ctrl;
|
|
ocf_cache_t cache = context->cache;
|
|
|
|
ocf_metadata_raw_load_all(cache, &ctrl->raw_desc[segment],
|
|
ocf_metadata_generic_complete, context);
|
|
}
|