diff --git a/src/metadata/metadata.c b/src/metadata/metadata.c index 42658ef..5eb4466 100644 --- a/src/metadata/metadata.c +++ b/src/metadata/metadata.c @@ -394,7 +394,6 @@ static void ocf_metadata_raw_info(struct ocf_cache *cache, void ocf_metadata_deinit_variable_size(struct ocf_cache *cache) { - int result = 0; uint32_t i = 0; struct ocf_metadata_ctrl *ctrl = (struct ocf_metadata_ctrl *) @@ -409,8 +408,7 @@ void ocf_metadata_deinit_variable_size(struct ocf_cache *cache) */ for (i = metadata_segment_variable_size_start; i < metadata_segment_max; i++) { - result |= ocf_metadata_raw_deinit(cache, - &(ctrl->raw_desc[i])); + ocf_metadata_segment_destroy(cache, ctrl->segment[i]); } } @@ -440,11 +438,16 @@ static void ocf_metadata_deinit_fixed_size(struct ocf_cache *cache) struct ocf_metadata_ctrl *ctrl = (struct ocf_metadata_ctrl *) cache->metadata.priv; + struct ocf_metadata_segment *superblock = + ctrl->segment[metadata_segment_sb_config]; + for (i = 0; i < metadata_segment_fixed_size_max; i++) { - result |= ocf_metadata_raw_deinit(cache, - &(ctrl->raw_desc[i])); + if (i != metadata_segment_sb_config) + ocf_metadata_segment_destroy(cache, ctrl->segment[i]); } + ocf_metadata_superblock_destroy(cache, superblock); + env_vfree(ctrl); cache->metadata.priv = NULL; @@ -513,6 +516,7 @@ static int ocf_metadata_init_fixed_size(struct ocf_cache *cache, struct ocf_core_meta_runtime *core_meta_runtime; struct ocf_user_part_config *part_config; struct ocf_user_part_runtime *part_runtime; + struct ocf_metadata_segment *superblock; ocf_core_t core; ocf_core_id_t core_id; uint32_t i = 0; @@ -529,9 +533,25 @@ static int ocf_metadata_init_fixed_size(struct ocf_cache *cache, return -OCF_ERR_NO_MEM; metadata->priv = ctrl; + result = ocf_metadata_superblock_init( + &ctrl->segment[metadata_segment_sb_config], cache, + &ctrl->raw_desc[metadata_segment_sb_config]); + if (result) { + ocf_metadata_deinit_fixed_size(cache); + return result; + } + + superblock = ctrl->segment[metadata_segment_sb_config]; + for (i = 0; i < metadata_segment_fixed_size_max; i++) { - result |= ocf_metadata_raw_init(cache, NULL, NULL, - &(ctrl->raw_desc[i])); + if (i == metadata_segment_sb_config) + continue; + result |= ocf_metadata_segment_init( + &ctrl->segment[i], + cache, + &ctrl->raw_desc[i], + NULL, NULL, + superblock); if (result) break; } @@ -609,6 +629,7 @@ int ocf_metadata_init_variable_size(struct ocf_cache *cache, (struct ocf_cache_line_settings *)&cache->metadata.settings; ocf_flush_page_synch_t lock_page, unlock_page; uint64_t device_lines; + struct ocf_metadata_segment *superblock; OCF_DEBUG_TRACE(cache); @@ -669,6 +690,8 @@ int ocf_metadata_init_variable_size(struct ocf_cache *cache, OCF_DEBUG_PARAM(cache, "Metadata end pages = %u", ctrl->start_page + ctrl->count_pages); + superblock = ctrl->segment[metadata_segment_sb_config]; + /* * Initialize all dynamic size RAW types */ @@ -683,8 +706,12 @@ int ocf_metadata_init_variable_size(struct ocf_cache *cache, lock_page = unlock_page = NULL; } - result |= ocf_metadata_raw_init(cache, lock_page, unlock_page, - &(ctrl->raw_desc[i])); + result |= ocf_metadata_segment_init( + &ctrl->segment[i], + cache, + &ctrl->raw_desc[i], + lock_page, unlock_page, + superblock); if (result) goto finalize; @@ -991,6 +1018,7 @@ void ocf_metadata_flush_all(ocf_cache_t cache, context->priv = priv; context->pipeline = pipeline; context->cache = cache; + context->ctrl = cache->metadata.priv; ocf_pipeline_next(pipeline); } @@ -1113,6 +1141,7 @@ void ocf_metadata_load_all(ocf_cache_t cache, context->priv = priv; context->pipeline = pipeline; context->cache = cache; + context->ctrl = cache->metadata.priv; ocf_pipeline_next(pipeline); } @@ -1272,6 +1301,7 @@ static void _ocf_metadata_load_recovery_legacy(ocf_cache_t cache, context->priv = priv; context->pipeline = pipeline; context->cache = cache; + context->ctrl = cache->metadata.priv; ocf_pipeline_next(pipeline); } @@ -1416,6 +1446,7 @@ static void _ocf_metadata_load_recovery_atomic(ocf_cache_t cache, context->priv = priv; context->pipeline = pipeline; context->cache = cache; + context->ctrl = cache->metadata.priv; ocf_pipeline_next(pipeline); } diff --git a/src/metadata/metadata_internal.h b/src/metadata/metadata_internal.h index 95adabf..3e1a694 100644 --- a/src/metadata/metadata_internal.h +++ b/src/metadata/metadata_internal.h @@ -8,6 +8,7 @@ #include #include "../ocf_cache_priv.h" +#include "metadata_segment.h" #include "metadata_segment_id.h" #include "metadata_raw.h" @@ -23,6 +24,7 @@ struct ocf_metadata_ctrl { uint32_t device_lines; size_t mapping_size; struct ocf_metadata_raw raw_desc[metadata_segment_max]; + struct ocf_metadata_segment *segment[metadata_segment_max]; }; struct ocf_metadata_context { @@ -30,6 +32,7 @@ struct ocf_metadata_context { void *priv; ocf_pipeline_t pipeline; ocf_cache_t cache; + struct ocf_metadata_ctrl *ctrl; struct ocf_metadata_raw segment_copy[metadata_segment_fixed_size_max]; }; diff --git a/src/metadata/metadata_raw.h b/src/metadata/metadata_raw.h index ffc12c7..ea62b7f 100644 --- a/src/metadata/metadata_raw.h +++ b/src/metadata/metadata_raw.h @@ -6,6 +6,8 @@ #ifndef __METADATA_RAW_H__ #define __METADATA_RAW_H__ +#include "metadata_segment_id.h" + /** * @file metadata_raw.h * @brief Metadata RAW container implementation @@ -306,4 +308,9 @@ static inline void _raw_bug_on(struct ocf_metadata_raw *raw, uint32_t entry) int _raw_ram_flush_do_page_cmp(const void *item1, const void *item2); +static inline void *ocf_metadata_raw_get_mem(struct ocf_metadata_raw *raw) +{ + return raw->mem_pool; +} + #endif /* METADATA_RAW_H_ */ diff --git a/src/metadata/metadata_segment.c b/src/metadata/metadata_segment.c index 2a0b767..6cf9c04 100644 --- a/src/metadata/metadata_segment.c +++ b/src/metadata/metadata_segment.c @@ -4,6 +4,65 @@ */ #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) { @@ -16,30 +75,32 @@ 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 = ocf_pipeline_arg_get_int(arg); - struct ocf_metadata_ctrl *ctrl; - struct ocf_superblock_config *sb_config; + 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; - ctrl = (struct ocf_metadata_ctrl *)cache->metadata.priv; - sb_config = METADATA_MEM_POOL(ctrl, metadata_segment_sb_config); - - if (!sb_config->clean_shutdown && skip_on_dirty_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, &(ctrl->raw_desc[segment])); + crc = ocf_metadata_raw_checksum(cache, segment->raw); + superblock_crc = ocf_metadata_superblock_get_checksum(segment->superblock, + segment_id); - if (crc != sb_config->checksum[segment]) { + if (crc != superblock_crc) { /* Checksum does not match */ - if (!sb_config->clean_shutdown) { + if (!clean_shutdown) { ocf_cache_log(cache, log_warn, "Loading %s WARNING, invalid checksum", - ocf_metadata_segment_names[segment]); + ocf_metadata_segment_names[segment_id]); } else { ocf_cache_log(cache, log_err, "Loading %s ERROR, invalid checksum", - ocf_metadata_segment_names[segment]); + ocf_metadata_segment_names[segment_id]); OCF_PL_FINISH_RET(pipeline, -OCF_ERR_INVAL); } } @@ -64,16 +125,11 @@ void ocf_metadata_calculate_crc(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; - struct ocf_superblock_config *sb_config; - ocf_cache_t cache = context->cache; + int segment_id = ocf_pipeline_arg_get_int(arg); + struct ocf_metadata_segment *segment = context->ctrl->segment[segment_id]; - ctrl = (struct ocf_metadata_ctrl *)cache->metadata.priv; - sb_config = METADATA_MEM_POOL(ctrl, metadata_segment_sb_config); - - sb_config->checksum[segment] = ocf_metadata_raw_checksum(cache, - &(ctrl->raw_desc[segment])); + ocf_metadata_superblock_set_checksum(segment->superblock, segment_id, + ocf_metadata_raw_checksum(context->cache, segment->raw)); ocf_pipeline_next(pipeline); } @@ -83,11 +139,9 @@ void ocf_metadata_flush_segment(ocf_pipeline_t pipeline, { struct ocf_metadata_context *context = priv; int segment = ocf_pipeline_arg_get_int(arg); - struct ocf_metadata_ctrl *ctrl; + struct ocf_metadata_ctrl *ctrl = context->ctrl; ocf_cache_t cache = context->cache; - ctrl = (struct ocf_metadata_ctrl *)cache->metadata.priv; - ocf_metadata_raw_flush_all(cache, &ctrl->raw_desc[segment], ocf_metadata_generic_complete, context); } @@ -97,11 +151,9 @@ void ocf_metadata_load_segment(ocf_pipeline_t pipeline, { struct ocf_metadata_context *context = priv; int segment = ocf_pipeline_arg_get_int(arg); - struct ocf_metadata_ctrl *ctrl; + struct ocf_metadata_ctrl *ctrl = context->ctrl; ocf_cache_t cache = context->cache; - ctrl = (struct ocf_metadata_ctrl *)cache->metadata.priv; - ocf_metadata_raw_load_all(cache, &ctrl->raw_desc[segment], ocf_metadata_generic_complete, context); } diff --git a/src/metadata/metadata_segment.h b/src/metadata/metadata_segment.h index 3ef71d2..d0ccf32 100644 --- a/src/metadata/metadata_segment.h +++ b/src/metadata/metadata_segment.h @@ -9,6 +9,23 @@ #include "metadata_raw.h" #include +struct ocf_metadata_segment +{ + struct ocf_metadata_raw *raw; + struct ocf_metadata_segment *superblock; +}; + +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); + +void ocf_metadata_segment_destroy(struct ocf_cache *cache, + struct ocf_metadata_segment *self); + void ocf_metadata_check_crc_if_clean(ocf_pipeline_t pipeline, void *priv, ocf_pipeline_arg_t arg); diff --git a/src/metadata/metadata_superblock.c b/src/metadata/metadata_superblock.c index 5f563d8..e690200 100644 --- a/src/metadata/metadata_superblock.c +++ b/src/metadata/metadata_superblock.c @@ -25,6 +25,13 @@ #define OCF_DEBUG_PARAM(cache, format, ...) #endif +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); /** * @brief Super Block - Set Shutdown Status @@ -45,12 +52,14 @@ void ocf_metadata_set_shutdown_status(ocf_cache_t cache, /* * Get metadata hash service control structure */ + /* TODO: get metadata ctrl from args rather than via cache */ ctrl = (struct ocf_metadata_ctrl *) cache->metadata.priv; /* * Get super block */ - superblock = METADATA_MEM_POOL(ctrl, metadata_segment_sb_config); + superblock = ocf_metadata_raw_get_mem( + &ctrl->raw_desc[metadata_segment_sb_config]); /* Set shutdown status */ superblock->clean_shutdown = shutdown_status; @@ -271,7 +280,8 @@ void ocf_metadata_load_superblock(ocf_cache_t cache, ocf_metadata_end_t cmpl, OCF_DEBUG_TRACE(cache); - ctrl = (struct ocf_metadata_ctrl *) cache->metadata.priv; + /* TODO: get ctrl from args rather than from cache */ + ctrl = cache->metadata.priv; ENV_BUG_ON(!ctrl); sb_config = METADATA_MEM_POOL(ctrl, metadata_segment_sb_config); @@ -291,6 +301,7 @@ void ocf_metadata_load_superblock(ocf_cache_t cache, ocf_metadata_end_t cmpl, context->priv = priv; context->pipeline = pipeline; context->cache = cache; + context->ctrl = cache->metadata.priv; ocf_pipeline_next(pipeline); } @@ -318,9 +329,8 @@ static void ocf_metadata_calculate_crc_sb_config(ocf_pipeline_t pipeline, struct ocf_metadata_context *context = priv; struct ocf_metadata_ctrl *ctrl; struct ocf_superblock_config *sb_config; - ocf_cache_t cache = context->cache; - ctrl = (struct ocf_metadata_ctrl *)cache->metadata.priv; + ctrl = context->ctrl; sb_config = METADATA_MEM_POOL(ctrl, metadata_segment_sb_config); sb_config->checksum[metadata_segment_sb_config] = env_crc32(0, @@ -419,6 +429,77 @@ void ocf_metadata_flush_superblock(ocf_cache_t cache, context->priv = priv; context->pipeline = pipeline; context->cache = cache; + context->ctrl = cache->metadata.priv; ocf_pipeline_next(pipeline); } + +struct ocf_metadata_superblock +{ + struct ocf_metadata_segment segment; + struct ocf_superblock_config *config; +}; + +#define _ocf_segment_to_sb(_segment) \ + container_of(_segment, struct ocf_metadata_superblock, segment); + +int ocf_metadata_superblock_init( + struct ocf_metadata_segment **self, + struct ocf_cache *cache, + struct ocf_metadata_raw *raw) +{ + struct ocf_metadata_superblock *sb = env_vzalloc(sizeof(*sb)); + int result; + + if (!sb) + return -OCF_ERR_NO_MEM; + + result = ocf_metadata_segment_init_in_place(&sb->segment, cache, + raw, NULL, NULL, &sb->segment); + + if (result) { + env_vfree(sb); + return result; + } + + sb->config = ocf_metadata_raw_get_mem(sb->segment.raw); + + *self = &sb->segment; + return 0; +} + + +void ocf_metadata_superblock_destroy( + struct ocf_cache *cache, + struct ocf_metadata_segment *self) +{ + ocf_metadata_segment_destroy(cache, self); +} + +uint32_t ocf_metadata_superblock_get_checksum( + struct ocf_metadata_segment *self, + enum ocf_metadata_segment_id segment) +{ + struct ocf_metadata_superblock *sb = _ocf_segment_to_sb(self); + + return sb->config->checksum[segment]; +} + +void ocf_metadata_superblock_set_checksum( + struct ocf_metadata_segment *self, + enum ocf_metadata_segment_id segment, + uint32_t csum) +{ + struct ocf_metadata_superblock *sb = _ocf_segment_to_sb(self); + + sb->config->checksum[segment] = csum; +} + +bool ocf_metadata_superblock_get_clean_shutdown( + struct ocf_metadata_segment *self) +{ + struct ocf_metadata_superblock *sb = _ocf_segment_to_sb(self); + + return sb->config->clean_shutdown; +} + diff --git a/src/metadata/metadata_superblock.h b/src/metadata/metadata_superblock.h index 73f88e7..c4b1968 100644 --- a/src/metadata/metadata_superblock.h +++ b/src/metadata/metadata_superblock.h @@ -64,6 +64,8 @@ struct ocf_superblock_runtime { uint32_t cleaning_thread_access; }; +struct ocf_metadata_ctrl; + void ocf_metadata_set_shutdown_status(ocf_cache_t cache, enum ocf_metadata_shutdown_status shutdown_status, ocf_metadata_end_t cmpl, void *priv); @@ -74,4 +76,25 @@ void ocf_metadata_load_superblock(ocf_cache_t cache, void ocf_metadata_flush_superblock(ocf_cache_t cache, ocf_metadata_end_t cmpl, void *priv); +int ocf_metadata_superblock_init( + struct ocf_metadata_segment **self, + struct ocf_cache *cache, + struct ocf_metadata_raw *raw); + +void ocf_metadata_superblock_destroy( + struct ocf_cache *cache, + struct ocf_metadata_segment *self); + +uint32_t ocf_metadata_superblock_get_checksum( + struct ocf_metadata_segment *self, + enum ocf_metadata_segment_id segment); + +void ocf_metadata_superblock_set_checksum( + struct ocf_metadata_segment *self, + enum ocf_metadata_segment_id segment, + uint32_t csum); + +bool ocf_metadata_superblock_get_clean_shutdown( + struct ocf_metadata_segment *self); + #endif /* METADATA_SUPERBLOCK_H_ */