143 lines
3.8 KiB
C
143 lines
3.8 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);
|
|
}
|
|
|
|
void ocf_metadata_check_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_cache_t cache = context->cache;
|
|
uint32_t crc;
|
|
uint32_t superblock_crc;
|
|
|
|
crc = ocf_metadata_raw_checksum(cache, segment->raw);
|
|
superblock_crc = ocf_metadata_superblock_get_checksum(segment->superblock,
|
|
segment_id);
|
|
if (crc != superblock_crc) {
|
|
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_CRC_MISMATCH);
|
|
}
|
|
|
|
ocf_pipeline_next(pipeline);
|
|
}
|
|
|
|
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_id = ocf_pipeline_arg_get_int(arg);
|
|
struct ocf_metadata_segment *segment = context->ctrl->segment[segment_id];
|
|
ocf_cache_t cache = context->cache;
|
|
unsigned next_flapping_idx =
|
|
ocf_metadata_superblock_get_next_flapping_idx(
|
|
segment->superblock);
|
|
|
|
next_flapping_idx = segment->raw->flapping ? next_flapping_idx : 0;
|
|
|
|
ocf_metadata_raw_flush_all(cache, segment->raw,
|
|
ocf_metadata_generic_complete, context,
|
|
next_flapping_idx);
|
|
}
|
|
|
|
void ocf_metadata_load_segment(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_cache_t cache = context->cache;
|
|
unsigned flapping_idx = ocf_metadata_superblock_get_flapping_idx(
|
|
segment->superblock);
|
|
|
|
flapping_idx = segment->raw->flapping ? flapping_idx : 0;
|
|
|
|
ocf_metadata_raw_load_all(cache, segment->raw,
|
|
ocf_metadata_generic_complete, context, flapping_idx);
|
|
}
|