From 196437f9bc2b258bb9026922489a0f511f64e57a Mon Sep 17 00:00:00 2001 From: Adam Rutkowski Date: Tue, 21 Dec 2021 18:16:23 +0100 Subject: [PATCH] Zero superblock before writing metadata This is the first step towards atomic initialization of metadata on cache disk. Signed-off-by: Adam Rutkowski --- src/metadata/metadata.c | 10 +++++ src/metadata/metadata.h | 3 ++ src/metadata/metadata_raw.c | 57 +++++++++++++++++++++++++++- src/metadata/metadata_raw.h | 20 ++++++++++ src/metadata/metadata_raw_volatile.c | 9 +++++ src/metadata/metadata_raw_volatile.h | 5 +++ src/metadata/metadata_superblock.c | 10 +++++ src/metadata/metadata_superblock.h | 3 ++ src/mngt/ocf_mngt_cache.c | 26 +++++++++++++ 9 files changed, 141 insertions(+), 2 deletions(-) diff --git a/src/metadata/metadata.c b/src/metadata/metadata.c index 9c033df..ac43b33 100644 --- a/src/metadata/metadata.c +++ b/src/metadata/metadata.c @@ -1628,6 +1628,16 @@ void ocf_metadata_load_properties(ocf_volume_t volume, OCF_CMPL_RET(priv, result, NULL); } +void ocf_metadata_zero_superblock(ocf_cache_t cache, + ocf_metadata_end_t cmpl, void *context) +{ + struct ocf_metadata_ctrl *ctrl = (struct ocf_metadata_ctrl *) + cache->metadata.priv; + + ocf_metadata_sb_zero(ctrl->segment[metadata_segment_sb_config], + cmpl, context); +} + /* metadata segment data + iterators */ struct query_cores_data { diff --git a/src/metadata/metadata.h b/src/metadata/metadata.h index 630b470..9f0ef00 100644 --- a/src/metadata/metadata.h +++ b/src/metadata/metadata.h @@ -217,4 +217,7 @@ static inline ocf_cache_line_t ocf_metadata_collision_table_entries( return cache->device->collision_table_entries; } +void ocf_metadata_zero_superblock(ocf_cache_t cache, + ocf_metadata_end_t cmpl, void *context); + #endif /* METADATA_H_ */ diff --git a/src/metadata/metadata_raw.c b/src/metadata/metadata_raw.c index 3276443..f19560e 100644 --- a/src/metadata/metadata_raw.c +++ b/src/metadata/metadata_raw.c @@ -41,13 +41,21 @@ static uint32_t _raw_ram_segment_size_on_ssd(struct ocf_metadata_raw *raw) return OCF_DIV_ROUND_UP(raw->ssd_pages, alignment) * alignment; } + +static uint32_t _raw_ram_segment_size_on_ssd_total(struct ocf_metadata_raw *raw) +{ + uint32_t size = _raw_ram_segment_size_on_ssd(raw) * + (raw->flapping ? 2 : 1); + + return size; +} + /* * Check if page is valid for specified RAW descriptor */ static bool _raw_ssd_page_is_valid(struct ocf_metadata_raw *raw, uint32_t page) { - uint32_t size = _raw_ram_segment_size_on_ssd(raw) * - (raw->flapping ? 2 : 1); + uint32_t size = _raw_ram_segment_size_on_ssd_total(raw); ENV_BUG_ON(page < raw->ssd_pages_offset); ENV_BUG_ON(page >= (raw->ssd_pages_offset + size)); @@ -235,6 +243,47 @@ static int _raw_ram_update(ocf_cache_t cache, } +static int raw_ram_zero_do_asynch_fill(ocf_cache_t cache, + ctx_data_t *data, uint32_t page, void *context) +{ + ctx_data_zero(cache->owner, data, PAGE_SIZE); + + return 0; +} + +struct ocf_raw_ram_zero_ctx +{ + ocf_metadata_end_t cmpl; + void *priv; +}; + +static void raw_ram_zero_end(ocf_cache_t cache, + void *context, int error) +{ + struct ocf_raw_ram_zero_ctx *zero_ctx = context; + + zero_ctx->cmpl(zero_ctx->priv, error); + env_free(zero_ctx); +} + +static void raw_ram_zero(ocf_cache_t cache, struct ocf_metadata_raw *raw, + ocf_metadata_end_t cmpl, void *priv) +{ + struct ocf_raw_ram_zero_ctx *ctx; + + ctx = env_malloc(sizeof(*ctx), ENV_MEM_NORMAL); + if (!ctx) + cmpl(priv, -OCF_ERR_NO_MEM); + ctx->cmpl = cmpl; + ctx->priv = priv; + + metadata_io_write_i_asynch(cache, cache->mngt_queue, ctx, + raw->ssd_pages_offset, + _raw_ram_segment_size_on_ssd_total(raw), + 0, raw_ram_zero_do_asynch_fill, + raw_ram_zero_end, NULL); +} + struct _raw_ram_load_all_context { struct ocf_metadata_raw *raw; uint64_t ssd_pages_offset; @@ -603,6 +652,7 @@ static const struct raw_iface IRAW[metadata_raw_type_max] = { .page = _raw_ram_page, .access = _raw_ram_access, .update = _raw_ram_update, + .zero = raw_ram_zero, .load_all = _raw_ram_load_all, .flush_all = _raw_ram_flush_all, .flush_mark = _raw_ram_flush_mark, @@ -617,6 +667,7 @@ static const struct raw_iface IRAW[metadata_raw_type_max] = { .page = raw_dynamic_page, .access = raw_dynamic_access, .update = raw_dynamic_update, + .zero = raw_ram_zero, .load_all = raw_dynamic_load_all, .flush_all = raw_dynamic_flush_all, .flush_mark = raw_dynamic_flush_mark, @@ -631,6 +682,7 @@ static const struct raw_iface IRAW[metadata_raw_type_max] = { .page = _raw_ram_page, .access = _raw_ram_access, .update = raw_volatile_update, + .zero = raw_volatile_zero, .load_all = raw_volatile_load_all, .flush_all = raw_volatile_flush_all, .flush_mark = raw_volatile_flush_mark, @@ -645,6 +697,7 @@ static const struct raw_iface IRAW[metadata_raw_type_max] = { .page = _raw_ram_page, .access = _raw_ram_access, .update = _raw_ram_update, + .zero = raw_ram_zero, .load_all = _raw_ram_load_all, .flush_all = _raw_ram_flush_all, .flush_mark = raw_atomic_flush_mark, diff --git a/src/metadata/metadata_raw.h b/src/metadata/metadata_raw.h index b016dee..f262709 100644 --- a/src/metadata/metadata_raw.h +++ b/src/metadata/metadata_raw.h @@ -129,6 +129,9 @@ struct raw_iface { int (*update)(ocf_cache_t cache, struct ocf_metadata_raw *raw, ctx_data_t *data, uint64_t page, uint64_t count); + void (*zero)(ocf_cache_t cache, struct ocf_metadata_raw *raw, + ocf_metadata_end_t cmpl, void *priv); + void (*load_all)(ocf_cache_t cache, struct ocf_metadata_raw *raw, ocf_metadata_end_t cmpl, void *priv, unsigned flapping_idx); @@ -265,6 +268,23 @@ static inline int ocf_metadata_raw_update(ocf_cache_t cache, return raw->iface->update(cache, raw, data, page, count); } +/** + * @brief Zero metadata + * @details NOTE: this is fo management purposes only, no synchronization with + * I/O is guarangeed + * + * @param cache - Cache instance + * @param raw - RAW descriptor + * @param cmpl - completion callback + * @param priv - completion callback private context + */ +static inline void ocf_metadata_raw_zero(ocf_cache_t cache, + struct ocf_metadata_raw *raw, ocf_metadata_end_t cmpl, + void *priv) +{ + raw->iface->zero(cache, raw, cmpl, priv); +} + /** * @brief Load all entries from SSD cache (cahce cache) * diff --git a/src/metadata/metadata_raw_volatile.c b/src/metadata/metadata_raw_volatile.c index a7b4e15..8a4a720 100644 --- a/src/metadata/metadata_raw_volatile.c +++ b/src/metadata/metadata_raw_volatile.c @@ -37,6 +37,15 @@ int raw_volatile_update(ocf_cache_t cache, return 0; } +/* + * RAW volatile Implementation - Zero - implemented as noop + */ +void raw_volatile_zero(ocf_cache_t cache, struct ocf_metadata_raw *raw, + ocf_metadata_end_t cmpl, void *context) +{ + cmpl(context, 0); +} + /* * RAW volatile Implementation - Load all metadata elements from SSD */ diff --git a/src/metadata/metadata_raw_volatile.h b/src/metadata/metadata_raw_volatile.h index fe3a71e..8a28564 100644 --- a/src/metadata/metadata_raw_volatile.h +++ b/src/metadata/metadata_raw_volatile.h @@ -24,6 +24,11 @@ int raw_volatile_update(ocf_cache_t cache, struct ocf_metadata_raw *raw, ctx_data_t *data, uint64_t page, uint64_t count); +/* + * RAW volatile Implementation - Zero + */ +void raw_volatile_zero(ocf_cache_t cache, struct ocf_metadata_raw *raw, + ocf_metadata_end_t cmpl, void *context); /* * RAW volatile Implementation - Load all metadata elements from SSD */ diff --git a/src/metadata/metadata_superblock.c b/src/metadata/metadata_superblock.c index 52772a3..f4eab78 100644 --- a/src/metadata/metadata_superblock.c +++ b/src/metadata/metadata_superblock.c @@ -504,6 +504,7 @@ struct ocf_metadata_superblock { struct ocf_metadata_segment segment; struct ocf_superblock_config *config; + ocf_cache_t cache; }; #define _ocf_segment_to_sb(_segment) \ @@ -529,6 +530,7 @@ int ocf_metadata_superblock_init( } sb->config = ocf_metadata_raw_get_mem(sb->segment.raw); + sb->cache = cache; *self = &sb->segment; return 0; @@ -752,3 +754,11 @@ void ocf_metadata_sb_crc_recovery(ocf_cache_t cache, ocf_pipeline_next(pipeline); } + +void ocf_metadata_sb_zero(struct ocf_metadata_segment *self, + ocf_metadata_end_t cmpl, void *priv) +{ + struct ocf_metadata_superblock *sb = _ocf_segment_to_sb(self); + + ocf_metadata_raw_zero(sb->cache, sb->segment.raw, cmpl, priv); +} diff --git a/src/metadata/metadata_superblock.h b/src/metadata/metadata_superblock.h index 16e0285..073abe3 100644 --- a/src/metadata/metadata_superblock.h +++ b/src/metadata/metadata_superblock.h @@ -131,4 +131,7 @@ int ocf_metadata_read_sb(ocf_ctx_t ctx, ocf_volume_t volume, void ocf_metadata_sb_crc_recovery(ocf_cache_t cache, ocf_metadata_end_t cmpl, void *priv); +void ocf_metadata_sb_zero(struct ocf_metadata_segment *self, + ocf_metadata_end_t cmpl, void *priv); + #endif /* METADATA_SUPERBLOCK_H_ */ diff --git a/src/mngt/ocf_mngt_cache.c b/src/mngt/ocf_mngt_cache.c index affe120..6e08f94 100644 --- a/src/mngt/ocf_mngt_cache.c +++ b/src/mngt/ocf_mngt_cache.c @@ -1476,6 +1476,30 @@ static void _ocf_mngt_init_promotion(ocf_pipeline_t pipeline, ocf_pipeline_next(pipeline); } +static void _ocf_mngt_zero_superblock_complete(void *priv, int error) +{ + struct ocf_cache_attach_context *context = priv; + ocf_cache_t cache = context->cache; + + if (error) { + ocf_cache_log(cache, log_err, + "ERROR: Failed to clear superblock\n"); + OCF_PL_FINISH_RET(context->pipeline, -OCF_ERR_WRITE_CACHE); + } + + ocf_pipeline_next(context->pipeline); +} + +static void _ocf_mngt_zero_superblock(ocf_pipeline_t pipeline, + void *priv, ocf_pipeline_arg_t arg) +{ + struct ocf_cache_attach_context *context = priv; + ocf_cache_t cache = context->cache; + + ocf_metadata_zero_superblock(cache, + _ocf_mngt_zero_superblock_complete, context); +} + static void _ocf_mngt_attach_flush_metadata_complete(void *priv, int error) { struct ocf_cache_attach_context *context = priv; @@ -1685,6 +1709,7 @@ struct ocf_pipeline_properties _ocf_mngt_cache_attach_pipeline_properties = { OCF_PL_STEP(_ocf_mngt_init_cleaner), OCF_PL_STEP(_ocf_mngt_init_promotion), OCF_PL_STEP(_ocf_mngt_attach_init_instance), + OCF_PL_STEP(_ocf_mngt_zero_superblock), OCF_PL_STEP(_ocf_mngt_attach_flush_metadata), OCF_PL_STEP(_ocf_mngt_attach_discard), OCF_PL_STEP(_ocf_mngt_attach_flush), @@ -2139,6 +2164,7 @@ struct ocf_pipeline_properties _ocf_mngt_cache_standby_attach_pipeline_propertie OCF_PL_STEP(_ocf_mngt_standby_init_cleaning), OCF_PL_STEP(_ocf_mngt_standby_preapre_mempool), OCF_PL_STEP(_ocf_mngt_standby_init_pio_concurrency), + OCF_PL_STEP(_ocf_mngt_zero_superblock), OCF_PL_STEP(_ocf_mngt_attach_flush_metadata), OCF_PL_STEP(_ocf_mngt_attach_discard), OCF_PL_STEP(_ocf_mngt_attach_flush),