diff --git a/inc/cleaning/alru.h b/inc/cleaning/alru.h index d7303986..2804481c 100644 --- a/inc/cleaning/alru.h +++ b/inc/cleaning/alru.h @@ -1,6 +1,7 @@ /* * Copyright(c) 2012-2021 Intel Corporation * Copyright(c) 2022 David Lee + * Copyright(c) 2025 Huawei Technologies * SPDX-License-Identifier: BSD-3-Clause */ #ifndef __OCF_CLEANING_ALRU_H__ @@ -16,7 +17,8 @@ enum ocf_cleaning_alru_parameters { ocf_alru_stale_buffer_time, ocf_alru_flush_max_buffers, ocf_alru_activity_threshold, - ocf_alru_max_dirty_ratio, + ocf_alru_dirty_ratio_threshold, + ocf_alru_dirty_ratio_inertia, }; /** @@ -69,15 +71,29 @@ enum ocf_cleaning_alru_parameters { #define OCF_ALRU_DEFAULT_ACTIVITY_THRESHOLD 10000 /** - * ALRU max dirty ratio for a cache device + * ALRU dirty-ratio-based cleaning trigger threshold */ -/** Minimum dirty ratio value */ -#define OCF_ALRU_MIN_MAX_DIRTY_RATIO 0 -/** Maximum dirty ratio value */ -#define OCF_ALRU_MAX_MAX_DIRTY_RATIO 100 -/** Default dirty ratio value */ -#define OCF_ALRU_DEFAULT_MAX_DIRTY_RATIO OCF_ALRU_MAX_MAX_DIRTY_RATIO +/** Minimum dirty ratio trigger threshold value */ +#define OCF_ALRU_MIN_DIRTY_RATIO_THRESHOLD 0 +/** Maximum dirty ratio trigger threshold value */ +#define OCF_ALRU_MAX_DIRTY_RATIO_THRESHOLD 100 +/** Default dirty ratio trigger threshold value */ +#define OCF_ALRU_DEFAULT_DIRTY_RATIO_THRESHOLD \ + OCF_ALRU_MAX_DIRTY_RATIO_THRESHOLD + +/** + * ALRU dirty-ratio-based cleaning trigger inertia + * Cleaning triggered by exceeding dirty ratio threshold will stop + * when dirty ratio drops below (threshold - inertia). + */ + +/** Minimum dirty ratio trigger inertia value */ +#define OCF_ALRU_MIN_DIRTY_RATIO_INERTIA 0 +/** Maximum dirty ratio trigger inertia value */ +#define OCF_ALRU_MAX_DIRTY_RATIO_INERTIA UINT_MAX +/** Default dirty ratio trigger inertia */ +#define OCF_ALRU_DEFAULT_DIRTY_RATIO_INERTIA (128 * MiB) /** * @} */ diff --git a/src/cleaning/alru.c b/src/cleaning/alru.c index acf8eeeb..c4bf543d 100644 --- a/src/cleaning/alru.c +++ b/src/cleaning/alru.c @@ -59,6 +59,7 @@ struct alru_flush_ctx { struct alru_context { struct alru_flush_ctx flush_ctx; + bool dirty_ratio_triggered; env_spinlock list_lock[OCF_USER_IO_CLASS_MAX]; }; @@ -356,7 +357,8 @@ void cleaning_policy_alru_setup(struct ocf_cache *cache) config->stale_buffer_time = OCF_ALRU_DEFAULT_STALENESS_TIME; config->flush_max_buffers = OCF_ALRU_DEFAULT_FLUSH_MAX_BUFFERS; config->activity_threshold = OCF_ALRU_DEFAULT_ACTIVITY_THRESHOLD; - config->max_dirty_ratio = OCF_ALRU_DEFAULT_MAX_DIRTY_RATIO; + config->dirty_ratio_threshold = OCF_ALRU_DEFAULT_DIRTY_RATIO_THRESHOLD; + config->dirty_ratio_inertia = OCF_ALRU_DEFAULT_DIRTY_RATIO_INERTIA; } int cleaning_policy_alru_initialize(ocf_cache_t cache, int kick_cleaner) @@ -763,15 +765,25 @@ int cleaning_policy_alru_set_cleaning_param(ocf_cache_t cache, "activity time threshold: %d\n", config->activity_threshold); break; - case ocf_alru_max_dirty_ratio: + case ocf_alru_dirty_ratio_threshold: OCF_CLEANING_CHECK_PARAM(cache, param_value, - OCF_ALRU_MIN_MAX_DIRTY_RATIO, - OCF_ALRU_MAX_MAX_DIRTY_RATIO, - "max_dirty_ratio"); - config->max_dirty_ratio = param_value; + OCF_ALRU_MIN_DIRTY_RATIO_THRESHOLD, + OCF_ALRU_MAX_DIRTY_RATIO_THRESHOLD, + "dirty_ratio_threshold"); + config->dirty_ratio_threshold = param_value; ocf_cache_log(cache, log_info, "Write-back flush thread " - "max dirty ratio: %d\n", - config->max_dirty_ratio); + "dirty ratio trigger threshold: %d\n", + config->dirty_ratio_threshold); + break; + case ocf_alru_dirty_ratio_inertia: + OCF_CLEANING_CHECK_PARAM(cache, param_value, + OCF_ALRU_MIN_DIRTY_RATIO_INERTIA, + OCF_ALRU_MAX_DIRTY_RATIO_INERTIA, + "dirty_ratio_inertia"); + config->dirty_ratio_inertia = param_value; + ocf_cache_log(cache, log_info, "Write-back flush thread " + "dirty ratio trigger inertia: %d\n", + config->dirty_ratio_inertia); break; default: return -OCF_ERR_INVAL; @@ -800,8 +812,11 @@ int cleaning_policy_alru_get_cleaning_param(ocf_cache_t cache, case ocf_alru_activity_threshold: *param_value = config->activity_threshold; break; - case ocf_alru_max_dirty_ratio: - *param_value = config->max_dirty_ratio; + case ocf_alru_dirty_ratio_threshold: + *param_value = config->dirty_ratio_threshold; + break; + case ocf_alru_dirty_ratio_inertia: + *param_value = config->dirty_ratio_inertia; break; default: return -OCF_ERR_INVAL; @@ -850,30 +865,43 @@ static bool clean_later(ocf_cache_t cache, uint32_t *delta) } static bool check_for_dirty_ratio(ocf_cache_t cache, - struct alru_cleaning_policy_config *config) + struct alru_cleaning_policy_config *config, + struct alru_context *ctx) { struct ocf_cache_info info; + /* values in cache lines */ + ocf_cache_line_t threshold_cl, inertia_cl; - if (config->max_dirty_ratio == OCF_ALRU_MAX_MAX_DIRTY_RATIO) + if (config->dirty_ratio_threshold == OCF_ALRU_MAX_DIRTY_RATIO_THRESHOLD) return false; if (ocf_cache_get_info(cache, &info)) return false; - return info.dirty * 100 / info.size >= config->max_dirty_ratio; + threshold_cl = info.size / 100 * config->dirty_ratio_threshold; + if (ctx->dirty_ratio_triggered) { + inertia_cl = config->dirty_ratio_inertia / info.cache_line_size; + if (inertia_cl >= threshold_cl) + return true; + + threshold_cl -= inertia_cl; + } + + ctx->dirty_ratio_triggered = info.dirty >= threshold_cl; + return ctx->dirty_ratio_triggered; } -static bool is_cleanup_possible(ocf_cache_t cache, struct alru_flush_ctx *fctx) +static bool is_cleanup_possible(ocf_cache_t cache, struct alru_context *ctx) { + struct alru_flush_ctx *fctx = &ctx->flush_ctx; struct alru_cleaning_policy_config *config; uint32_t delta; - config = (void *)&cache->conf_meta->cleaning[ocf_cleaning_alru].data; - if (check_for_dirty_ratio(cache, config)) { + if (check_for_dirty_ratio(cache, config, ctx)) { fctx->dirty_ratio_exceeded = true; OCF_DEBUG_PARAM(cache, "Dirty ratio exceeds: %u%%", - config->max_dirty_ratio); + config->dirty_ratio_threshold); return true; } @@ -1027,7 +1055,7 @@ static void alru_clean(struct alru_context *ctx) ocf_cache_t cache = fctx->cache; int to_clean; - if (!is_cleanup_possible(cache, fctx)) { + if (!is_cleanup_possible(cache, ctx)) { alru_clean_complete(fctx, 0); return; } diff --git a/src/cleaning/alru_structs.h b/src/cleaning/alru_structs.h index 64c338ea..78f06dfe 100644 --- a/src/cleaning/alru_structs.h +++ b/src/cleaning/alru_structs.h @@ -1,6 +1,7 @@ /* * Copyright(c) 2012-2021 Intel Corporation * Copyright(c) 2022 David Lee + * Copyright(c) 2025 Huawei Technologies * SPDX-License-Identifier: BSD-3-Clause */ #ifndef __CLEANING_ALRU_STRUCTS_H__ @@ -17,11 +18,12 @@ struct alru_cleaning_policy_meta { } __attribute__((packed)); struct alru_cleaning_policy_config { - uint32_t thread_wakeup_time; /* in seconds */ - uint32_t stale_buffer_time; /* in seconds */ - uint32_t flush_max_buffers; /* in lines */ - uint32_t activity_threshold; /* in milliseconds */ - uint32_t max_dirty_ratio; /* percent */ + uint32_t thread_wakeup_time; /* in seconds */ + uint32_t stale_buffer_time; /* in seconds */ + uint32_t flush_max_buffers; /* in lines */ + uint32_t activity_threshold; /* in milliseconds */ + uint32_t dirty_ratio_threshold; /* percent */ + uint32_t dirty_ratio_inertia; /* bytes */ }; struct alru_cleaning_policy {