diff --git a/src/metadata/metadata.c b/src/metadata/metadata.c index 6d8207d..8b642a1 100644 --- a/src/metadata/metadata.c +++ b/src/metadata/metadata.c @@ -2004,3 +2004,51 @@ void ocf_metadata_probe_cores(ocf_ctx_t ctx, ocf_volume_t volume, ocf_metadata_query_cores(ctx, volume, uuids, uuids_count, ocf_metadata_probe_cores_end, context); } + +int ocf_metadata_passive_update(ocf_cache_t cache, struct ocf_io *io) +{ + struct ocf_metadata_ctrl *ctrl = cache->metadata.priv; + ctx_data_t *data = ocf_io_get_data(io); + uint64_t io_start_page = BYTES_TO_PAGES(io->addr); + uint64_t io_end_page = io_start_page + BYTES_TO_PAGES(io->bytes); + enum ocf_metadata_segment_id update_segments[] = { + metadata_segment_sb_config, + metadata_segment_part_config, + metadata_segment_core_config, + metadata_segment_core_uuid, + metadata_segment_collision, + }; + int i; + + if (io->dir == OCF_READ) + return 0; + + if (io->addr % PAGE_SIZE || io->bytes % PAGE_SIZE) { + ocf_cache_log(cache, log_crit, + "Metadata update not aligned to page size!\n"); + return -OCF_ERR_INVAL; + } + + if (io_end_page >= ctrl->count_pages) + return 0; + + for (i = 0; i < ARRAY_SIZE(update_segments); i++) { + enum ocf_metadata_segment_id seg = update_segments[i]; + struct ocf_metadata_raw *raw = &(ctrl->raw_desc[seg]); + uint64_t raw_start_page = raw->ssd_pages_offset; + uint64_t raw_end_page = raw_start_page + raw->ssd_pages; + uint64_t overlap_start = OCF_MAX(io_start_page, raw_start_page); + uint64_t overlap_end = OCF_MIN(io_end_page, raw_end_page); + uint64_t overlap_start_data = overlap_start - io_start_page; + + if (overlap_start < overlap_end) { + ctx_data_seek(cache->owner, data, ctx_data_seek_begin, + PAGES_TO_BYTES(overlap_start_data)); + ocf_metadata_raw_update(cache, raw, data, + overlap_start - raw_start_page, + overlap_end - overlap_start); + } + } + + return 0; +} diff --git a/src/metadata/metadata.h b/src/metadata/metadata.h index 8a7e59b..6b2d4fa 100644 --- a/src/metadata/metadata.h +++ b/src/metadata/metadata.h @@ -226,4 +226,6 @@ static inline ocf_cache_line_t ocf_metadata_collision_table_entries( return cache->device->collision_table_entries; } +int ocf_metadata_passive_update(ocf_cache_t cache, struct ocf_io *io); + #endif /* METADATA_H_ */ diff --git a/src/metadata/metadata_raw.c b/src/metadata/metadata_raw.c index 15287e7..b7ee15c 100644 --- a/src/metadata/metadata_raw.c +++ b/src/metadata/metadata_raw.c @@ -188,6 +188,42 @@ static void *_raw_ram_access(ocf_cache_t cache, return _RAW_RAM_ADDR(raw, entry); } +static int _raw_ram_drain_page(ocf_cache_t cache, + struct ocf_metadata_raw *raw, ctx_data_t *data, uint32_t page) +{ + + uint32_t size = raw->entry_size * raw->entries_in_page; + ocf_cache_line_t line; + + ENV_BUG_ON(page > raw->ssd_pages); + ENV_BUG_ON(size > PAGE_SIZE); + + line = page * raw->entries_in_page; + + OCF_DEBUG_PARAM(cache, "Line = %u, Page = %u", line, page); + + ctx_data_rd_check(cache->owner, _RAW_RAM_ADDR(raw, line), data, size); + ctx_data_seek(cache->owner, data, ctx_data_seek_current, + PAGE_SIZE - size); + + return 0; +} + +/* + * RAM Implementation - update + */ +static int _raw_ram_update(ocf_cache_t cache, + struct ocf_metadata_raw *raw, ctx_data_t *data, + uint64_t page, uint64_t count) +{ + uint64_t i; + + for (i = 0; i < count; i++) + _raw_ram_drain_page(cache, raw, data, page + i); + + return 0; +} + struct _raw_ram_load_all_context { struct ocf_metadata_raw *raw; ocf_metadata_end_t cmpl; @@ -202,23 +238,9 @@ static int _raw_ram_load_all_drain(ocf_cache_t cache, { struct _raw_ram_load_all_context *context = priv; struct ocf_metadata_raw *raw = context->raw; - uint32_t size = raw->entry_size * raw->entries_in_page; - ocf_cache_line_t line; - uint32_t raw_page; - ENV_BUG_ON(!_raw_ssd_page_is_valid(raw, page)); - ENV_BUG_ON(size > PAGE_SIZE); - - raw_page = page - raw->ssd_pages_offset; - line = raw_page * raw->entries_in_page; - - OCF_DEBUG_PARAM(cache, "Line = %u, Page = %u", line, raw_page); - - ctx_data_rd_check(cache->owner, _RAW_RAM_ADDR(raw, line), data, size); - ctx_data_seek(cache->owner, data, ctx_data_seek_current, - PAGE_SIZE - size); - - return 0; + return _raw_ram_drain_page(cache, raw, data, + page - raw->ssd_pages_offset); } static void _raw_ram_load_all_complete(ocf_cache_t cache, @@ -562,6 +584,7 @@ static const struct raw_iface IRAW[metadata_raw_type_max] = { .checksum = _raw_ram_checksum, .page = _raw_ram_page, .access = _raw_ram_access, + .update = _raw_ram_update, .load_all = _raw_ram_load_all, .flush_all = _raw_ram_flush_all, .flush_mark = _raw_ram_flush_mark, @@ -575,6 +598,7 @@ static const struct raw_iface IRAW[metadata_raw_type_max] = { .checksum = raw_dynamic_checksum, .page = raw_dynamic_page, .access = raw_dynamic_access, + .update = raw_dynamic_update, .load_all = raw_dynamic_load_all, .flush_all = raw_dynamic_flush_all, .flush_mark = raw_dynamic_flush_mark, @@ -588,6 +612,7 @@ static const struct raw_iface IRAW[metadata_raw_type_max] = { .checksum = raw_volatile_checksum, .page = _raw_ram_page, .access = _raw_ram_access, + .update = raw_volatile_update, .load_all = raw_volatile_load_all, .flush_all = raw_volatile_flush_all, .flush_mark = raw_volatile_flush_mark, @@ -601,6 +626,7 @@ static const struct raw_iface IRAW[metadata_raw_type_max] = { .checksum = _raw_ram_checksum, .page = _raw_ram_page, .access = _raw_ram_access, + .update = _raw_ram_update, .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 b595d7a..d8cf9bd 100644 --- a/src/metadata/metadata_raw.h +++ b/src/metadata/metadata_raw.h @@ -125,6 +125,9 @@ struct raw_iface { void* (*access)(ocf_cache_t cache, struct ocf_metadata_raw *raw, uint32_t entry); + int (*update)(ocf_cache_t cache, struct ocf_metadata_raw *raw, + ctx_data_t *data, uint64_t page, uint64_t count); + void (*load_all)(ocf_cache_t cache, struct ocf_metadata_raw *raw, ocf_metadata_end_t cmpl, void *priv); @@ -242,6 +245,23 @@ static inline const void *ocf_metadata_raw_rd_access( ocf_cache_t cache, return raw->iface->access(cache, raw, entry); } +/** + * @brief Update metadata based on cache device I/O + * + * @param cache - Cache instance + * @param raw - RAW descriptor + * @param data - Data buffer containing metadata pages + * @param page - First metadata page + * @param count - Number of metadata pages + * @return 0 - Operation success, otherwise error + */ +static inline int ocf_metadata_raw_update(ocf_cache_t cache, + struct ocf_metadata_raw *raw, ctx_data_t *data, + uint64_t page, uint64_t count) +{ + return raw->iface->update(cache, raw, data, page, count); +} + /** * @brief Load all entries from SSD cache (cahce cache) * diff --git a/src/metadata/metadata_raw_dynamic.c b/src/metadata/metadata_raw_dynamic.c index 08453ce..3da9a5b 100644 --- a/src/metadata/metadata_raw_dynamic.c +++ b/src/metadata/metadata_raw_dynamic.c @@ -256,6 +256,72 @@ void *raw_dynamic_access(ocf_cache_t cache, return _raw_dynamic_get_item(cache, raw, entry); } +/* + * RAM DYNAMIC Implementation - update + */ +static int raw_dynamic_update_pages(ocf_cache_t cache, + struct ocf_metadata_raw *raw, ctx_data_t *data, uint64_t page, + uint64_t count, uint8_t **buffer, uint8_t *zpage) +{ + struct _raw_ctrl *ctrl = (struct _raw_ctrl *)raw->priv; + int result = 0; + uint64_t i; + int cmp; + + for (i = 0; i < count; i++) { + if (!*buffer) { + *buffer = env_secure_alloc(PAGE_SIZE); + if (!*buffer) + return -OCF_ERR_NO_MEM; + } + + ctx_data_rd_check(cache->owner, *buffer, data, PAGE_SIZE); + + result = env_memcmp(zpage, PAGE_SIZE, *buffer, PAGE_SIZE, &cmp); + if (result < 0) + return result; + + /* When page is zero set, no need to allocate space for it */ + if (cmp == 0) { + OCF_DEBUG_PARAM(cache, "Zero loaded %llu", i); + continue; + } + + OCF_DEBUG_PARAM(cache, "Non-zero loaded %llu", i); + + if (ctrl->pages[page + i]) + env_secure_free(ctrl->pages[page + i], PAGE_SIZE); + ctrl->pages[page + i] = *buffer; + *buffer = NULL; + + env_atomic_inc(&ctrl->count); + } + + return 0; +} + +int raw_dynamic_update(ocf_cache_t cache, + struct ocf_metadata_raw *raw, ctx_data_t *data, + uint64_t page, uint64_t count) +{ + uint8_t *buffer = NULL, *zpage; + int result; + + zpage = env_vzalloc(PAGE_SIZE); + if (!zpage) + return -OCF_ERR_NO_MEM; + + result = raw_dynamic_update_pages(cache, raw, data, page, + count, &buffer, zpage); + + if (buffer) + env_secure_free(buffer, PAGE_SIZE); + + env_vfree(zpage); + + return result; +} + /* * RAM DYNAMIC Implementation - Load all */ @@ -269,7 +335,7 @@ struct raw_dynamic_load_all_context { ctx_data_t *data; uint8_t *zpage; uint8_t *page; - uint64_t i; + uint64_t i_page; int error; ocf_metadata_end_t cmpl; @@ -317,11 +383,12 @@ static int raw_dynamic_load_all_read(struct ocf_request *req) uint64_t count; int result; - count = OCF_MIN(RAW_DYNAMIC_LOAD_PAGES, raw->ssd_pages - context->i); + count = OCF_MIN(RAW_DYNAMIC_LOAD_PAGES, + raw->ssd_pages - context->i_page); /* Allocate IO */ context->io = ocf_new_cache_io(context->cache, req->io_queue, - PAGES_TO_BYTES(raw->ssd_pages_offset + context->i), + PAGES_TO_BYTES(raw->ssd_pages_offset + context->i_page), PAGES_TO_BYTES(count), OCF_READ, 0, 0); if (!context->io) { @@ -354,53 +421,20 @@ static int raw_dynamic_load_all_update(struct ocf_request *req) { struct raw_dynamic_load_all_context *context = req->priv; struct ocf_metadata_raw *raw = context->raw; - struct _raw_ctrl *ctrl = (struct _raw_ctrl *)raw->priv; ocf_cache_t cache = context->cache; uint64_t count = BYTES_TO_PAGES(context->io->bytes); - uint64_t i_page; int result = 0; - int cmp; /* Reset head of data buffer */ ctx_data_seek_check(context->cache->owner, context->data, ctx_data_seek_begin, 0); - for (i_page = 0; i_page < count; i_page++, context->i++) { - if (!context->page) { - context->page = env_secure_alloc(PAGE_SIZE); - if (!context->page) { - /* Allocation error */ - result = -OCF_ERR_NO_MEM; - break; - } - } + result = raw_dynamic_update_pages(cache, raw, context->data, + context->i_page, count, &context->page, context->zpage); - ctx_data_rd_check(cache->owner, context->page, - context->data, PAGE_SIZE); + context->i_page += count; - result = env_memcmp(context->zpage, PAGE_SIZE, context->page, - PAGE_SIZE, &cmp); - if (result) - break; - - /* When page is zero set, no need to allocate space for it */ - if (cmp == 0) { - OCF_DEBUG_PARAM(cache, "Zero loaded %llu", i); - continue; - } - - OCF_DEBUG_PARAM(cache, "Non-zero loaded %llu", i); - - if (ctrl->pages[context->i]) - env_vfree(ctrl->pages[context->i]); - - ctrl->pages[context->i] = context->page; - context->page = NULL; - - env_atomic_inc(&ctrl->count); - } - - if (result || context->i >= raw->ssd_pages) { + if (result || context->i_page >= raw->ssd_pages) { raw_dynamic_load_all_complete(context, result); return 0; } diff --git a/src/metadata/metadata_raw_dynamic.h b/src/metadata/metadata_raw_dynamic.h index 5443bb2..714896d 100644 --- a/src/metadata/metadata_raw_dynamic.h +++ b/src/metadata/metadata_raw_dynamic.h @@ -53,6 +53,13 @@ uint32_t raw_dynamic_page(struct ocf_metadata_raw *raw, uint32_t entry); void *raw_dynamic_access(ocf_cache_t cache, struct ocf_metadata_raw *raw, uint32_t entry); +/* + * RAW DYNAMIC - Update metadata based on cache volume io + */ +int raw_dynamic_update(ocf_cache_t cache, + struct ocf_metadata_raw *raw, ctx_data_t *data, + uint64_t page, uint64_t count); + /* * RAW DYNAMIC - Load all metadata of this RAW metadata container * from cache device diff --git a/src/metadata/metadata_raw_volatile.c b/src/metadata/metadata_raw_volatile.c index 0f08b93..ec55fcb 100644 --- a/src/metadata/metadata_raw_volatile.c +++ b/src/metadata/metadata_raw_volatile.c @@ -26,6 +26,17 @@ uint32_t raw_volatile_checksum(ocf_cache_t cache, return 0; } +/* + * RAW volatile Implementation - Update + */ +int raw_volatile_update(ocf_cache_t cache, + struct ocf_metadata_raw *raw, ctx_data_t *data, + uint64_t page, uint64_t count) +{ + /* Do nothing on purpose. */ + return 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 0d794b0..24286e0 100644 --- a/src/metadata/metadata_raw_volatile.h +++ b/src/metadata/metadata_raw_volatile.h @@ -17,6 +17,13 @@ uint32_t raw_volatile_size_on_ssd(struct ocf_metadata_raw *raw); uint32_t raw_volatile_checksum(ocf_cache_t cache, struct ocf_metadata_raw *raw); +/* + * RAW volatile Implementation - Update + */ +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 - Load all metadata elements from SSD */