From dfd89dd43a2938c94cafc4db3be9144d29689a65 Mon Sep 17 00:00:00 2001 From: Adam Rutkowski Date: Sun, 14 Apr 2019 15:25:58 -0400 Subject: [PATCH] Probe core UUIDs from metadata Signed-off-by: Adam Rutkowski --- inc/ocf_metadata.h | 24 ++ inc/ocf_mngt.h | 15 -- inc/ocf_volume.h | 2 +- src/metadata/metadata.c | 36 +++ src/metadata/metadata_hash.c | 349 +++++++++++++++++++++++++-- src/metadata/metadata_raw.c | 11 +- src/metadata/metadata_raw.h | 8 +- src/metadata/metadata_raw_dynamic.c | 3 +- src/metadata/metadata_raw_dynamic.h | 3 +- src/metadata/metadata_raw_volatile.c | 3 +- src/metadata/metadata_raw_volatile.h | 3 +- src/metadata/metadata_structs.h | 25 ++ 12 files changed, 426 insertions(+), 56 deletions(-) diff --git a/inc/ocf_metadata.h b/inc/ocf_metadata.h index 95bc83e..f2951cf 100644 --- a/inc/ocf_metadata.h +++ b/inc/ocf_metadata.h @@ -83,6 +83,30 @@ typedef void (*ocf_metadata_probe_end_t)(void *priv, int error, void ocf_metadata_probe(ocf_ctx_t ctx, ocf_volume_t volume, ocf_metadata_probe_end_t cmpl, void *priv); +/** + * @brief Metadata probe for cores completion callback + * + * @param[in] priv Completion context + * @param[in] error Error code (zero on success) + * @param[in] num_cores Number of cores in cache metadata + */ +typedef void (*ocf_metadata_probe_cores_end_t)(void *priv, int error, + unsigned int num_cores); + +/** + * @brief Probe cache device for associated cores + * + * @param[in] ctx handle to object designating ocf context + * @param[in] volume Cache volume + * @param[in,out] uuids Array of uuids + * @param[in] uuid_count Size of @uuid array + * @param[in] cmpl Completion callback + * @param[in] priv Completion context + */ +void ocf_metadata_probe_cores(ocf_ctx_t ctx, ocf_volume_t volume, + struct ocf_volume_uuid *uuids, uint32_t uuid_count, + ocf_metadata_probe_cores_end_t cmpl, void *priv); + /** * @brief Check if sectors in cache line before given address are invalid * diff --git a/inc/ocf_mngt.h b/inc/ocf_mngt.h index 3019826..b71214b 100644 --- a/inc/ocf_mngt.h +++ b/inc/ocf_mngt.h @@ -217,21 +217,6 @@ int ocf_mngt_cache_visit(ocf_ctx_t ctx, ocf_mngt_cache_visitor_t visitor, int ocf_mngt_cache_visit_reverse(ocf_ctx_t ctx, ocf_mngt_cache_visitor_t visitor, void *cntx); -/** - * @brief Cache probe status - */ -struct ocf_mngt_cache_probe_status { - /** - * @brief Gracefully shutdown for cache detected - */ - bool clean_shutdown; - - /** - * @brief Cache is dirty and requires flushing - */ - bool cache_dirty; -}; - /** * @brief Cache start configuration */ diff --git a/inc/ocf_volume.h b/inc/ocf_volume.h index 68586ed..ed1b6b5 100644 --- a/inc/ocf_volume.h +++ b/inc/ocf_volume.h @@ -29,7 +29,7 @@ struct ocf_volume_uuid { size_t size; /*!< UUID data size */ - const void *data; + void *data; /*!< UUID data content */ }; diff --git a/src/metadata/metadata.c b/src/metadata/metadata.c index 9a7a4c0..d8e6897 100644 --- a/src/metadata/metadata.c +++ b/src/metadata/metadata.c @@ -360,3 +360,39 @@ void ocf_metadata_probe(ocf_ctx_t ctx, ocf_volume_t volume, if (result) cmpl(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_query_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; + const struct ocf_metadata_iface *iface; + + context = env_vzalloc(sizeof(*context)); + if (!context) + cmpl(priv, -OCF_ERR_NO_MEM, 0); + context->cmpl = cmpl; + context->priv = priv; + + iface = metadata_hash_get_iface(); + iface->query_cores(ctx, volume, uuids, uuids_count, + ocf_metadata_query_cores_end, context); +} + + diff --git a/src/metadata/metadata_hash.c b/src/metadata/metadata_hash.c index 4fc8726..a3b809c 100644 --- a/src/metadata/metadata_hash.c +++ b/src/metadata/metadata_hash.c @@ -251,8 +251,7 @@ static int ocf_metadata_hash_calculate_metadata_size( raw->entries_in_page); /* Update offset for next container */ - count_pages += ocf_metadata_raw_size_on_ssd( - cache, raw); + count_pages += ocf_metadata_raw_size_on_ssd(raw); } /* @@ -446,27 +445,16 @@ static void ocf_metadata_hash_deinit(struct ocf_cache *cache) ENV_BUG(); } -static int ocf_metadata_hash_init(struct ocf_cache *cache, - ocf_cache_line_size_t cache_line_size) +static struct ocf_metadata_hash_ctrl *ocf_metadata_hash_ctrl_init( + bool metadata_volatile) { struct ocf_metadata_hash_ctrl *ctrl = NULL; - struct ocf_cache_line_settings *settings = - (struct ocf_cache_line_settings *)&cache->metadata.settings; - uint32_t i = 0; uint32_t page = 0; - int result = 0; - - OCF_DEBUG_TRACE(cache); - - ENV_WARN_ON(cache->metadata.iface_priv); + uint32_t i = 0; ctrl = env_vzalloc(sizeof(*ctrl)); if (!ctrl) - return -ENOMEM; - - cache->metadata.iface_priv = ctrl; - - ocf_metadata_config_init(cache, settings, cache_line_size); + return NULL; /* Initial setup of RAW containers */ for (i = 0; i < metadata_segment_fixed_size_max; i++) { @@ -477,7 +465,7 @@ static int ocf_metadata_hash_init(struct ocf_cache *cache, /* Default type for metadata RAW container */ raw->raw_type = metadata_raw_type_ram; - if (cache->metadata.is_volatile) { + if (metadata_volatile) { raw->raw_type = metadata_raw_type_volatile; } else if (i == metadata_segment_core_uuid) { raw->raw_type = metadata_raw_type_dynamic; @@ -499,11 +487,35 @@ static int ocf_metadata_hash_init(struct ocf_cache *cache, raw->entries_in_page); /* Update offset for next container */ - page += ocf_metadata_raw_size_on_ssd(cache, raw); + page += ocf_metadata_raw_size_on_ssd(raw); } ctrl->count_pages = page; + return ctrl; +} + +int ocf_metadata_hash_init(struct ocf_cache *cache, + ocf_cache_line_size_t cache_line_size) +{ + struct ocf_metadata_hash_ctrl *ctrl = NULL; + struct ocf_metadata *metadata = &cache->metadata; + struct ocf_cache_line_settings *settings = + (struct ocf_cache_line_settings *)&metadata->settings; + uint32_t i = 0; + int result = 0; + + OCF_DEBUG_TRACE(cache); + + ENV_WARN_ON(metadata->iface_priv); + + ocf_metadata_config_init(cache, settings, cache_line_size); + + ctrl = ocf_metadata_hash_ctrl_init(metadata->is_volatile); + if (!ctrl) + return -ENOMEM; + metadata->iface_priv = ctrl; + for (i = 0; i < metadata_segment_fixed_size_max; i++) { result |= ocf_metadata_raw_init(cache, &(ctrl->raw_desc[i])); if (result) @@ -531,7 +543,305 @@ static int ocf_metadata_hash_init(struct ocf_cache *cache, return result; } +/* 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_hash_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 = -ENODATA; + 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_hash_query_cores_data_read(ctx, + &context->data.core_config, + &core_config, sizeof(core_config)); + if (core_config.added) { + 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_hash_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 = -EINVAL; + goto exit; + } + if (muuid->size > context->params.uuids[core_idx].size) { + error = -ENOSPC; + 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_vfree(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); + if (!io) { + err = -OCF_ERR_NO_MEM; + goto exit_error; + } + + /* Setup IO */ + ocf_io_configure(io, + PAGES_TO_BYTES(page), + PAGES_TO_BYTES(num_pages), + OCF_READ, 0, 0); + + 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 segment, + struct ocf_metadata_hash_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 = ocf_volume_get_max_io_size(volume) / + PAGE_SIZE; + int err = 0; + + /* Allocate data */ + segment_data->data = ctx_data_alloc(owner, + ctrl->raw_desc[segment].ssd_pages); + if (!segment_data->data) { + err = -ENOMEM; + 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_hash_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_hash_ctrl *ctrl = NULL; + struct query_cores_context *context; + int err; + + if (count > OCF_CORE_MAX) { + cmpl(priv, -EINVAL, 0); + return; + } + + /* intialize query context */ + context = env_vzalloc(sizeof(*context)); + if (!context) { + cmpl(priv, -ENOMEM, 0); + return; + } + 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_hash_ctrl_init(false); + if (!ctrl) { + err = -ENOMEM; + 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); +} /* * Initialize hash metadata interface @@ -2456,6 +2766,7 @@ static void ocf_metadata_hash_set_partition_info( static const struct ocf_metadata_iface metadata_hash_iface = { .init = ocf_metadata_hash_init, .deinit = ocf_metadata_hash_deinit, + .query_cores = ocf_metadata_hash_query_cores, .init_variable_size = ocf_metadata_hash_init_variable_size, .deinit_variable_size = ocf_metadata_hash_deinit_variable_size, .init_hash_table = ocf_metadata_hash_init_hash_table, diff --git a/src/metadata/metadata_raw.c b/src/metadata/metadata_raw.c index d3b9292..4f8941f 100644 --- a/src/metadata/metadata_raw.c +++ b/src/metadata/metadata_raw.c @@ -109,8 +109,7 @@ static int _raw_ram_init(ocf_cache_t cache, /* * RAM Implementation - Size of */ -static size_t _raw_ram_size_of(ocf_cache_t cache, - struct ocf_metadata_raw *raw) +static size_t _raw_ram_size_of(ocf_cache_t cache, struct ocf_metadata_raw *raw) { size_t size; @@ -123,8 +122,7 @@ static size_t _raw_ram_size_of(ocf_cache_t cache, /* * RAM Implementation - Size on SSD */ -static uint32_t _raw_ram_size_on_ssd(ocf_cache_t cache, - struct ocf_metadata_raw *raw) +static uint32_t _raw_ram_size_on_ssd(struct ocf_metadata_raw *raw) { const size_t alignment = 128 * KiB / PAGE_SIZE; @@ -644,11 +642,10 @@ int ocf_metadata_raw_deinit(ocf_cache_t cache, return result; } -size_t ocf_metadata_raw_size_on_ssd(ocf_cache_t cache, - struct ocf_metadata_raw* raw) +size_t ocf_metadata_raw_size_on_ssd(struct ocf_metadata_raw* raw) { ENV_BUG_ON(raw->raw_type < metadata_raw_type_min); ENV_BUG_ON(raw->raw_type >= metadata_raw_type_max); - return IRAW[raw->raw_type].size_on_ssd(cache, raw); + return IRAW[raw->raw_type].size_on_ssd(raw); } diff --git a/src/metadata/metadata_raw.h b/src/metadata/metadata_raw.h index f665605..2e9e7a9 100644 --- a/src/metadata/metadata_raw.h +++ b/src/metadata/metadata_raw.h @@ -93,13 +93,11 @@ struct raw_iface { /** * @brief Return size which metadata take on cache device * - * @param cache Cache instance * @param raw RAW container of metadata * * @return Number of pages (4 kiB) on cache device */ - uint32_t (*size_on_ssd)(ocf_cache_t cache, - struct ocf_metadata_raw *raw); + uint32_t (*size_on_ssd)(struct ocf_metadata_raw *raw); uint32_t (*checksum)(ocf_cache_t cache, struct ocf_metadata_raw *raw); @@ -175,12 +173,10 @@ static inline size_t ocf_metadata_raw_size_of(ocf_cache_t cache, /** * @brief Get SSD footprint * - * @param cache - Cache instance * @param raw - RAW descriptor * @return Size on SSD */ -size_t ocf_metadata_raw_size_on_ssd(struct ocf_cache* cache, - struct ocf_metadata_raw* raw); +size_t ocf_metadata_raw_size_on_ssd(struct ocf_metadata_raw* raw); /** * @brief Calculate metadata checksum diff --git a/src/metadata/metadata_raw_dynamic.c b/src/metadata/metadata_raw_dynamic.c index 65573d5..35031bd 100644 --- a/src/metadata/metadata_raw_dynamic.c +++ b/src/metadata/metadata_raw_dynamic.c @@ -188,8 +188,7 @@ size_t raw_dynamic_size_of(ocf_cache_t cache, /* * RAW DYNAMIC Implementation - Size on SSD */ -uint32_t raw_dynamic_size_on_ssd(ocf_cache_t cache, - struct ocf_metadata_raw *raw) +uint32_t raw_dynamic_size_on_ssd(struct ocf_metadata_raw *raw) { const size_t alignment = 128 * KiB / PAGE_SIZE; diff --git a/src/metadata/metadata_raw_dynamic.h b/src/metadata/metadata_raw_dynamic.h index cd02d83..6f22614 100644 --- a/src/metadata/metadata_raw_dynamic.h +++ b/src/metadata/metadata_raw_dynamic.h @@ -32,8 +32,7 @@ size_t raw_dynamic_size_of(ocf_cache_t cache, /* * RAW DYNAMIC Implementation - Size on SSD */ -uint32_t raw_dynamic_size_on_ssd(ocf_cache_t cache, - struct ocf_metadata_raw *raw); +uint32_t raw_dynamic_size_on_ssd(struct ocf_metadata_raw *raw); /* * RAW DYNAMIC Implementation - Checksum diff --git a/src/metadata/metadata_raw_volatile.c b/src/metadata/metadata_raw_volatile.c index 9605fae..85d4cca 100644 --- a/src/metadata/metadata_raw_volatile.c +++ b/src/metadata/metadata_raw_volatile.c @@ -12,8 +12,7 @@ /* * RAW volatile Implementation - Size on SSD */ -uint32_t raw_volatile_size_on_ssd(ocf_cache_t cache, - struct ocf_metadata_raw *raw) +uint32_t raw_volatile_size_on_ssd(struct ocf_metadata_raw *raw) { return 0; } diff --git a/src/metadata/metadata_raw_volatile.h b/src/metadata/metadata_raw_volatile.h index db8b276..e2deb93 100644 --- a/src/metadata/metadata_raw_volatile.h +++ b/src/metadata/metadata_raw_volatile.h @@ -9,8 +9,7 @@ /* * RAW volatile Implementation - Size on SSD */ -uint32_t raw_volatile_size_on_ssd(ocf_cache_t cache, - struct ocf_metadata_raw *raw); +uint32_t raw_volatile_size_on_ssd(struct ocf_metadata_raw *raw); /* * RAW volatile Implementation - Checksum diff --git a/src/metadata/metadata_structs.h b/src/metadata/metadata_structs.h index 81a9998..5a72fbc 100644 --- a/src/metadata/metadata_structs.h +++ b/src/metadata/metadata_structs.h @@ -11,6 +11,7 @@ #include "../cleaning/cleaning.h" #include "../ocf_request.h" + /** * @file metadata_priv.h * @brief Metadata private structures @@ -81,6 +82,16 @@ struct ocf_metadata_layout_iface { ocf_cache_line_t phy); }; +/** + * @brief Query cores completion callback + * + * @param priv - Caller private data + * @param error - Operation error status + * @param num_cores - Number of cores in metadata + */ +typedef void (*ocf_metadata_query_cores_end_t)(void *priv, int error, + unsigned int num_cores); + /** * OCF Metadata interface */ @@ -108,6 +119,20 @@ struct ocf_metadata_iface { ocf_cache_line_size_t cache_line_size, ocf_metadata_layout_t layout); + /** + * @brief Query metadata for added cores + * + * @param[in] owner - OCF context + * @param[in] volume - volume to probe + * @param[in,out] uuid - array of uuids + * @param[in] count - size of uuid array + * @param[in] cmpl - completion callback + * @param[in] priv - completion private data + */ + void (*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); + /** * @brief Metadata cache line location on pages interface */