alru: add parameter `max_dirty_ratio'
With a high dirty ratio and occupancy, OCF might unable to map cache lines for new requests, thus pass-through the I/O to core devices. IOPS will drop afterwards. We need to control the dirty ratio. Existing `alru' policy gives user the chance to control the stale buffer time, activity threshold etc. They can affect the dirty ratio of the cache device, but in an empirical manner, more or less. Introducing `max_dirty_ratio' can make it explicit. At first glance, it might be better to implement a dedicated cleaner policy directly targeting dirty ratio goal, so that the `alru' parameters remains orthogonal. But one the other hand, we still need to flush dirty cache lines periodically, instead of just keeping a watermark of dirty ratio. It indicates that existing `alru' parameters are still required if we develop a new policy, and it seems reasonable to make it a parameter. To sum up, this patch does the following: - added a 'max_dirty_ratio' parameter with default value 100; - with default value 100, `alru' cleaner is identical to what is was; - with value N less than 100, the cleaner (when waken up) will active brought dirty ratio to N, regardless of staleness time. Signed-off-by: David Lee <live4thee@gmail.com>
This commit is contained in:
parent
d6b0fbceac
commit
6184ad7759
@ -15,6 +15,7 @@ enum ocf_cleaning_alru_parameters {
|
|||||||
ocf_alru_stale_buffer_time,
|
ocf_alru_stale_buffer_time,
|
||||||
ocf_alru_flush_max_buffers,
|
ocf_alru_flush_max_buffers,
|
||||||
ocf_alru_activity_threshold,
|
ocf_alru_activity_threshold,
|
||||||
|
ocf_alru_max_dirty_ratio,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -66,6 +67,16 @@ enum ocf_cleaning_alru_parameters {
|
|||||||
/** Idle time before flushing thread can start default value */
|
/** Idle time before flushing thread can start default value */
|
||||||
#define OCF_ALRU_DEFAULT_ACTIVITY_THRESHOLD 10000
|
#define OCF_ALRU_DEFAULT_ACTIVITY_THRESHOLD 10000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ALRU max dirty ratio for a cache device
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** 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
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
struct alru_flush_ctx {
|
struct alru_flush_ctx {
|
||||||
struct ocf_cleaner_attribs attribs;
|
struct ocf_cleaner_attribs attribs;
|
||||||
bool flush_perfomed;
|
bool flush_perfomed;
|
||||||
|
bool dirty_ratio_exceeded;
|
||||||
uint32_t clines_no;
|
uint32_t clines_no;
|
||||||
ocf_cache_t cache;
|
ocf_cache_t cache;
|
||||||
ocf_cleaner_end_t cmpl;
|
ocf_cleaner_end_t cmpl;
|
||||||
@ -359,6 +360,7 @@ void cleaning_policy_alru_setup(struct ocf_cache *cache)
|
|||||||
config->stale_buffer_time = OCF_ALRU_DEFAULT_STALENESS_TIME;
|
config->stale_buffer_time = OCF_ALRU_DEFAULT_STALENESS_TIME;
|
||||||
config->flush_max_buffers = OCF_ALRU_DEFAULT_FLUSH_MAX_BUFFERS;
|
config->flush_max_buffers = OCF_ALRU_DEFAULT_FLUSH_MAX_BUFFERS;
|
||||||
config->activity_threshold = OCF_ALRU_DEFAULT_ACTIVITY_THRESHOLD;
|
config->activity_threshold = OCF_ALRU_DEFAULT_ACTIVITY_THRESHOLD;
|
||||||
|
config->max_dirty_ratio = OCF_ALRU_DEFAULT_MAX_DIRTY_RATIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cleaning_policy_alru_initialize(ocf_cache_t cache, int kick_cleaner)
|
int cleaning_policy_alru_initialize(ocf_cache_t cache, int kick_cleaner)
|
||||||
@ -625,6 +627,16 @@ int cleaning_policy_alru_set_cleaning_param(ocf_cache_t cache,
|
|||||||
"activity time threshold: %d\n",
|
"activity time threshold: %d\n",
|
||||||
config->activity_threshold);
|
config->activity_threshold);
|
||||||
break;
|
break;
|
||||||
|
case ocf_alru_max_dirty_ratio:
|
||||||
|
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_cache_log(cache, log_info, "Write-back flush thread "
|
||||||
|
"max dirty ratio: %d\n",
|
||||||
|
config->max_dirty_ratio);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return -OCF_ERR_INVAL;
|
return -OCF_ERR_INVAL;
|
||||||
}
|
}
|
||||||
@ -652,6 +664,9 @@ int cleaning_policy_alru_get_cleaning_param(ocf_cache_t cache,
|
|||||||
case ocf_alru_activity_threshold:
|
case ocf_alru_activity_threshold:
|
||||||
*param_value = config->activity_threshold;
|
*param_value = config->activity_threshold;
|
||||||
break;
|
break;
|
||||||
|
case ocf_alru_max_dirty_ratio:
|
||||||
|
*param_value = config->max_dirty_ratio;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return -OCF_ERR_INVAL;
|
return -OCF_ERR_INVAL;
|
||||||
}
|
}
|
||||||
@ -698,13 +713,34 @@ static bool clean_later(ocf_cache_t cache, uint32_t *delta)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_cleanup_possible(ocf_cache_t cache)
|
static bool check_for_dirty_ratio(ocf_cache_t cache,
|
||||||
|
struct alru_cleaning_policy_config *config)
|
||||||
|
{
|
||||||
|
struct ocf_cache_info info;
|
||||||
|
|
||||||
|
if (config->max_dirty_ratio == OCF_ALRU_MAX_MAX_DIRTY_RATIO)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ocf_cache_get_info(cache, &info))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return info.dirty * 100 / info.size >= config->max_dirty_ratio;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_cleanup_possible(ocf_cache_t cache, struct alru_flush_ctx *fctx)
|
||||||
{
|
{
|
||||||
struct alru_cleaning_policy_config *config;
|
struct alru_cleaning_policy_config *config;
|
||||||
uint32_t delta;
|
uint32_t delta;
|
||||||
|
|
||||||
config = (void *)&cache->conf_meta->cleaning[ocf_cleaning_alru].data;
|
config = (void *)&cache->conf_meta->cleaning[ocf_cleaning_alru].data;
|
||||||
|
|
||||||
|
if (check_for_dirty_ratio(cache, config)) {
|
||||||
|
fctx->dirty_ratio_exceeded = true;
|
||||||
|
OCF_DEBUG_PARAM(cache, "Dirty ratio exceeds: %u%%",
|
||||||
|
config->max_dirty_ratio);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (check_for_io_activity(cache, config)) {
|
if (check_for_io_activity(cache, config)) {
|
||||||
OCF_DEBUG_PARAM(cache, "IO activity detected");
|
OCF_DEBUG_PARAM(cache, "IO activity detected");
|
||||||
return false;
|
return false;
|
||||||
@ -794,7 +830,7 @@ static int get_data_to_flush(struct alru_context *ctx)
|
|||||||
|
|
||||||
cache_line = user_part->clean_pol->policy.alru.lru_tail;
|
cache_line = user_part->clean_pol->policy.alru.lru_tail;
|
||||||
|
|
||||||
last_access = compute_timestamp(config);
|
last_access = fctx->dirty_ratio_exceeded ? (uint32_t)(~0UL) : compute_timestamp(config);
|
||||||
|
|
||||||
#if OCF_CLEANING_DEBUG == 1
|
#if OCF_CLEANING_DEBUG == 1
|
||||||
alru = &ocf_metadata_get_cleaning_policy(cache, cache_line)
|
alru = &ocf_metadata_get_cleaning_policy(cache, cache_line)
|
||||||
@ -852,7 +888,7 @@ static void alru_clean(struct alru_context *ctx)
|
|||||||
ocf_cache_t cache = fctx->cache;
|
ocf_cache_t cache = fctx->cache;
|
||||||
int to_clean;
|
int to_clean;
|
||||||
|
|
||||||
if (!is_cleanup_possible(cache)) {
|
if (!is_cleanup_possible(cache, fctx)) {
|
||||||
alru_clean_complete(fctx, 0);
|
alru_clean_complete(fctx, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -909,6 +945,7 @@ void cleaning_alru_perform_cleaning(ocf_cache_t cache, ocf_cleaner_end_t cmpl)
|
|||||||
fctx->cache = cache;
|
fctx->cache = cache;
|
||||||
fctx->cmpl = cmpl;
|
fctx->cmpl = cmpl;
|
||||||
fctx->flush_perfomed = false;
|
fctx->flush_perfomed = false;
|
||||||
|
fctx->dirty_ratio_exceeded = false;
|
||||||
|
|
||||||
alru_clean(ctx);
|
alru_clean(ctx);
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ struct alru_cleaning_policy_config {
|
|||||||
uint32_t stale_buffer_time; /* in seconds */
|
uint32_t stale_buffer_time; /* in seconds */
|
||||||
uint32_t flush_max_buffers; /* in lines */
|
uint32_t flush_max_buffers; /* in lines */
|
||||||
uint32_t activity_threshold; /* in milliseconds */
|
uint32_t activity_threshold; /* in milliseconds */
|
||||||
|
uint32_t max_dirty_ratio; /* percent */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct alru_cleaning_policy {
|
struct alru_cleaning_policy {
|
||||||
|
Loading…
Reference in New Issue
Block a user