From 917cbd859ac580aa4435960d991fbee3e3c35c27 Mon Sep 17 00:00:00 2001 From: Jan Musial Date: Thu, 11 Jul 2019 12:19:29 +0200 Subject: [PATCH] Add promotion policy API and use it in I/O path Promotion policy is supposed to perform ALRU noise filtering by eliminating one-hit wonders being added to cache and polluting it. Signed-off-by: Jan Musial --- inc/ocf_def.h | 19 ++++- inc/ocf_mngt.h | 6 ++ src/engine/engine_common.c | 19 ++++- src/engine/engine_discard.c | 2 + src/engine/engine_rd.c | 4 +- src/engine/engine_wb.c | 4 +- src/engine/engine_wt.c | 4 +- src/eviction/eviction.c | 2 +- src/metadata/metadata_superblock.h | 4 ++ src/mngt/ocf_mngt_cache.c | 76 ++++++++++++++++++-- src/ocf_cache_priv.h | 2 + src/ocf_request.h | 4 +- src/promotion/nhit.c | 36 ++++++++++ src/promotion/nhit.h | 26 +++++++ src/promotion/ops.h | 42 ++++++++++++ src/promotion/promotion.c | 99 +++++++++++++++++++++++++++ src/promotion/promotion.h | 69 +++++++++++++++++++ src/utils/utils_cache_line.c | 1 + src/utils/utils_cache_line.h | 2 +- tests/functional/pyocf/types/cache.py | 9 +++ 20 files changed, 409 insertions(+), 21 deletions(-) create mode 100644 src/promotion/nhit.c create mode 100644 src/promotion/nhit.h create mode 100644 src/promotion/ops.h create mode 100644 src/promotion/promotion.c create mode 100644 src/promotion/promotion.h diff --git a/inc/ocf_def.h b/inc/ocf_def.h index 0fa37da..7125396 100644 --- a/inc/ocf_def.h +++ b/inc/ocf_def.h @@ -193,7 +193,7 @@ typedef enum { } ocf_seq_cutoff_policy; /** - * OCF supported eviction types + * OCF supported eviction policy types */ typedef enum { ocf_eviction_lru = 0, @@ -206,6 +206,23 @@ typedef enum { /*!< Default eviction policy */ } ocf_eviction_t; +/** + * OCF supported promotion policy types + */ +typedef enum { + ocf_promotion_nop = 0, + /*!< No promotion policy. Cache inserts are not filtered */ + + ocf_promotion_nhit, + /*!< Line can be inserted after N requests for it */ + + ocf_promotion_max, + /*!< Stopper of enumerator */ + + ocf_promotion_default = ocf_promotion_nop, + /*!< Default promotion policy */ +} ocf_promotion_t; + /** * OCF supported Write-Back cleaning policies type */ diff --git a/inc/ocf_mngt.h b/inc/ocf_mngt.h index d1285ae..5029110 100644 --- a/inc/ocf_mngt.h +++ b/inc/ocf_mngt.h @@ -262,6 +262,11 @@ struct ocf_mngt_cache_config { */ ocf_eviction_t eviction_policy; + /** + * @brief Promotion policy type + */ + ocf_promotion_t promotion_policy; + /** * @brief Cache line size */ @@ -313,6 +318,7 @@ static inline void ocf_mngt_cache_config_set_default( cfg->name = NULL; cfg->cache_mode = ocf_cache_mode_default; cfg->eviction_policy = ocf_eviction_default; + cfg->promotion_policy = ocf_promotion_default; cfg->cache_line_size = ocf_cache_line_size_4; cfg->metadata_layout = ocf_metadata_layout_default; cfg->metadata_volatile = false; diff --git a/src/engine/engine_common.c b/src/engine/engine_common.c index 2bd6544..e14b1b6 100644 --- a/src/engine/engine_common.c +++ b/src/engine/engine_common.c @@ -15,6 +15,7 @@ #include "../utils/utils_cleaner.h" #include "../metadata/metadata.h" #include "../eviction/eviction.h" +#include "../promotion/promotion.h" void ocf_engine_error(struct ocf_request *req, bool stop_cache, const char *msg) @@ -171,6 +172,7 @@ void ocf_engine_traverse(struct ocf_request *req) if (entry->status != LOOKUP_HIT) { req->info.seq_req = false; + /* There is miss then lookup for next map entry */ OCF_DEBUG_PARAM(cache, "Miss, core line = %llu", entry->core_line); @@ -249,7 +251,7 @@ static void ocf_engine_map_cache_line(struct ocf_request *req, ocf_cleaning_t clean_policy_type; if (cache->device->freelist_part->curr_size == 0) { - req->info.eviction_error = 1; + req->info.mapping_error = 1; return; } @@ -320,11 +322,16 @@ void ocf_engine_map(struct ocf_request *req) int status = LOOKUP_MAPPED; ocf_core_id_t core_id = ocf_core_get_id(req->core); + if (!ocf_promotion_req_should_promote(cache->promotion_policy, req)) { + req->info.mapping_error = 1; + return; + } + if (ocf_engine_unmapped_count(req)) status = space_managment_evict_do(cache, req, ocf_engine_unmapped_count(req)); - if (req->info.eviction_error) + if (req->info.mapping_error) return; ocf_req_clear_info(req); @@ -342,7 +349,7 @@ void ocf_engine_map(struct ocf_request *req) ocf_engine_map_cache_line(req, entry->core_line, entry->hash_key, &entry->coll_idx); - if (req->info.eviction_error) { + if (req->info.mapping_error) { /* * Eviction error (mapping error), need to * clean, return and do pass through @@ -364,6 +371,12 @@ void ocf_engine_map(struct ocf_request *req) } + if (!req->info.mapping_error) { + /* request has been inserted into cache - purge it from promotion + * policy */ + ocf_promotion_req_purge(cache->promotion_policy, req); + } + OCF_DEBUG_PARAM(req->cache, "Sequential - %s", req->info.seq_req ? "Yes" : "No"); } diff --git a/src/engine/engine_discard.c b/src/engine/engine_discard.c index 4b80573..9529257 100644 --- a/src/engine/engine_discard.c +++ b/src/engine/engine_discard.c @@ -60,6 +60,8 @@ static void _ocf_discard_core_complete(struct ocf_io *io, int error) OCF_DEBUG_RQ(req, "Core DISCARD Completion"); + ocf_promotion_req_purge(req->cache->promotion_policy, req); + _ocf_discard_complete_req(req, error); ocf_io_put(io); diff --git a/src/engine/engine_rd.c b/src/engine/engine_rd.c index 0a58a9e..504b182 100644 --- a/src/engine/engine_rd.c +++ b/src/engine/engine_rd.c @@ -269,7 +269,7 @@ int ocf_read_generic(struct ocf_request *req) */ ocf_engine_map(req); - if (!req->info.eviction_error) { + if (!req->info.mapping_error) { if (ocf_engine_is_hit(req)) { /* After mapping turns out there is hit, * so lock OCF request for read access @@ -287,7 +287,7 @@ int ocf_read_generic(struct ocf_request *req) /*- END Metadata WR access -----------------------------------*/ } - if (!req->info.eviction_error) { + if (!req->info.mapping_error) { if (lock >= 0) { if (lock != OCF_LOCK_ACQUIRED) { /* Lock was not acquired, need to wait for resume */ diff --git a/src/engine/engine_wb.c b/src/engine/engine_wb.c index d7a8c08..d495518 100644 --- a/src/engine/engine_wb.c +++ b/src/engine/engine_wb.c @@ -204,7 +204,7 @@ int ocf_write_wb(struct ocf_request *req) */ ocf_engine_map(req); - if (!req->info.eviction_error) { + if (!req->info.mapping_error) { /* Lock request for WRITE access */ lock = ocf_req_trylock_wr(req); } @@ -212,7 +212,7 @@ int ocf_write_wb(struct ocf_request *req) OCF_METADATA_UNLOCK_WR(); /*- END Metadata WR access ---------*/ } - if (!req->info.eviction_error) { + if (!req->info.mapping_error) { if (lock >= 0) { if (lock != OCF_LOCK_ACQUIRED) { /* WR lock was not acquired, need to wait for resume */ diff --git a/src/engine/engine_wt.c b/src/engine/engine_wt.c index a5be349..ef97510 100644 --- a/src/engine/engine_wt.c +++ b/src/engine/engine_wt.c @@ -197,7 +197,7 @@ int ocf_write_wt(struct ocf_request *req) */ ocf_engine_map(req); - if (!req->info.eviction_error) { + if (!req->info.mapping_error) { /* Lock request for WRITE access */ lock = ocf_req_trylock_wr(req); } @@ -205,7 +205,7 @@ int ocf_write_wt(struct ocf_request *req) OCF_METADATA_UNLOCK_WR(); /*- END Metadata WR access ---------*/ } - if (!req->info.eviction_error) { + if (!req->info.mapping_error) { if (lock >= 0) { if (lock != OCF_LOCK_ACQUIRED) { /* WR lock was not acquired, need to wait for resume */ diff --git a/src/eviction/eviction.c b/src/eviction/eviction.c index 81eae08..0bacee8 100644 --- a/src/eviction/eviction.c +++ b/src/eviction/eviction.c @@ -118,6 +118,6 @@ int space_managment_evict_do(struct ocf_cache *cache, if (evict_cline_no <= evicted) return LOOKUP_MAPPED; - req->info.eviction_error |= true; + req->info.mapping_error |= true; return LOOKUP_MISS; } diff --git a/src/metadata/metadata_superblock.h b/src/metadata/metadata_superblock.h index 18b52da..fd30acd 100644 --- a/src/metadata/metadata_superblock.h +++ b/src/metadata/metadata_superblock.h @@ -6,6 +6,9 @@ #ifndef __METADATA_SUPERBLOCK_H__ #define __METADATA_SUPERBLOCK_H__ +#include "../eviction/eviction.h" +#include "../promotion/promotion.h" + #define CACHE_MAGIC_NUMBER 0x187E1CA6 /** @@ -38,6 +41,7 @@ struct ocf_superblock_config { struct cleaning_policy_config cleaning[CLEANING_POLICY_TYPE_MAX]; ocf_eviction_t eviction_policy_type; + ocf_promotion_t promotion_policy_type; /* Current core sequence number */ ocf_core_id_t curr_core_seq_no; diff --git a/src/mngt/ocf_mngt_cache.c b/src/mngt/ocf_mngt_cache.c index c359179..8ed3201 100644 --- a/src/mngt/ocf_mngt_cache.c +++ b/src/mngt/ocf_mngt_cache.c @@ -91,6 +91,8 @@ struct ocf_cache_mngt_init_params { ocf_cache_mode_t cache_mode; /*!< cache mode */ + + ocf_promotion_t promotion_policy; } metadata; }; @@ -233,10 +235,11 @@ static void __init_partitions_attached(ocf_cache_t cache) } } -static void __init_cleaning_policy(ocf_cache_t cache) +static ocf_error_t __init_cleaning_policy(ocf_cache_t cache) { ocf_cleaning_t cleaning_policy = ocf_cleaning_default; int i; + ocf_error_t result = 0; OCF_ASSERT_PLUGGED(cache); @@ -247,7 +250,9 @@ static void __init_cleaning_policy(ocf_cache_t cache) cache->conf_meta->cleaning_policy_type = ocf_cleaning_default; if (cleaning_policy_ops[cleaning_policy].initialize) - cleaning_policy_ops[cleaning_policy].initialize(cache, 1); + result = cleaning_policy_ops[cleaning_policy].initialize(cache, 1); + + return result; } static void __deinit_cleaning_policy(ocf_cache_t cache) @@ -267,6 +272,19 @@ static void __init_eviction_policy(ocf_cache_t cache, cache->conf_meta->eviction_policy_type = eviction; } +static ocf_error_t __init_promotion_policy(ocf_cache_t cache) +{ + ENV_BUG_ON(cache->promotion_policy); + + return ocf_promotion_init(cache, &cache->promotion_policy); +} + +static void __deinit_promotion_policy(ocf_cache_t cache) +{ + ocf_promotion_deinit(cache->promotion_policy); + cache->promotion_policy = NULL; +} + static void __init_cores(ocf_cache_t cache) { /* No core devices yet */ @@ -300,17 +318,39 @@ static void __reset_stats(ocf_cache_t cache) } } -static void init_attached_data_structures(ocf_cache_t cache, +static ocf_error_t init_attached_data_structures(ocf_cache_t cache, ocf_eviction_t eviction_policy) { + ocf_error_t result; + /* Lock to ensure consistency */ OCF_METADATA_LOCK_WR(); + __init_hash_table(cache); __init_freelist(cache); __init_partitions_attached(cache); - __init_cleaning_policy(cache); + + result = __init_cleaning_policy(cache); + if (result) { + ocf_cache_log(cache, log_err, + "Cannot initialize cleaning policy\n"); + OCF_METADATA_UNLOCK_WR(); + return result; + } + __init_eviction_policy(cache, eviction_policy); + result =__init_promotion_policy(cache); + if (result) { + ocf_cache_log(cache, log_err, + "Cannot initialize promotion policy\n"); + __deinit_cleaning_policy(cache); + OCF_METADATA_UNLOCK_WR(); + return result; + } + OCF_METADATA_UNLOCK_WR(); + + return 0; } static void init_attached_data_structures_recovery(ocf_cache_t cache) @@ -468,6 +508,7 @@ void _ocf_mngt_init_instance_load_complete(void *priv, int error) struct ocf_cache_attach_context *context = priv; ocf_cache_t cache = context->cache; ocf_cleaning_t cleaning_policy; + ocf_error_t result; if (error) { ocf_cache_log(cache, log_err, @@ -480,9 +521,23 @@ void _ocf_mngt_init_instance_load_complete(void *priv, int error) goto out; if (context->metadata.shutdown_status == ocf_metadata_clean_shutdown) - cleaning_policy_ops[cleaning_policy].initialize(cache, 0); + result = cleaning_policy_ops[cleaning_policy].initialize(cache, 0); else - cleaning_policy_ops[cleaning_policy].initialize(cache, 1); + result = cleaning_policy_ops[cleaning_policy].initialize(cache, 1); + + if (result) { + ocf_cache_log(cache, log_err, + "Cannot initialize cleaning policy\n"); + OCF_PL_FINISH_RET(context->pipeline, result); + } + + result = __init_promotion_policy(cache); + if (result) { + __deinit_cleaning_policy(cache); + ocf_cache_log(cache, log_err, + "Cannot initialize promotion policy\n"); + OCF_PL_FINISH_RET(context->pipeline, result); + } out: ocf_pipeline_next(context->pipeline); @@ -1023,6 +1078,7 @@ static void _ocf_mngt_attach_prepare_metadata(ocf_pipeline_t pipeline, static void _ocf_mngt_init_instance_init(struct ocf_cache_attach_context *context) { ocf_cache_t cache = context->cache; + ocf_error_t result; if (!context->metadata.status && !context->cfg.force && context->metadata.shutdown_status != @@ -1044,7 +1100,9 @@ static void _ocf_mngt_init_instance_init(struct ocf_cache_attach_context *contex } } - init_attached_data_structures(cache, cache->eviction_policy_init); + result = init_attached_data_structures(cache, cache->eviction_policy_init); + if (result) + OCF_PL_FINISH_RET(context->pipeline, result); /* In initial cache state there is no dirty data, so all dirty data is considered to be flushed @@ -1177,6 +1235,8 @@ static void _ocf_mngt_cache_init(ocf_cache_t cache, */ cache->conf_meta->cache_mode = params->metadata.cache_mode; cache->conf_meta->metadata_layout = params->metadata.layout; + cache->conf_meta->promotion_policy_type = + params->metadata.promotion_policy; for (i = 0; i < OCF_IO_CLASS_MAX + 1; ++i) { cache->user_parts[i].config = @@ -1208,6 +1268,7 @@ static int _ocf_mngt_cache_start(ocf_ctx_t ctx, ocf_cache_t *cache, params.metadata.layout = cfg->metadata_layout; params.metadata.line_size = cfg->cache_line_size; params.metadata_volatile = cfg->metadata_volatile; + params.metadata.promotion_policy = cfg->promotion_policy; params.locked = cfg->locked; /* Prepare cache */ @@ -1766,6 +1827,7 @@ static void _ocf_mngt_cache_unplug(ocf_cache_t cache, bool stop, ocf_stop_cleaner(cache); __deinit_cleaning_policy(cache); + __deinit_promotion_policy(cache); if (ocf_mngt_cache_is_dirty(cache)) { ENV_BUG_ON(!stop); diff --git a/src/ocf_cache_priv.h b/src/ocf_cache_priv.h index d03d105..b599f61 100644 --- a/src/ocf_cache_priv.h +++ b/src/ocf_cache_priv.h @@ -20,6 +20,7 @@ #include "cleaning/cleaning.h" #include "ocf_logger_priv.h" #include "ocf/ocf_trace.h" +#include "promotion/promotion.h" #define DIRTY_FLUSHED 1 #define DIRTY_NOT_FLUSHED 0 @@ -149,6 +150,7 @@ struct ocf_cache { struct ocf_cleaner cleaner; struct ocf_metadata_updater metadata_updater; + ocf_promotion_policy_t promotion_policy; struct ocf_async_lock lock; diff --git a/src/ocf_request.h b/src/ocf_request.h index 44590b2..9d22a46 100644 --- a/src/ocf_request.h +++ b/src/ocf_request.h @@ -30,8 +30,8 @@ struct ocf_req_info { uint32_t flush_metadata : 1; /*!< This bit tells if metadata flushing is required */ - uint32_t eviction_error : 1; - /*!< Eviction error flag */ + uint32_t mapping_error : 1; + /*!< Core lines in this request were not mapped into cache */ uint32_t re_part : 1; /*!< This bit indicate that in the request some cache lines diff --git a/src/promotion/nhit.c b/src/promotion/nhit.c new file mode 100644 index 0000000..3e05e2a --- /dev/null +++ b/src/promotion/nhit.c @@ -0,0 +1,36 @@ +/* + * Copyright(c) 2019 Intel Corporation + * SPDX-License-Identifier: BSD-3-Clause-Clear + */ + +#include "../metadata/metadata.h" + +#include "nhit.h" + +ocf_error_t nhit_init(ocf_cache_t cache, ocf_promotion_policy_t policy) +{ + return 0; +} + +void nhit_deinit(ocf_promotion_policy_t policy) +{ + +} + +ocf_error_t nhit_set_param(ocf_promotion_policy_t policy, uint8_t param_id, + uint64_t param_value) +{ + return 0; +} + +void nhit_req_purge(ocf_promotion_policy_t policy, + struct ocf_request *req) +{ + +} + +bool nhit_req_should_promote(ocf_promotion_policy_t policy, struct ocf_request *req) +{ + return true; +} + diff --git a/src/promotion/nhit.h b/src/promotion/nhit.h new file mode 100644 index 0000000..53e08cf --- /dev/null +++ b/src/promotion/nhit.h @@ -0,0 +1,26 @@ +/* + * Copyright(c) 2019 Intel Corporation + * SPDX-License-Identifier: BSD-3-Clause-Clear + */ + +#ifndef NHIT_PROMOTION_POLICY_H_ +#define NHIT_PROMOTION_POLICY_H_ + +#include "ocf/ocf.h" +#include "../ocf_request.h" +#include "promotion.h" + +ocf_error_t nhit_init(ocf_cache_t cache, ocf_promotion_policy_t policy); + +void nhit_deinit(ocf_promotion_policy_t policy); + +ocf_error_t nhit_set_param(ocf_promotion_policy_t policy, uint8_t param_id, + uint64_t param_value); + +void nhit_req_purge(ocf_promotion_policy_t policy, + struct ocf_request *req); + +bool nhit_req_should_promote(ocf_promotion_policy_t policy, + struct ocf_request *req); + +#endif /* NHIT_PROMOTION_POLICY_H_ */ diff --git a/src/promotion/ops.h b/src/promotion/ops.h new file mode 100644 index 0000000..6f5a113 --- /dev/null +++ b/src/promotion/ops.h @@ -0,0 +1,42 @@ +/* + * Copyright(c) 2019 Intel Corporation + * SPDX-License-Identifier: BSD-3-Clause-Clear + */ + +#ifndef PROMOTION_OPS_H_ +#define PROMOTION_OPS_H_ + +#include "../metadata/metadata.h" +#include "promotion.h" + +struct ocf_promotion_policy { + ocf_promotion_t type; + void *ctx; +}; + +struct promotion_policy_ops { + const char *name; + /*!< Promotion policy name */ + + ocf_error_t (*init)(ocf_cache_t cache, ocf_promotion_policy_t policy); + /*!< Allocate and initialize promotion policy */ + + void (*deinit)(ocf_promotion_policy_t policy); + /*!< Deinit and free promotion policy */ + + ocf_error_t (*set_param)(ocf_promotion_policy_t policy, uint8_t param_id, + uint64_t param_value); + /*!< Set promotion policy parameter */ + + void (*req_purge)(ocf_promotion_policy_t policy, + struct ocf_request *req); + /*!< Call when request core lines have been inserted or it is + * a discard request */ + + bool (*req_should_promote)(ocf_promotion_policy_t policy, + struct ocf_request *req); + /*!< Should request lines be inserted into cache */ +}; + +#endif /* PROMOTION_OPS_H_ */ + diff --git a/src/promotion/promotion.c b/src/promotion/promotion.c new file mode 100644 index 0000000..c96a773 --- /dev/null +++ b/src/promotion/promotion.c @@ -0,0 +1,99 @@ +/* + * Copyright(c) 2019 Intel Corporation + * SPDX-License-Identifier: BSD-3-Clause-Clear + */ + +#include "../metadata/metadata.h" + +#include "promotion.h" +#include "ops.h" +#include "nhit.h" + +struct promotion_policy_ops ocf_promotion_policies[ocf_promotion_max] = { + [ocf_promotion_nop] = { + .name = "nop", + }, + [ocf_promotion_nhit] = { + .name = "nhit", + .init = nhit_init, + .deinit = nhit_deinit, + .set_param = nhit_set_param, + .req_purge = nhit_req_purge, + .req_should_promote = nhit_req_should_promote, + }, +}; + +ocf_error_t ocf_promotion_init(ocf_cache_t cache, ocf_promotion_policy_t *policy) +{ + ocf_promotion_t type = cache->conf_meta->promotion_policy_type; + ocf_error_t result = 0; + + ENV_BUG_ON(type >= ocf_promotion_max); + + *policy = env_vmalloc(sizeof(**policy)); + if (!*policy) + return -OCF_ERR_NO_MEM; + + (*policy)->type = type; + + if (ocf_promotion_policies[type].init) + result = ocf_promotion_policies[type].init(cache, *policy); + + return result; +} + +void ocf_promotion_deinit(ocf_promotion_policy_t policy) +{ + ocf_promotion_t type = policy->type; + + ENV_BUG_ON(type >= ocf_promotion_max); + + if (ocf_promotion_policies[type].deinit) + ocf_promotion_policies[type].deinit(policy); + + env_vfree(policy); +} + +ocf_error_t ocf_promotion_set_param(ocf_promotion_policy_t policy, + uint8_t param_id, uint64_t param_value) +{ + ocf_promotion_t type = policy->type; + ocf_error_t result = 0; + + ENV_BUG_ON(type >= ocf_promotion_max); + + if (ocf_promotion_policies[type].set_param) { + result = ocf_promotion_policies[type].set_param(policy, param_id, + param_value); + } + + return result; +} + +void ocf_promotion_req_purge(ocf_promotion_policy_t policy, + struct ocf_request *req) +{ + ocf_promotion_t type = policy->type; + + ENV_BUG_ON(type >= ocf_promotion_max); + + if (ocf_promotion_policies[type].req_purge) + ocf_promotion_policies[type].req_purge(policy, req); +} + +bool ocf_promotion_req_should_promote(ocf_promotion_policy_t policy, + struct ocf_request *req) +{ + ocf_promotion_t type = policy->type; + bool result = true; + + ENV_BUG_ON(type >= ocf_promotion_max); + + if (ocf_promotion_policies[type].req_should_promote) { + result = ocf_promotion_policies[type].req_should_promote(policy, + req); + } + + return result; +} + diff --git a/src/promotion/promotion.h b/src/promotion/promotion.h new file mode 100644 index 0000000..14d240c --- /dev/null +++ b/src/promotion/promotion.h @@ -0,0 +1,69 @@ +/* + * Copyright(c) 2019 Intel Corporation + * SPDX-License-Identifier: BSD-3-Clause-Clear + */ + +#ifndef PROMOTION_H_ +#define PROMOTION_H_ + +#include "ocf/ocf.h" +#include "../ocf_request.h" + +typedef struct ocf_promotion_policy *ocf_promotion_policy_t; +/** + * @brief Allocate and initialize promotion policy. Should be called after cache + * metadata has been allocated and cache->conf_meta->promotion_policy_type has + * been set. + * + * @param[in] cache OCF cache instance + * @param[out] param initialized policy handle + * + * @retval ocf_error_t + */ +ocf_error_t ocf_promotion_init(ocf_cache_t cache, ocf_promotion_policy_t *policy); + +/** + * @brief Stop, deinitialize and free promotion policy structures. + * + * @param[in] policy promotion policy handle + * + * @retval none + */ +void ocf_promotion_deinit(ocf_promotion_policy_t policy); + +/** + * @brief Set promotion policy parameter + * + * @param[in] policy promotion policy handle + * @param[in] param_id id of parameter to be set + * @param[in] param_value value of parameter to be set + * + * @retval ocf_error_t + */ +ocf_error_t ocf_promotion_set_param(ocf_promotion_policy_t policy, + uint8_t param_id, uint64_t param_value); + +/** + * @brief Update promotion policy after cache lines have been promoted to cache + * or discarded from core device + * + * @param[in] policy promotion policy handle + * @param[in] req OCF request to be purged + * + * @retval none + */ +void ocf_promotion_req_purge(ocf_promotion_policy_t policy, + struct ocf_request *req); + +/** + * @brief Check in promotion policy whether core lines in request can be promoted + * + * @param[in] policy promotion policy handle + * @param[in] req OCF request which is to be promoted + * + * @retval should core lines belonging to this request be promoted + */ +bool ocf_promotion_req_should_promote(ocf_promotion_policy_t policy, + struct ocf_request *req); + +#endif /* PROMOTION_H_ */ diff --git a/src/utils/utils_cache_line.c b/src/utils/utils_cache_line.c index 3777aa1..5e693e5 100644 --- a/src/utils/utils_cache_line.c +++ b/src/utils/utils_cache_line.c @@ -4,6 +4,7 @@ */ #include "utils_cache_line.h" +#include "../promotion/promotion.h" static inline void ocf_cleaning_set_hot_cache_line(struct ocf_cache *cache, ocf_cache_line_t line) diff --git a/src/utils/utils_cache_line.h b/src/utils/utils_cache_line.h index e014df6..a692e51 100644 --- a/src/utils/utils_cache_line.h +++ b/src/utils/utils_cache_line.h @@ -7,9 +7,9 @@ #define UTILS_CACHE_LINE_H_ #include "../metadata/metadata.h" +#include "../concurrency/ocf_cache_concurrency.h" #include "../eviction/eviction.h" #include "../eviction/ops.h" -#include "../concurrency/ocf_cache_concurrency.h" #include "../engine/cache_engine.h" #include "../ocf_request.h" #include "../ocf_def_priv.h" diff --git a/tests/functional/pyocf/types/cache.py b/tests/functional/pyocf/types/cache.py index 35c3d84..9559cd3 100644 --- a/tests/functional/pyocf/types/cache.py +++ b/tests/functional/pyocf/types/cache.py @@ -46,6 +46,7 @@ class CacheConfig(Structure): ("_name", c_char_p), ("_cache_mode", c_uint32), ("_eviction_policy", c_uint32), + ("_promotion_policy", c_uint32), ("_cache_line_size", c_uint64), ("_metadata_layout", c_uint32), ("_metadata_volatile", c_bool), @@ -92,6 +93,12 @@ class EvictionPolicy(IntEnum): DEFAULT = LRU +class PromotionPolicy(IntEnum): + NOP = 0 + NHIT = 1 + DEFAULT = NOP + + class CleaningPolicy(IntEnum): NOP = 0 ALRU = 1 @@ -131,6 +138,7 @@ class Cache: name: str = "", cache_mode: CacheMode = CacheMode.DEFAULT, eviction_policy: EvictionPolicy = EvictionPolicy.DEFAULT, + promotion_policy: PromotionPolicy = PromotionPolicy.DEFAULT, cache_line_size: CacheLineSize = CacheLineSize.DEFAULT, metadata_layout: MetadataLayout = MetadataLayout.DEFAULT, metadata_volatile: bool = False, @@ -150,6 +158,7 @@ class Cache: _name=name.encode("ascii") if name else None, _cache_mode=cache_mode, _eviction_policy=eviction_policy, + _promotion_policy=promotion_policy, _cache_line_size=cache_line_size, _metadata_layout=metadata_layout, _metadata_volatile=metadata_volatile,