Switching mechanism for promotion policies
Signed-off-by: Jan Musial <jan.musial@intel.com>
This commit is contained in:
@@ -17,6 +17,9 @@
|
||||
* and insert elements from the beggining. So lifetime of a core line varies
|
||||
* depending on insertion and removal rate.
|
||||
*
|
||||
* and rb_pointer which is index to ring_buffer element that is going to be used
|
||||
* for next insertion.
|
||||
*
|
||||
* Operations:
|
||||
* - query(core_id, core_lba):
|
||||
* Check if core line is present in structure, bump up counter and
|
||||
@@ -55,9 +58,10 @@
|
||||
* | ^ | ^
|
||||
* |________| |________|
|
||||
*
|
||||
* Since rb_pointer is pointing to occupied rb slot we need to write-lock hash
|
||||
* bucket I associated with this slot and remove it from collision list.
|
||||
* We've gained an empty slot and we use slot X for new hash H entry.
|
||||
* We will attempt to insert new element at rb_pointer. Since rb_pointer is
|
||||
* pointing to occupied rb slot we need to write-lock hash bucket I associated
|
||||
* with this slot and remove it from collision list. We've gained an empty slot
|
||||
* and we use slot X for new hash H entry.
|
||||
*
|
||||
* +--+--+--+--+--+--+--+--+--+--+
|
||||
* | | |I | | | | | |H | | hash_map
|
||||
@@ -109,7 +113,8 @@ ocf_error_t hash_init(uint64_t hash_size, nhit_hash_t *ctx)
|
||||
{
|
||||
int result = 0;
|
||||
struct nhit_hash *new_ctx;
|
||||
uint64_t i;
|
||||
uint32_t i;
|
||||
int64_t i_locks;
|
||||
|
||||
new_ctx = env_vzalloc(sizeof(*new_ctx));
|
||||
if (!new_ctx) {
|
||||
@@ -138,9 +143,10 @@ ocf_error_t hash_init(uint64_t hash_size, nhit_hash_t *ctx)
|
||||
goto dealloc_hash;
|
||||
}
|
||||
|
||||
for (i = 0; i < new_ctx->hash_entries; i++) {
|
||||
if (env_rwsem_init(&new_ctx->hash_locks[i])) {
|
||||
for (i_locks = 0; i_locks < new_ctx->hash_entries; i_locks++) {
|
||||
if (env_rwsem_init(&new_ctx->hash_locks[i_locks])) {
|
||||
result = -OCF_ERR_UNKNOWN;
|
||||
i_locks--;
|
||||
goto dealloc_locks;
|
||||
}
|
||||
}
|
||||
@@ -164,8 +170,8 @@ ocf_error_t hash_init(uint64_t hash_size, nhit_hash_t *ctx)
|
||||
return 0;
|
||||
|
||||
dealloc_locks:
|
||||
for (i = 0; i < new_ctx->hash_entries; i++)
|
||||
ENV_BUG_ON(env_rwsem_destroy(&new_ctx->hash_locks[i]));
|
||||
for (; i_locks >= 0; i_locks--)
|
||||
ENV_BUG_ON(env_rwsem_destroy(&new_ctx->hash_locks[i_locks]));
|
||||
env_vfree(new_ctx->hash_locks);
|
||||
dealloc_hash:
|
||||
env_vfree(new_ctx->hash_map);
|
||||
@@ -350,12 +356,12 @@ void hash_insert(nhit_hash_t ctx, ocf_core_id_t core_id, uint64_t core_lba)
|
||||
bool hash_query(nhit_hash_t ctx, ocf_core_id_t core_id, uint64_t core_lba,
|
||||
int32_t *counter)
|
||||
{
|
||||
OCF_CHECK_NULL(counter);
|
||||
|
||||
ocf_cache_line_t hash = hash_function(core_id, core_lba,
|
||||
ctx->hash_entries);
|
||||
uint64_t rb_idx;
|
||||
|
||||
OCF_CHECK_NULL(counter);
|
||||
|
||||
env_rwsem_down_read(&ctx->hash_locks[hash]);
|
||||
rb_idx = core_line_lookup(ctx, core_id, core_lba);
|
||||
|
||||
|
@@ -13,15 +13,12 @@
|
||||
|
||||
#define NHIT_MAPPING_RATIO 2
|
||||
|
||||
#define NHIT_MIN_THRESHOLD 1
|
||||
#define NHIT_MAX_THRESHOLD 1000
|
||||
#define NHIT_THRESHOLD_DEFAULT 3
|
||||
|
||||
struct nhit_policy_context {
|
||||
nhit_hash_t hash_map;
|
||||
|
||||
/* Configurable parameters */
|
||||
env_atomic insertion_threshold;
|
||||
env_atomic64 trigger_threshold;
|
||||
};
|
||||
|
||||
ocf_error_t nhit_init(ocf_cache_t cache, ocf_promotion_policy_t policy)
|
||||
@@ -41,6 +38,9 @@ ocf_error_t nhit_init(ocf_cache_t cache, ocf_promotion_policy_t policy)
|
||||
goto dealloc_ctx;
|
||||
|
||||
env_atomic_set(&ctx->insertion_threshold, NHIT_THRESHOLD_DEFAULT);
|
||||
env_atomic64_set(&ctx->trigger_threshold,
|
||||
OCF_DIV_ROUND_UP((NHIT_TRIGGER_DEFAULT *
|
||||
ocf_metadata_get_cachelines_count(cache)), 100));
|
||||
|
||||
policy->ctx = ctx;
|
||||
|
||||
@@ -71,7 +71,7 @@ ocf_error_t nhit_set_param(ocf_promotion_policy_t policy, uint8_t param_id,
|
||||
|
||||
switch (param_id) {
|
||||
case nhit_insertion_threshold:
|
||||
if (param_value > NHIT_MIN_THRESHOLD &&
|
||||
if (param_value >= NHIT_MIN_THRESHOLD &&
|
||||
param_value < NHIT_MAX_THRESHOLD) {
|
||||
env_atomic_set(&ctx->insertion_threshold, param_value);
|
||||
} else {
|
||||
@@ -81,6 +81,22 @@ ocf_error_t nhit_set_param(ocf_promotion_policy_t policy, uint8_t param_id,
|
||||
}
|
||||
break;
|
||||
|
||||
case nhit_trigger_threshold:
|
||||
if (param_value >= NHIT_MIN_TRIGGER &&
|
||||
param_value < NHIT_MAX_TRIGGER) {
|
||||
env_atomic64_set(&ctx->trigger_threshold,
|
||||
OCF_DIV_ROUND_UP((param_value *
|
||||
ocf_metadata_get_cachelines_count(policy->owner)),
|
||||
100));
|
||||
|
||||
} else {
|
||||
ocf_cache_log(policy->owner, log_err, "Invalid nhit "
|
||||
"promotion policy insertion trigger "
|
||||
"threshold!\n");
|
||||
result = -OCF_ERR_INVAL;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ocf_cache_log(policy->owner, log_err, "Invalid nhit "
|
||||
"promotion policy parameter (%u)!\n",
|
||||
@@ -163,6 +179,12 @@ bool nhit_req_should_promote(ocf_promotion_policy_t policy,
|
||||
bool result = true;
|
||||
uint32_t i;
|
||||
uint64_t core_line;
|
||||
uint64_t occupied_cachelines =
|
||||
ocf_metadata_get_cachelines_count(policy->owner) -
|
||||
policy->owner->device->freelist_part->curr_size;
|
||||
|
||||
if (occupied_cachelines > env_atomic64_read(&ctx->trigger_threshold))
|
||||
return true;
|
||||
|
||||
for (i = 0, core_line = req->core_line_first;
|
||||
core_line <= req->core_line_last; core_line++, i++) {
|
||||
|
@@ -10,11 +10,6 @@
|
||||
#include "../../ocf_request.h"
|
||||
#include "../promotion.h"
|
||||
|
||||
enum nhit_param {
|
||||
nhit_insertion_threshold,
|
||||
nhit_param_max
|
||||
};
|
||||
|
||||
ocf_error_t nhit_init(ocf_cache_t cache, ocf_promotion_policy_t policy);
|
||||
|
||||
void nhit_deinit(ocf_promotion_policy_t policy);
|
||||
|
@@ -11,6 +11,7 @@
|
||||
|
||||
struct ocf_promotion_policy {
|
||||
ocf_cache_t owner;
|
||||
|
||||
ocf_promotion_t type;
|
||||
void *ctx;
|
||||
};
|
||||
|
@@ -55,6 +55,35 @@ void ocf_promotion_deinit(ocf_promotion_policy_t policy)
|
||||
env_vfree(policy);
|
||||
}
|
||||
|
||||
ocf_error_t ocf_promotion_set_policy(ocf_promotion_policy_t policy,
|
||||
ocf_promotion_t type)
|
||||
{
|
||||
ocf_error_t result = 0;
|
||||
ocf_cache_t cache = policy->owner;
|
||||
ocf_promotion_t prev_policy;
|
||||
|
||||
prev_policy = cache->conf_meta->promotion_policy_type;
|
||||
|
||||
if (ocf_promotion_policies[prev_policy].deinit)
|
||||
ocf_promotion_policies[prev_policy].deinit(policy);
|
||||
|
||||
cache->conf_meta->promotion_policy_type = type;
|
||||
|
||||
if (ocf_promotion_policies[type].init)
|
||||
result = ocf_promotion_policies[type].init(cache, policy);
|
||||
|
||||
if (result) {
|
||||
ocf_cache_log(cache, log_err,
|
||||
"Error switching to new promotion policy\n");
|
||||
ocf_cache_log(cache, log_err,
|
||||
"Falling back to 'always' promotion policy\n");
|
||||
cache->conf_meta->promotion_policy_type = ocf_promotion_always;
|
||||
policy->type = ocf_promotion_always;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ocf_error_t ocf_promotion_set_param(ocf_promotion_policy_t policy,
|
||||
uint8_t param_id, uint64_t param_value)
|
||||
{
|
||||
|
@@ -31,6 +31,16 @@ ocf_error_t ocf_promotion_init(ocf_cache_t cache, ocf_promotion_policy_t *policy
|
||||
*/
|
||||
void ocf_promotion_deinit(ocf_promotion_policy_t policy);
|
||||
|
||||
/**
|
||||
* @brief Switch promotion policy to type. On failure will fall back to 'always'
|
||||
*
|
||||
* @param[in] policy promotion policy handle
|
||||
* @param[in] type promotion policy target type
|
||||
*
|
||||
* @retval ocf_error_t
|
||||
*/
|
||||
ocf_error_t ocf_promotion_set_policy(ocf_promotion_policy_t policy,
|
||||
ocf_promotion_t type);
|
||||
/**
|
||||
* @brief Set promotion policy parameter
|
||||
*
|
||||
|
Reference in New Issue
Block a user