Introduce ocf_cache_has_pending_cleaning() function

Signed-off-by: Robert Baldyga <robert.baldyga@intel.com>
This commit is contained in:
Robert Baldyga 2019-03-26 14:56:33 +01:00
parent 03c95d36f0
commit 5699422586
4 changed files with 83 additions and 68 deletions

View File

@ -174,6 +174,13 @@ void ocf_cache_wait_for_io_finish(ocf_cache_t cache);
*/ */
bool ocf_cache_has_pending_requests(ocf_cache_t cache); bool ocf_cache_has_pending_requests(ocf_cache_t cache);
/**
* @brief Check if cleaning triggered by eviction runs on the cache
*
* @param[in] cache Cache object
*/
bool ocf_cache_has_pending_cleaning(ocf_cache_t cache);
/** /**
* @brief Get cache mode of given cache object * @brief Get cache mode of given cache object
* *

View File

@ -9,7 +9,6 @@
#include "../ocf_ctx_priv.h" #include "../ocf_ctx_priv.h"
#include "../metadata/metadata.h" #include "../metadata/metadata.h"
#include "../engine/cache_engine.h" #include "../engine/cache_engine.h"
#include "../utils/utils_part.h"
#include "../utils/utils_req.h" #include "../utils/utils_req.h"
#include "../utils/utils_device.h" #include "../utils/utils_device.h"
#include "../eviction/ops.h" #include "../eviction/ops.h"
@ -118,53 +117,6 @@ void cache_mng_core_remove_from_cache(struct ocf_cache *cache, int core_id)
cache->conf_meta->core_count--; cache->conf_meta->core_count--;
} }
/**
* @brief Wait for the end of asynchronous cleaning
*
* @param cache OCF cache instance
* @param timeout_ms Timeout for waiting in milliseconds
* @note When timeout is less than zero it means wait forever
*
* @retval 0 cleaning finished
* @retval non-zero timeout and cleaning still in progress
*/
static int _ocf_cleaning_wait_for_finish(struct ocf_cache *cache,
const int32_t timeout_ms)
{
struct ocf_user_part *curr_part;
ocf_part_id_t part_id;
bool cleaning_active = ocf_cache_is_device_attached(cache);
int64_t _timeout = timeout_ms;
while (cleaning_active) {
cleaning_active = false;
OCF_METADATA_LOCK_WR();
for_each_part(cache, curr_part, part_id) {
if (env_atomic_read(&cache->cleaning[part_id])) {
cleaning_active = true;
break;
}
}
OCF_METADATA_UNLOCK_WR();
if (cleaning_active) {
env_msleep(20);
if (timeout_ms >= 0) {
_timeout -= 20;
if (_timeout <= 0)
break;
}
}
};
if (cleaning_active)
return -EBUSY;
return 0;
}
void ocf_mngt_cache_put(ocf_cache_t cache) void ocf_mngt_cache_put(ocf_cache_t cache)
{ {
OCF_CHECK_NULL(cache); OCF_CHECK_NULL(cache);
@ -275,15 +227,6 @@ static int _ocf_mngt_cache_lock(ocf_cache_t cache, int (*lock_fn)(env_rwsem *s),
goto unlock; goto unlock;
} }
/* Return, when asynchronous cleaning is finished */
if (_ocf_cleaning_wait_for_finish(cache, 60 * 1000)) {
/* Because of some reasons, asynchronous cleaning still active,
* cannot continue
*/
ret = -OCF_ERR_CACHE_IN_USE;
goto unlock;
}
return 0; return 0;
unlock: unlock:
@ -321,15 +264,15 @@ int ocf_mngt_cache_read_trylock(ocf_cache_t cache)
} }
/* if cache is either fully initialized or during recovery */ /* if cache is either fully initialized or during recovery */
static ocf_cache_t _ocf_mngt_cache_try_get(ocf_cache_t cache) static bool _ocf_mngt_cache_try_get(ocf_cache_t cache)
{ {
if (!!cache->valid_ocf_cache_device_t) { if (!!cache->valid_ocf_cache_device_t) {
/* Increase reference counter */ /* Increase reference counter */
env_atomic_inc(&cache->ref_count); env_atomic_inc(&cache->ref_count);
return cache; return true;
} }
return NULL; return false;
} }
int ocf_mngt_cache_get(ocf_cache_t cache) int ocf_mngt_cache_get(ocf_cache_t cache)
@ -345,7 +288,7 @@ static int _ocf_mngt_cache_get_list_cpy(ocf_ctx_t ocf_ctx, ocf_cache_t **list,
{ {
int result = 0; int result = 0;
uint32_t count = 0, i = 0; uint32_t count = 0, i = 0;
struct ocf_cache *iter, *this; ocf_cache_t iter;
*list = NULL; *list = NULL;
*size = 0; *size = 0;
@ -366,12 +309,9 @@ static int _ocf_mngt_cache_get_list_cpy(ocf_ctx_t ocf_ctx, ocf_cache_t **list,
} }
list_for_each_entry(iter, &ocf_ctx->caches, list) { list_for_each_entry(iter, &ocf_ctx->caches, list) {
this = _ocf_mngt_cache_try_get(iter);
if (this) { if (_ocf_mngt_cache_try_get(iter))
(*list)[i] = this; (*list)[i++] = iter;
i++;
}
} }
if (i) { if (i) {

View File

@ -588,6 +588,26 @@ err_pipeline:
cmpl(cache, NULL, priv, result); cmpl(cache, NULL, priv, result);
} }
/*
* Synchronously wait until cleaning triggered by eviction finishes.
* TODO: Replace it with asynchronous mechanism.
*/
static int _ocf_cleaning_wait_for_finish(ocf_cache_t cache, int32_t timeout_ms)
{
if (!ocf_cache_is_device_attached(cache))
return 0;
while (ocf_cache_has_pending_cleaning(cache)) {
env_msleep(20);
timeout_ms -= 20;
if (timeout_ms <= 0)
return -EBUSY;
}
return 0;
}
struct ocf_mngt_cache_remove_core_context { struct ocf_mngt_cache_remove_core_context {
ocf_mngt_cache_remove_core_end_t cmpl; ocf_mngt_cache_remove_core_end_t cmpl;
void *priv; void *priv;
@ -650,6 +670,12 @@ void ocf_mngt_cache_remove_core(ocf_core_t core,
cache = ocf_core_get_cache(core); cache = ocf_core_get_cache(core);
core_id = ocf_core_get_id(core); core_id = ocf_core_get_id(core);
/* TODO: Make this asynchronous */
if (_ocf_cleaning_wait_for_finish(cache, 60 * 1000)) {
cmpl(priv, -OCF_ERR_CACHE_IN_USE);
return;
}
result = ocf_pipeline_create(&pipeline, cache, result = ocf_pipeline_create(&pipeline, cache,
&ocf_mngt_cache_remove_core_pipeline_props); &ocf_mngt_cache_remove_core_pipeline_props);
if (result) { if (result) {
@ -702,10 +728,21 @@ static int _ocf_mngt_cache_detach_core(ocf_core_t core)
void ocf_mngt_cache_detach_core(ocf_core_t core, void ocf_mngt_cache_detach_core(ocf_core_t core,
ocf_mngt_cache_detach_core_end_t cmpl, void *priv) ocf_mngt_cache_detach_core_end_t cmpl, void *priv)
{ {
ocf_cache_t cache = ocf_core_get_cache(core); ocf_cache_t cache;
const char *core_name = ocf_core_get_name(core); const char *core_name;
int result; int result;
OCF_CHECK_NULL(core);
cache = ocf_core_get_cache(core);
core_name = ocf_core_get_name(core);
/* TODO: Make this asynchronous */
if (_ocf_cleaning_wait_for_finish(cache, 60 * 1000)) {
cmpl(priv, -OCF_ERR_CACHE_IN_USE);
return;
}
ocf_core_log(core, log_debug, "Detaching core\n"); ocf_core_log(core, log_debug, "Detaching core\n");
result = _ocf_mngt_cache_detach_core(core); result = _ocf_mngt_cache_detach_core(core);

View File

@ -8,6 +8,7 @@
#include "engine/cache_engine.h" #include "engine/cache_engine.h"
#include "utils/utils_cache_line.h" #include "utils/utils_cache_line.h"
#include "utils/utils_req.h" #include "utils/utils_req.h"
#include "utils/utils_part.h"
#include "ocf_priv.h" #include "ocf_priv.h"
#include "ocf_cache_priv.h" #include "ocf_cache_priv.h"
@ -68,12 +69,42 @@ void ocf_cache_wait_for_io_finish(ocf_cache_t cache)
bool ocf_cache_has_pending_requests(ocf_cache_t cache) bool ocf_cache_has_pending_requests(ocf_cache_t cache)
{ {
OCF_CHECK_NULL(cache); OCF_CHECK_NULL(cache);
return ocf_req_get_allocated(cache) > 0; return ocf_req_get_allocated(cache) > 0;
} }
/*
* This is temporary workaround allowing to check if cleaning triggered
* by eviction policy is running on the cache. This information is needed
* to remove core from cache properly.
*
* TODO: Replace this with asynchronous notification to which remove/detach
* core pipelines can subscribe.
*/
bool ocf_cache_has_pending_cleaning(ocf_cache_t cache)
{
struct ocf_user_part *curr_part;
ocf_part_id_t part_id;
bool cleaning_active = false;
OCF_CHECK_NULL(cache);
OCF_METADATA_LOCK_RD();
for_each_part(cache, curr_part, part_id) {
if (env_atomic_read(&cache->cleaning[part_id])) {
cleaning_active = true;
break;
}
}
OCF_METADATA_UNLOCK_RD();
return cleaning_active;
}
ocf_cache_mode_t ocf_cache_get_mode(ocf_cache_t cache) ocf_cache_mode_t ocf_cache_get_mode(ocf_cache_t cache)
{ {
OCF_CHECK_NULL(cache); OCF_CHECK_NULL(cache);
return cache->conf_meta->cache_mode; return cache->conf_meta->cache_mode;
} }