diff --git a/env/posix/ocf_env.h b/env/posix/ocf_env.h index 91167cc5..17d50f0f 100644 --- a/env/posix/ocf_env.h +++ b/env/posix/ocf_env.h @@ -1,6 +1,7 @@ /* * Copyright(c) 2019-2022 Intel Corporation * Copyright(c) 2023-2025 Huawei Technologies + * Copyright(c) 2026 Unvertical * SPDX-License-Identifier: BSD-3-Clause */ @@ -84,7 +85,7 @@ void env_stack_trace(void); const typeof(((type *)0)->member)*__mptr = (ptr); \ (type *)((char *)__mptr - offsetof(type, member)); }) -#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) +#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) /* STRING OPERATIONS */ #define env_memcpy(dest, dmax, src, slen) ({ \ @@ -597,31 +598,37 @@ static inline int env_in_interrupt(void) return 0; } +/* TIME */ +#define ENV_SEC_TO_NSEC(_sec) ((_sec) * 1000000000) +#define ENV_NSEC_TO_SEC(_sec) ((_sec) / 1000000000) +#define ENV_NSEC_TO_MSEC(_sec) ((_sec) / 1000000) + static inline uint64_t env_get_tick_count(void) { - struct timeval tv; - gettimeofday(&tv, NULL); - return tv.tv_sec * 1000000 + tv.tv_usec; + struct timespec tv; + + return clock_gettime(CLOCK_REALTIME, &tv) ? + 0 : ENV_SEC_TO_NSEC(tv.tv_sec) + tv.tv_nsec; } static inline uint64_t env_ticks_to_nsecs(uint64_t j) { - return j * 1000; + return j; } static inline uint64_t env_ticks_to_msecs(uint64_t j) { - return j / 1000; + return ENV_NSEC_TO_MSEC(j); } static inline uint64_t env_ticks_to_secs(uint64_t j) { - return j / 1000000; + return ENV_NSEC_TO_SEC(j); } static inline uint64_t env_secs_to_ticks(uint64_t j) { - return j * 1000000; + return ENV_SEC_TO_NSEC(j); } /* SORTING */ diff --git a/inc/ocf_cache.h b/inc/ocf_cache.h index 3280b9a8..683ee779 100644 --- a/inc/ocf_cache.h +++ b/inc/ocf_cache.h @@ -1,6 +1,7 @@ /* * Copyright(c) 2012-2021 Intel Corporation * Copyright(c) 2023-2025 Huawei Technologies + * Copyright(c) 2026 Unvertical * SPDX-License-Identifier: BSD-3-Clause */ @@ -193,6 +194,15 @@ ocf_cache_mode_t ocf_cache_get_mode(ocf_cache_t cache); */ ocf_cache_line_size_t ocf_cache_get_line_size(ocf_cache_t cache); +/** + * @brief Get number of cache lines of given cache object + * + * @param[in] cache Cache object + * + * @retval Number of cache lines + */ +ocf_cache_line_t ocf_cache_get_line_count(ocf_cache_t cache); + /** * @brief Convert bytes to cache lines * diff --git a/inc/ocf_volume.h b/inc/ocf_volume.h index 385ce6f4..a7426c32 100644 --- a/inc/ocf_volume.h +++ b/inc/ocf_volume.h @@ -1,6 +1,7 @@ /* * Copyright(c) 2012-2022 Intel Corporation * Copyright(c) 2024 Huawei Technologies + * Copyright(c) 2026 Unvertical * SPDX-License-Identifier: BSD-3-Clause */ @@ -409,5 +410,17 @@ unsigned int ocf_volume_get_max_io_size(ocf_volume_t volume); * @return Length of volume in bytes */ uint64_t ocf_volume_get_length(ocf_volume_t volume); +/* + * @brief Check if uuid instances contain the same data + * + * @param[in] a first uuid + * @param[in] b second uuid + * @param[out] diff 0 if equal, non-0 otherwise + * + * @retval 0 if comparison successful + * @retval other value if comparison failed + */ +int ocf_uuid_compare(const struct ocf_volume_uuid * const a, + const struct ocf_volume_uuid * const b, int *diff); #endif /* __OCF_VOLUME_H__ */ diff --git a/src/cleaning/acp.c b/src/cleaning/acp.c index b558a98d..e5a9af23 100644 --- a/src/cleaning/acp.c +++ b/src/cleaning/acp.c @@ -643,7 +643,7 @@ static ocf_cache_line_t _acp_trylock_dirty(struct ocf_cache *cache, ocf_engine_lookup_map_entry(cache, &info, core_id, core_line); - if (info.status == LOOKUP_HIT && + if ((info.status == LOOKUP_HIT || info.status == LOOKUP_HIT_INVALID) && metadata_test_dirty(cache, info.coll_idx)) { locked = ocf_cache_line_try_lock_rd( ocf_cache_line_concurrency(cache), diff --git a/src/engine/cache_engine.c b/src/engine/cache_engine.c index 2a1348ac..70081e99 100644 --- a/src/engine/cache_engine.c +++ b/src/engine/cache_engine.c @@ -1,6 +1,7 @@ /* * Copyright(c) 2012-2022 Intel Corporation * Copyright(c) 2024-2025 Huawei Technologies + * Copyright(c) 2026 Unvertical * SPDX-License-Identifier: BSD-3-Clause */ @@ -171,7 +172,7 @@ void ocf_resolve_effective_cache_mode(ocf_cache_t cache, return; } - if (unlikely(req->core_line_count > cache->conf_meta->cachelines)) { + if (unlikely(req->core_line_count > ocf_cache_get_line_count(cache))) { req->cache_mode = ocf_req_cache_mode_pt; return; } diff --git a/src/engine/cache_engine.h b/src/engine/cache_engine.h index f9c7c7d2..65b5495b 100644 --- a/src/engine/cache_engine.h +++ b/src/engine/cache_engine.h @@ -1,6 +1,7 @@ /* * Copyright(c) 2012-2022 Intel Corporation * Copyright(c) 2024 Huawei Technologies + * Copyright(c) 2026 Unvertical * SPDX-License-Identifier: BSD-3-Clause */ @@ -14,6 +15,7 @@ struct ocf_thread_priv; #define LOOKUP_HIT 5 #define LOOKUP_MISS 6 #define LOOKUP_REMAPPED 8 +#define LOOKUP_HIT_INVALID 9 static inline ocf_req_cache_mode_t ocf_cache_mode_to_req_cache_mode( ocf_cache_mode_t mode) diff --git a/src/engine/engine_bf.c b/src/engine/engine_bf.c index 219efb28..1ba963fc 100644 --- a/src/engine/engine_bf.c +++ b/src/engine/engine_bf.c @@ -1,6 +1,7 @@ /* * Copyright(c) 2012-2022 Intel Corporation * Copyright(c) 2024-2025 Huawei Technologies + * Copyright(c) 2026 Unvertical * SPDX-License-Identifier: BSD-3-Clause */ @@ -85,13 +86,86 @@ static void _ocf_backfill_complete(struct ocf_request *req, int error) static int _ocf_backfill_do(struct ocf_request *req) { + ocf_cache_t cache = req->cache; + uint64_t addr, bytes, total_bytes = 0, addr_next = 0; + uint64_t end = req->addr + req->bytes; + ocf_cache_line_size_t line_size = ocf_line_size(cache); + uint64_t seek, skip; + uint32_t i; + req->data = req->cp_data; if (unlikely(req->data == NULL)) { _ocf_backfill_complete(req, -OCF_ERR_NO_MEM); return 0; } - ocf_engine_forward_cache_io_req(req, OCF_WRITE, _ocf_backfill_complete); + ocf_req_forward_cache_init(req, _ocf_backfill_complete); + + if (ocf_engine_is_sequential(req)) { + addr = cache->device->metadata_offset; + addr += req->map[0].coll_idx * line_size; + addr += req->addr % line_size; + + ocf_core_stats_cache_block_update(req->core, req->part_id, + OCF_WRITE, req->bytes); + ocf_req_forward_cache_io(req, OCF_WRITE, addr, req->bytes, + req->offset); + return 0; + } + + ocf_req_forward_cache_get(req); + for (i = 0; i < req->core_line_count; i++) { + if (addr_next) { + addr = addr_next; + } else { + addr = req->map[i].coll_idx; + addr *= line_size; + addr += cache->device->metadata_offset; + } + bytes = line_size; + + if (i == 0) { + seek = req->addr % line_size; + addr += seek; + bytes -= seek; + } + + if (req->map[i].status == LOOKUP_HIT) { + /* This is the 1st cache line in the interval, + * and it's a hit. Don't write it to the cache. + */ + addr_next = 0; + total_bytes += bytes; + continue; + } + + for (; i < (req->core_line_count - 1); i++) { + addr_next = req->map[i + 1].coll_idx; + addr_next *= line_size; + addr_next += cache->device->metadata_offset; + + if (addr_next != (addr + bytes)) + break; + + bytes += line_size; + } + + if (i == (req->core_line_count - 1)) { + skip = (line_size - (end % line_size)) % line_size; + bytes -= skip; + } + + bytes = OCF_MIN(bytes, req->bytes - total_bytes); + + ocf_core_stats_cache_block_update(req->core, req->part_id, + OCF_WRITE, bytes); + ocf_req_forward_cache_io(req, OCF_WRITE, addr, bytes, + req->offset + total_bytes); + + total_bytes += bytes; + } + + ocf_req_forward_cache_put(req); return 0; } diff --git a/src/engine/engine_common.c b/src/engine/engine_common.c index 9a24828b..9d2937a5 100644 --- a/src/engine/engine_common.c +++ b/src/engine/engine_common.c @@ -1,6 +1,7 @@ /* * Copyright(c) 2012-2022 Intel Corporation * Copyright(c) 2024 Huawei Technologies + * Copyright(c) 2026 Unvertical * SPDX-License-Identifier: BSD-3-Clause */ @@ -143,7 +144,8 @@ static void ocf_engine_update_req_info(struct ocf_cache *cache, ENV_BUG_ON(entry->status != LOOKUP_HIT && entry->status != LOOKUP_MISS && - entry->status != LOOKUP_REMAPPED); + entry->status != LOOKUP_REMAPPED && + entry->status != LOOKUP_HIT_INVALID); /* Handle return value */ if (entry->status == LOOKUP_HIT) { @@ -152,6 +154,7 @@ static void ocf_engine_update_req_info(struct ocf_cache *cache, req->info.hit_no++; } else { req->info.invalid_no++; + entry->status = LOOKUP_HIT_INVALID; } /* Check request is dirty */ @@ -165,7 +168,9 @@ static void ocf_engine_update_req_info(struct ocf_cache *cache, } } - if (entry->status == LOOKUP_HIT || entry->status == LOOKUP_REMAPPED) { + if (entry->status == LOOKUP_HIT || + entry->status == LOOKUP_HIT_INVALID || + entry->status == LOOKUP_REMAPPED) { if (req->part_id != ocf_metadata_get_partition_id(cache, entry->coll_idx)) { /* @@ -201,7 +206,7 @@ void ocf_engine_set_hot(struct ocf_request *req) entry = &(req->map[i]); status = entry->status; - if (status == LOOKUP_HIT) { + if (status == LOOKUP_HIT || status == LOOKUP_HIT_INVALID) { /* Update eviction (LRU) */ ocf_lru_hot_cline(cache, entry->coll_idx); } @@ -341,6 +346,7 @@ static void ocf_engine_map_hndl_error(struct ocf_cache *cache, switch (entry->status) { case LOOKUP_HIT: + case LOOKUP_HIT_INVALID: case LOOKUP_MISS: break; @@ -548,7 +554,7 @@ static int _ocf_engine_clean_getter(struct ocf_cache *cache, entry = &req->map[item]; - if (entry->status != LOOKUP_HIT) + if (entry->status != LOOKUP_HIT && entry->status != LOOKUP_HIT_INVALID) return -1; if (!metadata_test_dirty(cache, entry->coll_idx)) diff --git a/src/metadata/metadata_cache_line.h b/src/metadata/metadata_cache_line.h index fa7230ac..0fbfd993 100644 --- a/src/metadata/metadata_cache_line.h +++ b/src/metadata/metadata_cache_line.h @@ -1,5 +1,7 @@ /* * Copyright(c) 2012-2021 Intel Corporation + * Copyright(c) 2023 Huawei Technologies + * Copyright(c) 2026 Unvertical * SPDX-License-Identifier: BSD-3-Clause */ @@ -11,6 +13,11 @@ static inline ocf_cache_line_size_t ocf_line_size(struct ocf_cache *cache) return cache->metadata.line_size; } +static inline ocf_cache_line_t ocf_line_count(struct ocf_cache *cache) +{ + return cache->conf_meta->cachelines; +} + static inline uint64_t ocf_line_sectors(struct ocf_cache *cache) { return BYTES_TO_SECTORS(cache->metadata.line_size); diff --git a/src/mngt/ocf_mngt_cache.c b/src/mngt/ocf_mngt_cache.c index 4ab7e0e2..ea1ecd30 100644 --- a/src/mngt/ocf_mngt_cache.c +++ b/src/mngt/ocf_mngt_cache.c @@ -1729,7 +1729,7 @@ static void _ocf_mngt_load_superblock_complete(void *priv, int error) OCF_PL_FINISH_RET(context->pipeline, error); } - if (cache->conf_meta->cachelines != + if (ocf_cache_get_line_count(cache) != ocf_metadata_get_cachelines_count(cache)) { ocf_cache_log(cache, log_err, "ERROR: Cache device size mismatch!\n"); diff --git a/src/mngt/ocf_mngt_core.c b/src/mngt/ocf_mngt_core.c index c4269758..f5a0c0ec 100644 --- a/src/mngt/ocf_mngt_core.c +++ b/src/mngt/ocf_mngt_core.c @@ -1,6 +1,7 @@ /* * Copyright(c) 2012-2022 Intel Corporation * Copyright(c) 2024-2025 Huawei Technologies + * Copyright(c) 2026 Unvertical * SPDX-License-Identifier: BSD-3-Clause */ @@ -30,17 +31,22 @@ static int ocf_mngt_core_set_name(ocf_core_t core, const char *name) name, OCF_CORE_NAME_SIZE); } -static int ocf_core_get_by_uuid(ocf_cache_t cache, void *uuid, size_t uuid_size, +static int ocf_core_get_by_uuid(ocf_cache_t cache, ocf_uuid_t uuid, ocf_core_t *core) { struct ocf_volume *volume; ocf_core_t i_core; ocf_core_id_t i_core_id; + int diff, result; for_each_core_metadata(cache, i_core, i_core_id) { volume = ocf_core_get_volume(i_core); - if (!env_strncmp(volume->uuid.data, volume->uuid.size, uuid, - uuid_size)) { + + result = ocf_uuid_compare(&volume->uuid, uuid, &diff); + if (result) + return -OCF_ERR_UNKNOWN; + + if (diff == 0) { *core = i_core; return 0; } @@ -253,7 +259,7 @@ static void ocf_mngt_cache_try_add_core_prepare(ocf_pipeline_t pipeline, ocf_volume_t volume; ocf_volume_type_t type; ocf_ctx_t ctx = cache->owner; - int result; + int result, diff; result = ocf_core_get_by_name(cache, cfg->name, OCF_CORE_NAME_SIZE, &core); @@ -273,8 +279,8 @@ static void ocf_mngt_cache_try_add_core_prepare(ocf_pipeline_t pipeline, goto err; } - if (env_strncmp(volume->uuid.data, volume->uuid.size, cfg->uuid.data, - cfg->uuid.size)) { + result = ocf_uuid_compare(&volume->uuid, &cfg->uuid, &diff); + if (result || diff) { result = -OCF_ERR_INVAL; goto err; } @@ -341,10 +347,11 @@ static void ocf_mngt_cache_add_core_prepare(ocf_pipeline_t pipeline, if (!result) OCF_PL_FINISH_RET(context->pipeline, -OCF_ERR_CORE_EXIST); - result = ocf_core_get_by_uuid(cache, cfg->uuid.data, - cfg->uuid.size, &core); + result = ocf_core_get_by_uuid(cache, &cfg->uuid, &core); if (!result) OCF_PL_FINISH_RET(context->pipeline, -OCF_ERR_CORE_UUID_EXISTS); + else if (result != -OCF_ERR_CORE_NOT_EXIST) + OCF_PL_FINISH_RET(context->pipeline, result); result = ocf_mngt_find_free_core(cache, &core); if (result) diff --git a/src/mngt/ocf_mngt_flush.c b/src/mngt/ocf_mngt_flush.c index dc9184c8..450ea82e 100644 --- a/src/mngt/ocf_mngt_flush.c +++ b/src/mngt/ocf_mngt_flush.c @@ -421,6 +421,8 @@ static void _ocf_mngt_flush_portion(struct flush_container *fc) fc->iter += curr_flush_portion_size; + fc->ticks1 = env_get_tick_count(); + ocf_cleaner_do_flush_data_async(fc->cache, &fc->flush_data[flush_data_offset], curr_flush_portion_size, &fc->attribs); diff --git a/src/ocf_cache.c b/src/ocf_cache.c index bace4b1f..8bf9a12b 100644 --- a/src/ocf_cache.c +++ b/src/ocf_cache.c @@ -1,6 +1,7 @@ /* * Copyright(c) 2012-2022 Intel Corporation * Copyright(c) 2023-2025 Huawei Technologies + * Copyright(c) 2026 Unvertical * SPDX-License-Identifier: BSD-3-Clause */ @@ -138,7 +139,7 @@ int ocf_cache_get_info(ocf_cache_t cache, struct ocf_cache_info *info) if (info->attached && !info->standby_detached) { info->volume_type = ocf_ctx_get_volume_type_id(cache->owner, cache->device->volume.type); - info->size = cache->conf_meta->cachelines; + info->size = ocf_cache_get_line_count(cache); } info->state = cache->cache_state; info->cache_line_size = ocf_line_size(cache); @@ -252,6 +253,12 @@ ocf_cache_line_size_t ocf_cache_get_line_size(ocf_cache_t cache) return ocf_line_size(cache); } +ocf_cache_line_t ocf_cache_get_line_count(ocf_cache_t cache) +{ + OCF_CHECK_NULL(cache); + return ocf_line_count(cache); +} + uint64_t ocf_cache_bytes_2_lines(ocf_cache_t cache, uint64_t bytes) { OCF_CHECK_NULL(cache); diff --git a/src/ocf_stats_builder.c b/src/ocf_stats_builder.c index 512374c1..bc215d9a 100644 --- a/src/ocf_stats_builder.c +++ b/src/ocf_stats_builder.c @@ -1,6 +1,7 @@ /* * Copyright(c) 2012-2022 Intel Corporation - * Copyright(c) 2024 Huawei Technologies + * Copyright(c) 2023 Huawei Technologies + * Copyright(c) 2026 Unvertical * SPDX-License-Identifier: BSD-3-Clause */ @@ -241,7 +242,7 @@ static void _ocf_stats_part_fill(ocf_cache_t cache, ocf_part_id_t part_id, uint64_t cache_size, cache_line_size; cache_line_size = ocf_cache_get_line_size(cache); - cache_size = cache->conf_meta->cachelines; + cache_size = ocf_cache_get_line_count(cache); if (usage) { _set(&usage->occupancy, @@ -361,7 +362,7 @@ int ocf_stats_collect_core(ocf_core_t core, goto mem_free; cache_line_size = ocf_cache_get_line_size(cache); - cache_size = cache->conf_meta->cachelines; + cache_size = ocf_cache_get_line_count(cache); cache_occupancy = ocf_get_cache_occupancy(cache); _ocf_stats_zero(usage); diff --git a/src/ocf_volume.c b/src/ocf_volume.c index 0a455a26..a9f0d314 100644 --- a/src/ocf_volume.c +++ b/src/ocf_volume.c @@ -1,6 +1,7 @@ /* * Copyright(c) 2012-2022 Intel Corporation * Copyright(c) 2024-2025 Huawei Technologies + * Copyright(c) 2026 Unvertical * SPDX-License-Identifier: BSD-3-Clause */ @@ -508,3 +509,26 @@ uint64_t ocf_volume_get_length(ocf_volume_t volume) return volume->type->properties->ops.get_length(volume); } + +int ocf_uuid_compare(const struct ocf_volume_uuid * const a, + const struct ocf_volume_uuid * const b, int *diff) +{ + int ret, tmp_diff; + + ret = env_memcmp(a->data, a->size, b->data, b->size, &tmp_diff); + if (ret) + return ret; + + /* + * env_memcmp() compares only min(slen1, slen2) bytes. If the sizes + * differ, we continue comparison, assuming that any value is greater + * than no value, i.e. if the first uuid is shorter, the diff is -1, + * otherwise the diff is 1. + */ + if (tmp_diff || a->size == b->size) + *diff = tmp_diff; + else + *diff = (a->size < b->size) ? -1 : 1; + + return 0; +} diff --git a/src/utils/utils_user_part.h b/src/utils/utils_user_part.h index 17ccdc6f..1ea9e6f1 100644 --- a/src/utils/utils_user_part.h +++ b/src/utils/utils_user_part.h @@ -1,5 +1,7 @@ /* * Copyright(c) 2012-2021 Intel Corporation + * Copyright(c) 2023 Huawei Technologies + * Copyright(c) 2026 Unvertical * SPDX-License-Identifier: BSD-3-Clause */ @@ -62,7 +64,7 @@ static inline uint32_t ocf_user_part_get_min_size(ocf_cache_t cache, uint64_t ioclass_size; ioclass_size = (uint64_t)user_part->config->min_size * - (uint64_t)cache->conf_meta->cachelines; + (uint64_t)ocf_cache_get_line_count(cache); ioclass_size /= 100; @@ -76,7 +78,7 @@ static inline uint32_t ocf_user_part_get_max_size(ocf_cache_t cache, uint64_t ioclass_size, max_size, cache_size; max_size = user_part->config->max_size; - cache_size = cache->conf_meta->cachelines; + cache_size = ocf_cache_get_line_count(cache); ioclass_size = max_size * cache_size; ioclass_size = OCF_DIV_ROUND_UP(ioclass_size, 100);