ocf/src/metadata/metadata_segment.c
Robert Baldyga af43a240d3 Return more specific error on CRC mismatch
Signed-off-by: Robert Baldyga <robert.baldyga@intel.com>
2022-03-28 22:42:59 +02:00

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);
}