From 83aab58952ce6a86407348326a36c580b4f07a85 Mon Sep 17 00:00:00 2001 From: Rafal Stefanowski Date: Thu, 9 Apr 2026 16:30:33 +0200 Subject: [PATCH 1/4] Eliminate C23 extensions SPDK doesn't allow using C23 extensions and throws an error in the upstream CI during compilation: "error: '_Static_assert' with no message is a C23 extension [-Werror,-Wc23-extensions]" Add a message as a second argument for _Static_assert() to avoid using C23 extensions. Signed-off-by: Rafal Stefanowski Signed-off-by: Robert Baldyga --- inc/ocf_def.h | 4 +++- src/metadata/metadata_collision.h | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/inc/ocf_def.h b/inc/ocf_def.h index 330a3a35..049c756c 100644 --- a/inc/ocf_def.h +++ b/inc/ocf_def.h @@ -88,7 +88,9 @@ * for invalid OCF_CORE_ID_INVALID. */ #define OCF_CORE_NUM OCF_CONFIG_MAX_CORES -_Static_assert(OCF_CORE_NUM < OCF_MAX_T(uint32_t, OCF_CORE_ID_BITS)); +_Static_assert(OCF_MAX_T(uint32_t, OCF_CORE_ID_BITS) > OCF_CORE_NUM, + "Not enough core ID bits (OCF_CORE_ID_BITS) to " + "store maximum number of cores (OCF_CORE_NUM)"); /** * Minimum value of a valid core ID */ diff --git a/src/metadata/metadata_collision.h b/src/metadata/metadata_collision.h index 01d7a7ed..f444c9b1 100644 --- a/src/metadata/metadata_collision.h +++ b/src/metadata/metadata_collision.h @@ -24,7 +24,8 @@ struct ocf_metadata_list_info { } __attribute__((packed)); /* Keep the struct ocf_metadata_list_info size of 8 bytes */ -_Static_assert(sizeof(struct ocf_metadata_list_info) == sizeof(uint64_t)); +_Static_assert(sizeof(struct ocf_metadata_list_info) == sizeof(uint64_t), + "Size of struct ocf_metadata_list_info is not equal to 8 bytes"); struct ocf_hash_entry { union { From 78735971c119587e932dcdab9c8ae132fcb78cd2 Mon Sep 17 00:00:00 2001 From: Rafal Stefanowski Date: Mon, 22 Jun 2026 14:35:37 +0200 Subject: [PATCH 2/4] Align cleaning and promotion policy config structs This properly alignes data and prevents UBSan from reporting misalignment errors. Signed-off-by: Rafal Stefanowski Signed-off-by: Robert Baldyga --- src/cleaning/cleaning.h | 2 +- src/promotion/promotion.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cleaning/cleaning.h b/src/cleaning/cleaning.h index f67a79e1..1e56af27 100644 --- a/src/cleaning/cleaning.h +++ b/src/cleaning/cleaning.h @@ -22,7 +22,7 @@ struct ocf_request; struct cleaning_policy_config { uint8_t data[CLEANING_POLICY_CONFIG_BYTES]; -}; +} __attribute__((aligned(4))); struct cleaning_policy { union { diff --git a/src/promotion/promotion.h b/src/promotion/promotion.h index f4005181..612b5b62 100644 --- a/src/promotion/promotion.h +++ b/src/promotion/promotion.h @@ -15,7 +15,7 @@ struct promotion_policy_config { uint8_t data[PROMOTION_POLICY_CONFIG_BYTES]; -}; +} __attribute__((aligned(4))); typedef struct ocf_promotion_policy *ocf_promotion_policy_t; From 6613683e9d3cba6730c928dd8418aa3081daf004 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Mon, 6 Jul 2026 15:43:50 +0200 Subject: [PATCH 3/4] generator: Protect against invalid values __builtin_clz() produces undefined behavior for argument equal 0. Implement proper handing of such a case. Signed-off-by: Robert Baldyga --- src/ocf_lru.c | 5 ++++- src/utils/utils_generator.c | 24 ++++++++++++++++++++---- src/utils/utils_generator.h | 3 ++- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/ocf_lru.c b/src/ocf_lru.c index 7a0d959e..af35aa2a 100644 --- a/src/ocf_lru.c +++ b/src/ocf_lru.c @@ -1031,6 +1031,7 @@ static int ocf_lru_populate_handle(ocf_parallelize_t parallelize, uint32_t partial_chunk_lines = 0; uint32_t num_chunks, chunk_idx, chunk_lines; uint32_t ci, j; + int result; /* Check if this shard has a partial last chunk */ if (remainder > (uint32_t)shard_id * OCF_LRU_CHUNK_SIZE) { @@ -1044,7 +1045,9 @@ static int ocf_lru_populate_handle(ocf_parallelize_t parallelize, if (num_chunks == 0) return 0; - ocf_generator_bisect_init(&generator, num_chunks, 0); + result = ocf_generator_bisect_init(&generator, num_chunks, 0); + if (result) + return result; list = ocf_lru_get_list(&cache->free, shard_id, true); diff --git a/src/utils/utils_generator.c b/src/utils/utils_generator.c index 47ab7e65..e04c8029 100644 --- a/src/utils/utils_generator.c +++ b/src/utils/utils_generator.c @@ -1,5 +1,6 @@ /* * Copyright(c) 2022 Intel Corporation + * Copyright(c) 2026 Unvertical * SPDX-License-Identifier: BSD-3-Clause */ @@ -29,20 +30,32 @@ static inline uint32_t bitreverse32(register uint32_t x) * returned by the generator is limit - 1) * @param[in] offset Offset at which generator should start * - * @return Reversed value + * @return Zero when success, otherwise an error */ -void ocf_generator_bisect_init( +int ocf_generator_bisect_init( struct ocf_generator_bisect_state *generator, uint32_t limit, uint32_t offset) { unsigned clz; uint32_t maplen; - clz = __builtin_clz(limit - 1); - maplen = 1 << (32 - clz); + if (limit == 0) + return -OCF_ERR_INVAL; + + if (offset >= limit) + return -OCF_ERR_INVAL; + + if (limit > 1) { + clz = __builtin_clz(limit - 1); + maplen = 1 << (32 - clz); + } else { + maplen = 1; + } generator->curr = (uint64_t)offset * maplen / limit; generator->limit = limit; + + return 0; } /** @@ -180,6 +193,9 @@ uint32_t ocf_generator_bisect_next( uint32_t maplen; uint32_t value; + if (generator->limit == 1) + return 0; + clz = __builtin_clz(generator->limit - 1); maplen = 1 << (32 - clz); diff --git a/src/utils/utils_generator.h b/src/utils/utils_generator.h index 068602d0..df8cb1ba 100644 --- a/src/utils/utils_generator.h +++ b/src/utils/utils_generator.h @@ -1,5 +1,6 @@ /* * Copyright(c) 2022 Intel Corporation + * Copyright(c) 2026 Unvertical * SPDX-License-Identifier: BSD-3-Clause */ @@ -13,7 +14,7 @@ struct ocf_generator_bisect_state { uint32_t limit; }; -void ocf_generator_bisect_init( +int ocf_generator_bisect_init( struct ocf_generator_bisect_state *generator, uint32_t limit, uint32_t offset); From 0ba990349cae9c5e9a68cc60b118c1c9f27a0c28 Mon Sep 17 00:00:00 2001 From: Rafal Stefanowski Date: Fri, 19 Jun 2026 17:44:25 +0200 Subject: [PATCH 4/4] Get cleaner from cache Needed by SPDK OCF module to set/get CPU mask on cleaner thread. Signed-off-by: Rafal Stefanowski Signed-off-by: Robert Baldyga --- inc/ocf_cache.h | 11 +++++++++++ src/ocf_cache.c | 16 ++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/inc/ocf_cache.h b/inc/ocf_cache.h index 683ee779..1f69fa60 100644 --- a/inc/ocf_cache.h +++ b/inc/ocf_cache.h @@ -261,6 +261,17 @@ const struct ocf_volume_uuid *ocf_cache_get_uuid(ocf_cache_t cache); */ ocf_ctx_t ocf_cache_get_ctx(ocf_cache_t cache); +/** + * @brief Get OCF cleaner of given cache object + * + * @param[in] cache Cache object + * + * @retval OCF cleaner, NULL if cache is in standby mode, + * cache device is not attached (cleaner not initialized) + * or cleaner is disabled + */ +ocf_cleaner_t ocf_cache_get_cleaner(ocf_cache_t cache); + /** * @brief Get volume type id of given cache object * diff --git a/src/ocf_cache.c b/src/ocf_cache.c index 55f99e87..3fbe12c0 100644 --- a/src/ocf_cache.c +++ b/src/ocf_cache.c @@ -287,6 +287,22 @@ ocf_ctx_t ocf_cache_get_ctx(ocf_cache_t cache) return cache->owner; } +ocf_cleaner_t ocf_cache_get_cleaner(ocf_cache_t cache) +{ + OCF_CHECK_NULL(cache); + + if (ocf_cache_is_standby(cache)) + return NULL; + + if (!ocf_cache_is_device_attached(cache)) + return NULL; + + if (cache->conf_meta->cleaner_disabled) + return NULL; + + return &cache->cleaner; +} + void ocf_cache_set_priv(ocf_cache_t cache, void *priv) { OCF_CHECK_NULL(cache);