From 092403a425a2a2f555710d060f789640526aeccb Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Mon, 17 Jan 2022 10:34:28 +0100 Subject: [PATCH 1/3] Check superblock CRC before it is used Superblock can be used during load of other sections, so we need to check its CRC before other sections are loaded. Signed-off-by: Robert Baldyga --- src/metadata/metadata_superblock.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/metadata/metadata_superblock.c b/src/metadata/metadata_superblock.c index 09852f29..5ac71633 100644 --- a/src/metadata/metadata_superblock.c +++ b/src/metadata/metadata_superblock.c @@ -225,7 +225,6 @@ struct ocf_pipeline_arg ocf_metadata_load_sb_store_segment_args[] = { }; struct ocf_pipeline_arg ocf_metadata_load_sb_load_segment_args[] = { - OCF_PL_ARG_INT(metadata_segment_sb_config), OCF_PL_ARG_INT(metadata_segment_sb_runtime), OCF_PL_ARG_INT(metadata_segment_part_config), OCF_PL_ARG_INT(metadata_segment_part_runtime), @@ -253,9 +252,11 @@ struct ocf_pipeline_properties ocf_metadata_load_sb_pipeline_props = { .steps = { OCF_PL_STEP_FOREACH(ocf_metadata_store_segment, ocf_metadata_load_sb_store_segment_args), + OCF_PL_STEP_ARG_INT(ocf_metadata_load_segment, + metadata_segment_sb_config), + OCF_PL_STEP(ocf_metadata_check_crc_sb_config), OCF_PL_STEP_FOREACH(ocf_metadata_load_segment, ocf_metadata_load_sb_load_segment_args), - OCF_PL_STEP(ocf_metadata_check_crc_sb_config), OCF_PL_STEP_FOREACH(ocf_metadata_check_crc, ocf_metadata_load_sb_check_crc_args), OCF_PL_STEP_FOREACH(ocf_metadata_check_crc_if_clean, From c09a49224dfe881ba44a80cd9128a628250451e6 Mon Sep 17 00:00:00 2001 From: Adam Rutkowski Date: Mon, 24 Jan 2022 15:31:06 +0100 Subject: [PATCH 2/3] Explicitly validate superblock after load Signed-off-by: Adam Rutkowski --- inc/ocf_def.h | 2 +- src/engine/cache_engine.c | 7 ++ src/engine/cache_engine.h | 12 +-- src/metadata/metadata.c | 71 +++++++-------- src/metadata/metadata.h | 2 +- src/metadata/metadata_superblock.c | 140 +++++++++++++++++++++-------- src/metadata/metadata_superblock.h | 4 + src/mngt/ocf_mngt_cache.c | 4 +- src/ocf_cache.c | 5 ++ src/ocf_cache_priv.h | 2 + 10 files changed, 159 insertions(+), 90 deletions(-) diff --git a/inc/ocf_def.h b/inc/ocf_def.h index 89fb2e0b..1a9865e4 100644 --- a/inc/ocf_def.h +++ b/inc/ocf_def.h @@ -83,7 +83,7 @@ /** * Maximum value of a valid core sequence number */ -#define OCF_SEQ_NO_MAX (65535UL) +#define OCF_SEQ_NO_MAX ((1ULL << (sizeof(ocf_core_id_t) * 8)) - 1) /* * Invalid value of core sequence number */ diff --git a/src/engine/cache_engine.c b/src/engine/cache_engine.c index 1dac7355..3ec0e21e 100644 --- a/src/engine/cache_engine.c +++ b/src/engine/cache_engine.c @@ -286,3 +286,10 @@ void ocf_engine_hndl_ops_req(struct ocf_request *req) ocf_engine_push_req_back(req, true); } + +bool ocf_req_cache_mode_has_lazy_write(ocf_req_cache_mode_t mode) +{ + return ocf_cache_mode_is_valid((ocf_cache_mode_t)mode) && + ocf_mngt_cache_mode_has_lazy_write( + (ocf_cache_mode_t)mode); +} diff --git a/src/engine/cache_engine.h b/src/engine/cache_engine.h index 91c440b3..d99e17d6 100644 --- a/src/engine/cache_engine.h +++ b/src/engine/cache_engine.h @@ -52,17 +52,7 @@ static inline const char *ocf_get_io_iface_name(ocf_cache_mode_t cache_mode) return iface ? iface->name : "Unknown"; } -static inline bool ocf_cache_mode_is_valid(ocf_cache_mode_t mode) -{ - return mode >= ocf_cache_mode_wt && mode < ocf_cache_mode_max; -} - -static inline bool ocf_req_cache_mode_has_lazy_write(ocf_req_cache_mode_t mode) -{ - return ocf_cache_mode_is_valid((ocf_cache_mode_t)mode) && - ocf_mngt_cache_mode_has_lazy_write( - (ocf_cache_mode_t)mode); -} +bool ocf_req_cache_mode_has_lazy_write(ocf_req_cache_mode_t mode); bool ocf_fallback_pt_is_on(ocf_cache_t cache); diff --git a/src/metadata/metadata.c b/src/metadata/metadata.c index 898f7c71..8f44b12c 100644 --- a/src/metadata/metadata.c +++ b/src/metadata/metadata.c @@ -1773,49 +1773,29 @@ static int ocf_metadata_read_sb(ocf_ctx_t ctx, ocf_volume_t volume, return result; } +struct ocf_metadata_load_properties_ctx +{ + ocf_cache_t cache; + ocf_metadata_load_properties_end_t cmpl; + void *priv; +}; + static void ocf_metadata_load_properties_cmpl( struct ocf_metadata_read_sb_ctx *context) { struct ocf_metadata_load_properties properties; struct ocf_superblock_config *superblock = &context->superblock; - ocf_metadata_load_properties_end_t cmpl = context->priv1; - void *priv = context->priv2; - ocf_ctx_t ctx = context->ctx; - - if (superblock->magic_number != CACHE_MAGIC_NUMBER) { - ocf_log(ctx, log_info, "Cannot detect pre-existing metadata\n"); - OCF_CMPL_RET(priv, -OCF_ERR_NO_METADATA, NULL); - } - - if (METADATA_VERSION() != superblock->metadata_version) { - ocf_log(ctx, log_err, "Metadata version mismatch!\n"); - OCF_CMPL_RET(priv, -OCF_ERR_METADATA_VER, NULL); - } - - if (!ocf_cache_line_size_is_valid(superblock->line_size)) { - ocf_log(ctx, log_err, "ERROR: Invalid cache line size!\n"); - OCF_CMPL_RET(priv, -OCF_ERR_INVAL, NULL); - } - - if ((unsigned)superblock->metadata_layout >= ocf_metadata_layout_max) { - ocf_log(ctx, log_err, "ERROR: Invalid metadata layout!\n"); - OCF_CMPL_RET(priv, -OCF_ERR_INVAL, NULL); - } + struct ocf_metadata_load_properties_ctx *load_context = context->priv1; + ocf_metadata_load_properties_end_t cmpl = load_context->cmpl; + void *priv = load_context->priv; + ocf_cache_t cache = load_context->cache; + int ret; - if (superblock->cache_mode >= ocf_cache_mode_max) { - ocf_log(ctx, log_err, "ERROR: Invalid cache mode!\n"); - OCF_CMPL_RET(priv, -OCF_ERR_INVAL, NULL); - } + env_vfree(load_context); - if (superblock->clean_shutdown > ocf_metadata_clean_shutdown) { - ocf_log(ctx, log_err, "ERROR: Invalid shutdown status!\n"); - OCF_CMPL_RET(priv, -OCF_ERR_INVAL, NULL); - } - - if (superblock->dirty_flushed > DIRTY_FLUSHED) { - ocf_log(ctx, log_err, "ERROR: Invalid flush status!\n"); - OCF_CMPL_RET(priv, -OCF_ERR_INVAL, NULL); - } + ret = ocf_metadata_validate_superblock(cache, superblock); + if (ret) + OCF_CMPL_RET(priv, ret, NULL); properties.line_size = superblock->line_size; properties.layout = superblock->metadata_layout; @@ -1827,17 +1807,28 @@ static void ocf_metadata_load_properties_cmpl( OCF_CMPL_RET(priv, 0, &properties); } -void ocf_metadata_load_properties(ocf_volume_t volume, +void ocf_metadata_load_properties(ocf_cache_t cache, ocf_metadata_load_properties_end_t cmpl, void *priv) { + ocf_volume_t volume = &cache->device->volume; + struct ocf_metadata_load_properties_ctx *context; int result; + context = env_vmalloc(sizeof(*context)); + if (!context) + OCF_CMPL_RET(priv, -OCF_ERR_NO_MEM, NULL); + context->cmpl = cmpl; + context->priv = priv; + context->cache = cache; + OCF_DEBUG_TRACE(cache); - result = ocf_metadata_read_sb(volume->cache->owner, volume, - ocf_metadata_load_properties_cmpl, cmpl, priv); - if (result) + result = ocf_metadata_read_sb(cache->owner, volume, + ocf_metadata_load_properties_cmpl, context, NULL); + if (result) { + env_vfree(context); OCF_CMPL_RET(priv, result, NULL); + } } /* metadata segment data + iterators */ diff --git a/src/metadata/metadata.h b/src/metadata/metadata.h index a084bb95..2023c411 100644 --- a/src/metadata/metadata.h +++ b/src/metadata/metadata.h @@ -207,7 +207,7 @@ struct ocf_metadata_load_properties { typedef void (*ocf_metadata_load_properties_end_t)(void *priv, int error, struct ocf_metadata_load_properties *properties); -void ocf_metadata_load_properties(ocf_volume_t volume, +void ocf_metadata_load_properties(ocf_cache_t cache, ocf_metadata_load_properties_end_t cmpl, void *priv); static inline ocf_cache_line_t ocf_metadata_collision_table_entries( diff --git a/src/metadata/metadata_superblock.c b/src/metadata/metadata_superblock.c index 5ac71633..62ad0077 100644 --- a/src/metadata/metadata_superblock.c +++ b/src/metadata/metadata_superblock.c @@ -10,6 +10,7 @@ #include "metadata_superblock.h" #include "../ocf_priv.h" #include "../utils/utils_io.h" +#include "../utils/utils_cache_line.h" #define OCF_METADATA_SUPERBLOCK_DEBUG 0 @@ -97,29 +98,117 @@ static void ocf_metadata_store_segment(ocf_pipeline_t pipeline, ocf_pipeline_next(pipeline); } -static void ocf_metadata_check_crc_sb_config(ocf_pipeline_t pipeline, + +#define ocf_log_invalid_superblock(param) \ + ocf_cache_log(cache, log_err, \ + "Loading %s: invalid %s\n", \ + ocf_metadata_segment_names[ \ + metadata_segment_sb_config], \ + param); + + +int ocf_metadata_validate_superblock(ocf_cache_t cache, + struct ocf_superblock_config *superblock) +{ + uint32_t crc; + + if (superblock->magic_number != CACHE_MAGIC_NUMBER) { + ocf_cache_log(cache, log_info, "Cannot detect pre-existing " + "metadata\n"); + return -OCF_ERR_NO_METADATA; + } + + if (METADATA_VERSION() != superblock->metadata_version) { + ocf_cache_log(cache, log_err, "Metadata version mismatch!\n"); + return -OCF_ERR_METADATA_VER; + } + + crc = env_crc32(0, (void *)superblock, + offsetof(struct ocf_superblock_config, checksum)); + + if (crc != superblock->checksum[metadata_segment_sb_config]) { + ocf_log_invalid_superblock("checksum"); + return -OCF_ERR_INVAL; + } + + if (superblock->clean_shutdown > ocf_metadata_clean_shutdown) { + ocf_log_invalid_superblock("shutdown status"); + return -OCF_ERR_INVAL; + } + + if (superblock->dirty_flushed > DIRTY_FLUSHED) { + ocf_log_invalid_superblock("flush status"); + return -OCF_ERR_INVAL; + } + + if (superblock->flapping_idx > 1) { + ocf_log_invalid_superblock("flapping index"); + return -OCF_ERR_INVAL; + } + + if (superblock->cache_mode < 0 || + superblock->cache_mode >= ocf_cache_mode_max) { + ocf_log_invalid_superblock("cache mode"); + return -OCF_ERR_INVAL; + } + + if (env_strnlen(superblock->name, sizeof(superblock->name)) >= + OCF_CACHE_NAME_SIZE) { + ocf_log_invalid_superblock("name"); + return -OCF_ERR_INVAL; + } + + if (superblock->valid_parts_no > OCF_USER_IO_CLASS_MAX) { + ocf_log_invalid_superblock("partition count"); + return -OCF_ERR_INVAL; + } + + if (!ocf_cache_line_size_is_valid(superblock->line_size)) { + ocf_log_invalid_superblock("cache line size"); + return -OCF_ERR_INVAL; + } + + if ((unsigned)superblock->metadata_layout >= ocf_metadata_layout_max) { + ocf_log_invalid_superblock("metadata layout"); + return -OCF_ERR_INVAL; + } + + if (superblock->core_count > OCF_CORE_MAX) { + ocf_log_invalid_superblock("core count"); + return -OCF_ERR_INVAL; + } + + if (superblock->cleaning_policy_type < 0 || + superblock->cleaning_policy_type >= ocf_cleaning_max) { + ocf_log_invalid_superblock("cleaning policy"); + return -OCF_ERR_INVAL; + } + + if (superblock->promotion_policy_type < 0 || + superblock->promotion_policy_type >= + ocf_promotion_max) { + ocf_log_invalid_superblock("promotion policy"); + return -OCF_ERR_INVAL; + } + + return 0; +} + +static void _ocf_metadata_validate_superblock(ocf_pipeline_t pipeline, void *priv, ocf_pipeline_arg_t arg) { struct ocf_metadata_context *context = priv; struct ocf_metadata_ctrl *ctrl; - struct ocf_superblock_config *sb_config; + struct ocf_superblock_config *superblock; ocf_cache_t cache = context->cache; - int segment = metadata_segment_sb_config; - uint32_t crc; + int ret; ctrl = (struct ocf_metadata_ctrl *)cache->metadata.priv; - sb_config = METADATA_MEM_POOL(ctrl, metadata_segment_sb_config); - - crc = env_crc32(0, (void *)sb_config, - offsetof(struct ocf_superblock_config, checksum)); + superblock = METADATA_MEM_POOL(ctrl, metadata_segment_sb_config); - if (crc != sb_config->checksum[segment]) { - /* Checksum does not match */ - ocf_cache_log(cache, log_err, - "Loading %s ERROR, invalid checksum\n", - ocf_metadata_segment_names[segment]); - OCF_PL_FINISH_RET(pipeline, -OCF_ERR_INVAL); - } + ret = ocf_metadata_validate_superblock(cache, superblock); + if (ret) + OCF_PL_FINISH_RET(pipeline, ret); ocf_pipeline_next(pipeline); } @@ -128,8 +217,6 @@ static void ocf_metadata_load_superblock_post(ocf_pipeline_t pipeline, void *priv, ocf_pipeline_arg_t arg) { struct ocf_metadata_context *context = priv; - struct ocf_metadata_ctrl *ctrl; - struct ocf_superblock_config *sb_config; ocf_cache_t cache = context->cache; struct ocf_metadata_uuid *muuid; struct ocf_volume_uuid uuid; @@ -137,9 +224,6 @@ static void ocf_metadata_load_superblock_post(ocf_pipeline_t pipeline, ocf_core_t core; ocf_core_id_t core_id; - ctrl = (struct ocf_metadata_ctrl *)cache->metadata.priv; - sb_config = METADATA_MEM_POOL(ctrl, metadata_segment_sb_config); - for_each_core_metadata(cache, core, core_id) { muuid = ocf_metadata_get_core_uuid(cache, core_id); uuid.data = muuid->data; @@ -153,20 +237,6 @@ static void ocf_metadata_load_superblock_post(ocf_pipeline_t pipeline, core->has_volume = true; } - /* Restore all dynamics items */ - - if (sb_config->core_count > OCF_CORE_MAX) { - ocf_cache_log(cache, log_err, - "Loading cache state ERROR, invalid cores count\n"); - OCF_PL_FINISH_RET(pipeline, -OCF_ERR_INVAL); - } - - if (sb_config->valid_parts_no > OCF_USER_IO_CLASS_MAX) { - ocf_cache_log(cache, log_err, - "Loading cache state ERROR, invalid partition count\n"); - OCF_PL_FINISH_RET(pipeline, -OCF_ERR_INVAL); - } - ocf_pipeline_next(pipeline); } @@ -254,7 +324,7 @@ struct ocf_pipeline_properties ocf_metadata_load_sb_pipeline_props = { ocf_metadata_load_sb_store_segment_args), OCF_PL_STEP_ARG_INT(ocf_metadata_load_segment, metadata_segment_sb_config), - OCF_PL_STEP(ocf_metadata_check_crc_sb_config), + OCF_PL_STEP(_ocf_metadata_validate_superblock), OCF_PL_STEP_FOREACH(ocf_metadata_load_segment, ocf_metadata_load_sb_load_segment_args), OCF_PL_STEP_FOREACH(ocf_metadata_check_crc, diff --git a/src/metadata/metadata_superblock.h b/src/metadata/metadata_superblock.h index f624e6d0..2000b84c 100644 --- a/src/metadata/metadata_superblock.h +++ b/src/metadata/metadata_superblock.h @@ -104,4 +104,8 @@ unsigned ocf_metadata_superblock_get_flapping_idx( unsigned ocf_metadata_superblock_get_next_flapping_idx( struct ocf_metadata_segment *self); + +int ocf_metadata_validate_superblock(ocf_cache_t cache, + struct ocf_superblock_config *superblock); + #endif /* METADATA_SUPERBLOCK_H_ */ diff --git a/src/mngt/ocf_mngt_cache.c b/src/mngt/ocf_mngt_cache.c index 54a2a67e..1369d957 100644 --- a/src/mngt/ocf_mngt_cache.c +++ b/src/mngt/ocf_mngt_cache.c @@ -940,7 +940,7 @@ static void _ocf_mngt_attach_read_properties(ocf_pipeline_t pipeline, if (context->cfg.force) OCF_PL_NEXT_RET(pipeline); - ocf_metadata_load_properties(&cache->device->volume, + ocf_metadata_load_properties(cache, _ocf_mngt_attach_read_properties_end, context); } @@ -950,7 +950,7 @@ static void _ocf_mngt_load_read_properties(ocf_pipeline_t pipeline, struct ocf_cache_attach_context *context = priv; ocf_cache_t cache = context->cache; - ocf_metadata_load_properties(&cache->device->volume, + ocf_metadata_load_properties(cache, _ocf_mngt_load_read_properties_end, context); } diff --git a/src/ocf_cache.c b/src/ocf_cache.c index cc29a495..3fa26206 100644 --- a/src/ocf_cache.c +++ b/src/ocf_cache.c @@ -26,6 +26,11 @@ int ocf_cache_set_name(ocf_cache_t cache, const char *src, size_t src_size) src, src_size); } +bool ocf_cache_mode_is_valid(ocf_cache_mode_t mode) +{ + return mode >= ocf_cache_mode_wt && mode < ocf_cache_mode_max; +} + const char *ocf_cache_get_name(ocf_cache_t cache) { OCF_CHECK_NULL(cache); diff --git a/src/ocf_cache_priv.h b/src/ocf_cache_priv.h index b0a6f77c..a1c76dce 100644 --- a/src/ocf_cache_priv.h +++ b/src/ocf_cache_priv.h @@ -185,4 +185,6 @@ static inline uint64_t ocf_get_cache_occupancy(ocf_cache_t cache) int ocf_cache_set_name(ocf_cache_t cache, const char *src, size_t src_size); +bool ocf_cache_mode_is_valid(ocf_cache_mode_t mode); + #endif /* __OCF_CACHE_PRIV_H__ */ From d78842d9a0485608536b0b0b0bde21a2432ec9b8 Mon Sep 17 00:00:00 2001 From: Adam Rutkowski Date: Tue, 25 Jan 2022 16:36:01 +0100 Subject: [PATCH 3/3] Remove ocf_metadata_probe_cores() implementation This function must be fixed to work with metadata flapping. Until then mark as not supported Signed-off-by: Adam Rutkowski --- src/metadata/metadata.c | 332 +--------------------------------------- 1 file changed, 1 insertion(+), 331 deletions(-) diff --git a/src/metadata/metadata.c b/src/metadata/metadata.c index 8f44b12c..cc76cb3b 100644 --- a/src/metadata/metadata.c +++ b/src/metadata/metadata.c @@ -1831,310 +1831,6 @@ void ocf_metadata_load_properties(ocf_cache_t cache, } } -/* metadata segment data + iterators */ -struct query_cores_data -{ - /* array of data */ - ctx_data_t *data; - /* current metadata entry counter */ - uint32_t entry; - /* number of entries per page */ - uint32_t entries_in_page; -}; - -/* query cores context */ -struct query_cores_context -{ - ocf_ctx_t ctx; - - struct ocf_superblock_config superblock; - struct ocf_metadata_uuid muuid; - - struct { - struct query_cores_data core_uuids; - struct query_cores_data core_config; - struct query_cores_data superblock; - } data; - - env_atomic count; - env_atomic error; - - /* OCF entry point parameters */ - struct { - struct ocf_volume_uuid *uuids; - uint32_t uuids_count; - void *priv; - ocf_metadata_query_cores_end_t cmpl; - } params; -}; - -/* copy next metadata entry from data to memory buffer */ -static void ocf_metadata_query_cores_data_read(ocf_ctx_t ctx, - struct query_cores_data *data, - void *buf, uint32_t size) -{ - if (data->entry > 0 && data->entry % data->entries_in_page == 0) { - ctx_data_seek_check(ctx, data->data, - ctx_data_seek_current, - PAGE_SIZE - data->entries_in_page * size); - } - - ctx_data_rd_check(ctx, buf, data->data, size); - - ++data->entry; -} - -static void ocf_metadata_query_cores_end(struct query_cores_context *context, - int error) -{ - ocf_ctx_t ctx = context->ctx; - unsigned i, core_idx; - struct ocf_metadata_uuid *muuid = &context->muuid; - struct ocf_core_meta_config core_config; - unsigned core_count = 0; - unsigned long valid_core_bitmap[(OCF_CORE_MAX / - (sizeof(unsigned long) * 8)) + 1]; - unsigned out_cores; - - if (error) - env_atomic_cmpxchg(&context->error, 0, error); - - if (env_atomic_dec_return(&context->count)) - return; - - error = env_atomic_read(&context->error); - if (error) - goto exit; - - /* read superblock */ - ctx_data_rd_check(ctx, &context->superblock, - context->data.superblock.data, - sizeof(context->superblock)); - - if (context->superblock.magic_number != CACHE_MAGIC_NUMBER) { - error = -OCF_ERR_NO_METADATA; - goto exit; - } - - env_memset(&valid_core_bitmap, sizeof(valid_core_bitmap), 0); - - /* read valid cores from core config segment */ - for (i = 0; i < OCF_CORE_MAX; i++) { - ocf_metadata_query_cores_data_read(ctx, - &context->data.core_config, - &core_config, sizeof(core_config)); - if (core_config.valid) { - env_bit_set(i, valid_core_bitmap); - ++core_count; - } - } - - /* read core uuids */ - out_cores = OCF_MIN(core_count, context->params.uuids_count); - for (i = 0, core_idx = 0; i < OCF_CORE_MAX && core_idx < out_cores; - i++) { - ocf_metadata_query_cores_data_read(ctx, - &context->data.core_uuids, - muuid, sizeof(*muuid)); - - if (!env_bit_test(i, valid_core_bitmap)) - continue; - - if (muuid->size > OCF_VOLUME_UUID_MAX_SIZE) { - error = -OCF_ERR_INVAL; - goto exit; - } - if (muuid->size > context->params.uuids[core_idx].size) { - error = -OCF_ERR_INVAL; - goto exit; - } - - error = env_memcpy(context->params.uuids[core_idx].data, - context->params.uuids[core_idx].size, - muuid->data, muuid->size); - if (error) - goto exit; - context->params.uuids[core_idx].size = muuid->size; - - ++core_idx; - } - -exit: - /* provide actual core count to completion */ - context->params.cmpl(context->params.priv, error, core_count); - - /* free data */ - ctx_data_free(ctx, context->data.core_uuids.data); - ctx_data_free(ctx, context->data.core_config.data); - ctx_data_free(ctx, context->data.superblock.data); - - env_secure_free(context, sizeof(*context)); -} - -static void ocf_metadata_query_cores_end_io(struct ocf_io *io, int error) -{ - struct query_cores_context *context = io->priv1; - - ocf_io_put(io); - ocf_metadata_query_cores_end(context, error); -} - -static int ocf_metadata_query_cores_io(ocf_volume_t volume, - struct query_cores_context *context, ctx_data_t *data, - uint32_t offset, uint64_t page, uint32_t num_pages) -{ - struct ocf_io *io; - int err; - - env_atomic_inc(&context->count); - - /* Allocate new IO */ - io = ocf_volume_new_io(volume, NULL, - PAGES_TO_BYTES(page), - PAGES_TO_BYTES(num_pages), - OCF_READ, 0, 0); - if (!io) { - err = -OCF_ERR_NO_MEM; - goto exit_error; - } - - /* Setup IO */ - ocf_io_set_cmpl(io, context, NULL, - ocf_metadata_query_cores_end_io); - err = ocf_io_set_data(io, data, PAGES_TO_BYTES(offset)); - if (err) { - ocf_io_put(io); - goto exit_error; - } - - ocf_volume_submit_io(io); - - return 0; - -exit_error: - env_atomic_dec(&context->count); - return err; -} - -int ocf_metadata_query_cores_segment_io( - struct query_cores_context *context, - ocf_ctx_t owner, - ocf_volume_t volume, - enum ocf_metadata_segment_id segment, - struct ocf_metadata_ctrl *ctrl, - struct query_cores_data *segment_data) -{ - uint32_t pages_left; - uint32_t pages; - uint32_t addr; - uint32_t offset; - uint32_t io_count; - uint32_t i; - uint32_t max_pages_per_io; - int err = 0; - unsigned int max_io_size = ocf_volume_get_max_io_size(volume); - - if (!max_io_size) { - err = -OCF_ERR_INVAL; - goto exit; - } - - max_pages_per_io = max_io_size / PAGE_SIZE; - - /* Allocate data */ - segment_data->data = ctx_data_alloc(owner, - ctrl->raw_desc[segment].ssd_pages); - if (!segment_data->data) { - err = -OCF_ERR_NO_MEM; - goto exit; - } - - segment_data->entries_in_page = ctrl->raw_desc[segment].entries_in_page; - - io_count = OCF_DIV_ROUND_UP(ctrl->raw_desc[segment].ssd_pages, - max_pages_per_io); - - /* submit segment data I/O */ - pages_left = ctrl->raw_desc[segment].ssd_pages; - addr = ctrl->raw_desc[segment].ssd_pages_offset; - offset = 0; - i = 0; - while (pages_left) { - ENV_BUG_ON(i >= io_count); - - pages = OCF_MIN(pages_left, max_pages_per_io); - - err = ocf_metadata_query_cores_io(volume, context, - segment_data->data, offset, addr, pages); - if (err) - goto exit; - - addr += pages; - offset += pages; - pages_left -= pages; - ++i; - } - -exit: - return err; -} - -void ocf_metadata_query_cores(ocf_ctx_t owner, ocf_volume_t volume, - struct ocf_volume_uuid *uuid, uint32_t count, - ocf_metadata_query_cores_end_t cmpl, void *priv) -{ - struct ocf_metadata_ctrl *ctrl = NULL; - struct query_cores_context *context; - int err; - - if (count > OCF_CORE_MAX) - OCF_CMPL_RET(priv, -OCF_ERR_INVAL, 0); - - /* intialize query context */ - context = env_secure_alloc(sizeof(*context)); - if (!context) - OCF_CMPL_RET(priv, -OCF_ERR_NO_MEM, 0); - - ENV_BUG_ON(env_memset(context, sizeof(*context), 0)); - context->ctx = owner; - context->params.cmpl = cmpl; - context->params.priv = priv; - context->params.uuids = uuid; - context->params.uuids_count = count; - env_atomic_set(&context->count, 1); - - ctrl = ocf_metadata_ctrl_init(false); - if (!ctrl) { - err = -OCF_ERR_NO_MEM; - goto exit; - } - - /* superblock I/O */ - err = ocf_metadata_query_cores_segment_io(context, owner, - volume, metadata_segment_sb_config, ctrl, - &context->data.superblock); - if (err) - goto exit; - - /* core config I/O */ - err = ocf_metadata_query_cores_segment_io(context, owner, - volume, metadata_segment_core_uuid, ctrl, - &context->data.core_uuids); - if (err) - goto exit; - - /* core uuid I/O */ - err = ocf_metadata_query_cores_segment_io(context, owner, - volume, metadata_segment_core_config, ctrl, - &context->data.core_config); - if (err) - goto exit; -exit: - env_vfree(ctrl); - ocf_metadata_query_cores_end(context, err); -} - - static void ocf_metadata_probe_cmpl(struct ocf_metadata_read_sb_ctx *context) { struct ocf_metadata_probe_status status; @@ -2178,35 +1874,9 @@ void ocf_metadata_probe(ocf_ctx_t ctx, ocf_volume_t volume, OCF_CMPL_RET(priv, result, NULL); } -/* completion context for query_cores */ -struct ocf_metadata_query_cores_context -{ - ocf_metadata_probe_cores_end_t cmpl; - void *priv; -}; - -static void ocf_metadata_probe_cores_end(void *_context, int error, - unsigned num_cores) -{ - struct ocf_metadata_query_cores_context *context = _context; - - context->cmpl(context->priv, error, num_cores); - env_vfree(context); -} - void ocf_metadata_probe_cores(ocf_ctx_t ctx, ocf_volume_t volume, struct ocf_volume_uuid *uuids, uint32_t uuids_count, ocf_metadata_probe_cores_end_t cmpl, void *priv) { - struct ocf_metadata_query_cores_context *context; - - context = env_vzalloc(sizeof(*context)); - if (!context) - OCF_CMPL_RET(priv, -OCF_ERR_NO_MEM, 0); - - context->cmpl = cmpl; - context->priv = priv; - - ocf_metadata_query_cores(ctx, volume, uuids, uuids_count, - ocf_metadata_probe_cores_end, context); + OCF_CMPL_RET(priv, -OCF_ERR_NOT_SUPP, 0); }