diff --git a/inc/ocf_cleaner.h b/inc/ocf_cleaner.h
index 85c0df7..42c218b 100644
--- a/inc/ocf_cleaner.h
+++ b/inc/ocf_cleaner.h
@@ -12,15 +12,38 @@
*
*/
+/**
+ * @brief OCF Cleaner completion
+ *
+ * @note Completion function for cleaner
+ *
+ * @param[in] cleaner Cleaner instance
+ * @param[in] interval Time to sleep before next cleaner iteration
+ */
+typedef void (*ocf_cleaner_end_t)(ocf_cleaner_t cleaner, uint32_t interval);
+
+/**
+ * @brief Set cleaner completion function
+ *
+ * @param[in] cleaner Cleaner instance
+ * @param[in] fn Completion function
+ */
+void ocf_cleaner_set_cmpl(ocf_cleaner_t cleaner, ocf_cleaner_end_t fn);
+
+/**
+ * @brief Set cleaner queue
+ *
+ * @param[in] cleaner Cleaner instance
+ * @param[in] io_queue Queue number
+ */
+void ocf_cleaner_set_io_queue(ocf_cleaner_t cleaner, uint32_t io_queue);
+
/**
* @brief Run cleaner
*
* @param[in] c Cleaner instance to run
- * @param[in] io_queue I/O queue to which cleaner requests should be submitted
- *
- * @retval Hint when to run cleaner next time. Value expressed in miliseconds.
*/
-uint32_t ocf_cleaner_run(ocf_cleaner_t c, uint32_t io_queue);
+void ocf_cleaner_run(ocf_cleaner_t c);
/**
* @brief Set cleaner private data
diff --git a/src/cleaning/acp.c b/src/cleaning/acp.c
index 7a44cb3..2f3f528 100644
--- a/src/cleaning/acp.c
+++ b/src/cleaning/acp.c
@@ -123,6 +123,12 @@ struct acp_context {
perform_cleaning */
struct acp_state state;
+ /* cache handle */
+ ocf_cache_t cache;
+
+ /* cleaner completion callback */
+ ocf_cleaner_end_t cmpl;
+
#if 1 == OCF_ACP_DEBUG
/* debug only */
uint64_t checksum;
@@ -146,7 +152,7 @@ struct acp_core_line_info
static struct acp_context *_acp_get_ctx_from_cache(struct ocf_cache *cache)
{
- return cache->cleaning_policy_context;
+ return cache->cleaner.cleaning_policy_context;
}
static struct acp_cleaning_policy_meta* _acp_meta_get(
@@ -227,8 +233,8 @@ void cleaning_policy_acp_deinitialize(struct ocf_cache *cache)
{
_acp_remove_cores(cache);
- env_vfree(cache->cleaning_policy_context);
- cache->cleaning_policy_context = NULL;
+ env_vfree(cache->cleaner.cleaning_policy_context);
+ cache->cleaner.cleaning_policy_context = NULL;
}
static void _acp_rebuild(struct ocf_cache *cache)
@@ -282,14 +288,15 @@ int cleaning_policy_acp_initialize(struct ocf_cache *cache,
1U << (sizeof(acp->chunk_info[0][0].num_dirty) * 8));
#endif
- ENV_BUG_ON(cache->cleaning_policy_context);
+ ENV_BUG_ON(cache->cleaner.cleaning_policy_context);
- cache->cleaning_policy_context = env_vzalloc(sizeof(struct acp_context));
- if (!cache->cleaning_policy_context) {
+ acp = env_vzalloc(sizeof(*acp));
+ if (!acp) {
ocf_cache_log(cache, log_err, "acp context allocation error\n");
return -OCF_ERR_NO_MEM;
}
- acp = cache->cleaning_policy_context;
+ cache->cleaner.cleaning_policy_context = acp;
+ acp->cache = cache;
env_rwsem_init(&acp->chunks_lock);
@@ -412,40 +419,6 @@ static void _acp_handle_flush_error(struct ocf_cache *cache,
}
}
-/* called after flush request completed */
-static void _acp_flush_end(
- struct ocf_cache *cache,
- struct acp_context *acp)
-{
- struct acp_flush_context *flush = &acp->flush;
- int i;
-
- for (i = 0; i < flush->size; i++) {
- ocf_cache_line_unlock_rd(cache, flush->data[i].cache_line);
- ACP_DEBUG_END(acp, flush->data[i].cache_line);
- }
-
- if (flush->error)
- _acp_handle_flush_error(cache, acp);
-}
-
-/* flush data */
-static void _acp_flush(struct ocf_cache *cache, struct acp_context *acp,
- uint32_t io_queue, struct acp_flush_context *flush)
-{
- struct ocf_cleaner_attribs attribs = {
- .cache_line_lock = false,
- .metadata_locked = false,
- .do_sort = false,
- .io_queue = io_queue,
- };
-
- flush->error = ocf_cleaner_do_flush_data(cache, flush->data,
- flush->size, &attribs);
-
- _acp_flush_end(cache, acp);
-}
-
static inline bool _acp_can_clean_chunk(struct ocf_cache *cache,
struct acp_chunk_info *chunk)
{
@@ -456,12 +429,11 @@ static inline bool _acp_can_clean_chunk(struct ocf_cache *cache,
!chunk->next_cleaning_timestamp));
}
-static struct acp_chunk_info *_acp_get_cleaning_candidate(
- struct ocf_cache *cache)
+static struct acp_chunk_info *_acp_get_cleaning_candidate(ocf_cache_t cache)
{
int i;
struct acp_chunk_info *cur;
- struct acp_context *acp = cache->cleaning_policy_context;
+ struct acp_context *acp = cache->cleaner.cleaning_policy_context;
ACP_LOCK_CHUNKS_RD();
@@ -480,72 +452,107 @@ static struct acp_chunk_info *_acp_get_cleaning_candidate(
return NULL;
}
-#define CHUNK_FINISHED -1
+/* called after flush request completed */
+static void _acp_flush_end(void *priv, int error)
+{
+ struct acp_cleaning_policy_config *config;
+ struct acp_context *acp = priv;
+ struct acp_flush_context *flush = &acp->flush;
+ ocf_cache_t cache = acp->cache;
+ int i;
-/* clean at most 'flush_max_buffers' cache lines from given chunk, starting
- * at given cache line */
-static int _acp_clean(struct ocf_cache *cache, uint32_t io_queue,
- struct acp_chunk_info *chunk, unsigned start,
+ config = (void *)&cache->conf_meta->cleaning[ocf_cleaning_acp].data;
+
+ for (i = 0; i < flush->size; i++) {
+ ocf_cache_line_unlock_rd(cache, flush->data[i].cache_line);
+ ACP_DEBUG_END(acp, flush->data[i].cache_line);
+ }
+
+ if (error) {
+ flush->error = error;
+ _acp_handle_flush_error(cache, acp);
+ }
+
+ ACP_DEBUG_CHECK(acp);
+
+ acp->cmpl(&cache->cleaner, config->thread_wakeup_time);
+}
+
+/* flush data */
+static void _acp_flush(struct acp_context *acp)
+{
+ ocf_cache_t cache = acp->cache;
+ struct ocf_cleaner_attribs attribs = {
+ .cmpl_context = acp,
+ .cmpl_fn = _acp_flush_end,
+ .cache_line_lock = false,
+ .do_sort = false,
+ .io_queue = cache->cleaner.io_queue,
+ };
+
+ ocf_cleaner_do_flush_data_async(cache, acp->flush.data,
+ acp->flush.size, &attribs);
+}
+
+static bool _acp_prepare_flush_data(struct acp_context *acp,
uint32_t flush_max_buffers)
{
- struct acp_context *acp = _acp_get_ctx_from_cache(cache);
- size_t lines_per_chunk = ACP_CHUNK_SIZE /
- ocf_line_size(cache);
+ ocf_cache_t cache = acp->cache;
+ struct acp_state *state = &acp->state;
+ struct acp_chunk_info *chunk = state->chunk;
+ size_t lines_per_chunk = ACP_CHUNK_SIZE / ocf_line_size(cache);
uint64_t first_core_line = chunk->chunk_id * lines_per_chunk;
- unsigned i;
OCF_DEBUG_PARAM(cache, "lines per chunk %llu chunk %llu "
- "first_core_line %llu\n",
- (uint64_t)lines_per_chunk,
- chunk->chunk_id,
- first_core_line);
-
- ACP_DEBUG_INIT(acp);
+ "first_core_line %llu\n", (uint64_t)lines_per_chunk,
+ chunk->chunk_id, first_core_line);
acp->flush.size = 0;
acp->flush.chunk = chunk;
- for (i = start; i < lines_per_chunk && acp->flush.size < flush_max_buffers ; i++) {
- uint64_t core_line = first_core_line + i;
+ for (; state->iter < lines_per_chunk &&
+ acp->flush.size < flush_max_buffers; state->iter++) {
+ uint64_t core_line = first_core_line + state->iter;
ocf_cache_line_t cache_line;
cache_line = _acp_trylock_dirty(cache, chunk->core_id, core_line);
if (cache_line == cache->device->collision_table_entries)
continue;
- acp->flush.data[acp->flush.size].core_id = chunk->core_id;
- acp->flush.data[acp->flush.size].core_line = core_line;
+ ACP_DEBUG_BEGIN(acp, cache_line);
+
+ acp->flush.data[acp->flush.size].core_id = chunk->core_id;
+ acp->flush.data[acp->flush.size].core_line = core_line;
acp->flush.data[acp->flush.size].cache_line = cache_line;
acp->flush.size++;
- ACP_DEBUG_BEGIN(acp, cache_line);
}
- if (acp->flush.size > 0) {
- _acp_flush(cache, acp, io_queue, &acp->flush);
+ if (state->iter == lines_per_chunk) {
+ /* reached end of chunk - reset state */
+ state->in_progress = false;
}
- ACP_DEBUG_CHECK(acp);
-
- return (i == lines_per_chunk) ? CHUNK_FINISHED : i;
+ return (acp->flush.size > 0);
}
-#define NOTHING_TO_CLEAN 0
-#define MORE_TO_CLEAN 1
-
/* Clean at most 'flush_max_buffers' cache lines from current or newly
* selected chunk */
-static int _acp_clean_iteration(struct ocf_cache *cache, uint32_t io_queue,
- uint32_t flush_max_buffers)
+void cleaning_policy_acp_perform_cleaning(struct ocf_cache *cache,
+ ocf_cleaner_end_t cmpl)
{
+ struct acp_cleaning_policy_config *config;
struct acp_context *acp = _acp_get_ctx_from_cache(cache);
struct acp_state *state = &acp->state;
+ acp->cmpl = cmpl;
+
if (!state->in_progress) {
/* get next chunk to clean */
state->chunk = _acp_get_cleaning_candidate(cache);
if (!state->chunk) {
/* nothing co clean */
- return NOTHING_TO_CLEAN;
+ cmpl(&cache->cleaner, ACP_BACKOFF_TIME_MS);
+ return;
}
/* new cleaning cycle - reset state */
@@ -553,34 +560,14 @@ static int _acp_clean_iteration(struct ocf_cache *cache, uint32_t io_queue,
state->in_progress = true;
}
- state->iter = _acp_clean(cache, io_queue, state->chunk, state->iter,
- flush_max_buffers);
-
- if (state->iter == CHUNK_FINISHED) {
- /* reached end of chunk - reset state */
- state->in_progress = false;
- }
-
-
- return MORE_TO_CLEAN;
-}
-
-int cleaning_policy_acp_perform_cleaning(struct ocf_cache *cache,
- uint32_t io_queue)
-{
- struct acp_cleaning_policy_config *config;
- int ret;
+ ACP_DEBUG_INIT(acp);
config = (void *)&cache->conf_meta->cleaning[ocf_cleaning_acp].data;
- if (NOTHING_TO_CLEAN == _acp_clean_iteration(cache, io_queue,
- config->flush_max_buffers)) {
- ret = ACP_BACKOFF_TIME_MS;
- } else {
- ret = config->thread_wakeup_time;
- }
-
- return ret;
+ if (_acp_prepare_flush_data(acp, config->flush_max_buffers))
+ _acp_flush(acp);
+ else
+ _acp_flush_end(acp, 0);
}
static void _acp_update_bucket(struct acp_context *acp,
diff --git a/src/cleaning/acp.h b/src/cleaning/acp.h
index f2b6c9d..1693b93 100644
--- a/src/cleaning/acp.h
+++ b/src/cleaning/acp.h
@@ -8,32 +8,30 @@
#include "cleaning.h"
-void cleaning_policy_acp_setup(struct ocf_cache *cache);
+void cleaning_policy_acp_setup(ocf_cache_t cache);
-int cleaning_policy_acp_initialize(struct ocf_cache *cache,
- int init_metadata);
+int cleaning_policy_acp_initialize(ocf_cache_t cache, int init_metadata);
-void cleaning_policy_acp_deinitialize(struct ocf_cache *cache);
+void cleaning_policy_acp_deinitialize(ocf_cache_t cache);
-int cleaning_policy_acp_perform_cleaning(struct ocf_cache *cache,
- uint32_t io_queue);
+void cleaning_policy_acp_perform_cleaning(ocf_cache_t cache,
+ ocf_cleaner_end_t cmpl);
-void cleaning_policy_acp_init_cache_block(struct ocf_cache *cache,
+void cleaning_policy_acp_init_cache_block(ocf_cache_t cache,
uint32_t cache_line);
-void cleaning_policy_acp_set_hot_cache_line(struct ocf_cache *cache,
+void cleaning_policy_acp_set_hot_cache_line(ocf_cache_t cache,
uint32_t cache_line);
-void cleaning_policy_acp_purge_block(struct ocf_cache *cache,
- uint32_t cache_line);
+void cleaning_policy_acp_purge_block(ocf_cache_t cache, uint32_t cache_line);
-int cleaning_policy_acp_purge_range(struct ocf_cache *cache,
+int cleaning_policy_acp_purge_range(ocf_cache_t cache,
int core_id, uint64_t start_byte, uint64_t end_byte);
-int cleaning_policy_acp_set_cleaning_param(struct ocf_cache *cache,
+int cleaning_policy_acp_set_cleaning_param(ocf_cache_t cache,
uint32_t param_id, uint32_t param_value);
-int cleaning_policy_acp_get_cleaning_param(struct ocf_cache *cache,
+int cleaning_policy_acp_get_cleaning_param(ocf_cache_t cache,
uint32_t param_id, uint32_t *param_value);
int cleaning_policy_acp_add_core(ocf_cache_t cache, ocf_core_id_t core_id);
diff --git a/src/cleaning/alru.c b/src/cleaning/alru.c
index 45a36ef..6d0373e 100644
--- a/src/cleaning/alru.c
+++ b/src/cleaning/alru.c
@@ -49,6 +49,17 @@ struct flush_merge_struct {
uint64_t core_sector;
};
+struct alru_flush_ctx {
+ struct ocf_cleaner_attribs attribs;
+ struct ocf_user_part *parts[OCF_IO_CLASS_MAX];
+ int part_id;
+ uint32_t clines_no;
+ ocf_cache_t cache;
+ ocf_cleaner_end_t cmpl;
+ struct flush_data *flush_data;
+ size_t flush_data_limit;
+};
+
/* -- Start of ALRU functions -- */
@@ -412,7 +423,6 @@ static void _alru_rebuild(struct ocf_cache *cache)
static int cleaning_policy_alru_initialize_part(struct ocf_cache *cache,
struct ocf_user_part *part, int init_metadata)
{
-
if (init_metadata) {
/* ALRU initialization */
env_atomic_set(&part->runtime->cleaning.policy.alru.size, 0);
@@ -443,6 +453,15 @@ int cleaning_policy_alru_initialize(struct ocf_cache *cache, int init_metadata)
{
struct ocf_user_part *part;
ocf_part_id_t part_id;
+ struct alru_flush_ctx *fctx;
+
+ fctx = env_vzalloc(sizeof(*fctx));
+ if (!fctx) {
+ ocf_cache_log(cache, log_err, "alru ctx allocation error\n");
+ return -OCF_ERR_NO_MEM;
+ }
+
+ cache->cleaner.cleaning_policy_context = fctx;
for_each_part(cache, part, part_id) {
cleaning_policy_alru_initialize_part(cache,
@@ -455,6 +474,12 @@ int cleaning_policy_alru_initialize(struct ocf_cache *cache, int init_metadata)
return 0;
}
+void cleaning_policy_alru_deinitialize(struct ocf_cache *cache)
+{
+ env_vfree(cache->cleaner.cleaning_policy_context);
+ cache->cleaner.cleaning_policy_context = NULL;
+}
+
int cleaning_policy_alru_set_cleaning_param(ocf_cache_t cache,
uint32_t param_id, uint32_t param_value)
{
@@ -590,7 +615,7 @@ static void get_parts_sorted(struct ocf_user_part **parts,
cmp_ocf_user_parts, swp_ocf_user_part);
}
-static int clean_later(ocf_cache_t cache, uint32_t *delta)
+static bool clean_later(ocf_cache_t cache, uint32_t *delta)
{
struct alru_cleaning_policy_config *config;
@@ -604,6 +629,33 @@ static int clean_later(ocf_cache_t cache, uint32_t *delta)
return false;
}
+static bool is_cleanup_possible(ocf_cache_t cache)
+{
+ struct alru_cleaning_policy_config *config;
+ uint32_t delta;
+
+ config = (void *)&cache->conf_meta->cleaning[ocf_cleaning_alru].data;
+
+ if (check_for_io_activity(cache, config)) {
+ OCF_DEBUG_PARAM(cache, "IO activity detected");
+ return false;
+ }
+
+ if (clean_later(cache, &delta)) {
+ OCF_DEBUG_PARAM(cache,
+ "Cleaning policy configured to clean later "
+ "delta=%u wake_up=%u", delta,
+ config->thread_wakeup_time);
+ return false;
+ }
+
+ //Cleaning policy configured to not clean anything
+ if (config->flush_max_buffers == 0)
+ return false;
+
+ return true;
+}
+
static void get_block_to_flush(struct flush_data* dst,
ocf_cache_line_t cache_line, struct ocf_cache* cache)
{
@@ -618,7 +670,7 @@ static void get_block_to_flush(struct flush_data* dst,
dst->core_line = core_line;
}
-static int more_blocks_to_flush(struct ocf_cache *cache,
+static bool more_blocks_to_flush(struct ocf_cache *cache,
ocf_cache_line_t cache_line, uint32_t last_access)
{
struct cleaning_policy_meta policy;
@@ -634,7 +686,7 @@ static int more_blocks_to_flush(struct ocf_cache *cache,
return true;
}
-static int block_is_busy(struct ocf_cache *cache,
+static bool block_is_busy(struct ocf_cache *cache,
ocf_cache_line_t cache_line)
{
ocf_core_id_t core_id;
@@ -687,116 +739,99 @@ static int get_data_to_flush(struct flush_data *dst, uint32_t clines_no,
return to_flush;
}
-static int perform_flushing(int clines_no, struct ocf_cache *cache, uint32_t io_queue,
- struct flush_data *flush_data, struct ocf_user_part *part)
+static bool alru_do_clean(ocf_cache_t cache, struct alru_flush_ctx *fctx)
{
- int to_clean = get_data_to_flush(flush_data, clines_no, cache, part);
+ struct ocf_user_part *part = fctx->parts[fctx->part_id];
+ int to_clean;
+ if (!is_cleanup_possible(cache))
+ return false;
+
+ if (OCF_METADATA_LOCK_WR_TRY())
+ return false;
+
+ OCF_REALLOC(&fctx->flush_data, sizeof(fctx->flush_data[0]),
+ fctx->clines_no, &fctx->flush_data_limit);
+ if (!fctx->flush_data) {
+ OCF_METADATA_UNLOCK_WR();
+ ocf_cache_log(cache, log_warn, "No memory to allocate flush "
+ "data for ALRU cleaning policy");
+ return false;
+ }
+
+ to_clean = get_data_to_flush(fctx->flush_data, fctx->clines_no,
+ cache, part);
if (to_clean > 0) {
- struct ocf_cleaner_attribs attribs = {
- .cache_line_lock = true,
- .metadata_locked = true,
- .do_sort = true,
- .io_queue = io_queue
- };
-
- ocf_cleaner_do_flush_data(cache, flush_data,
- to_clean, &attribs);
+ fctx->clines_no -= to_clean;
+ ocf_cleaner_do_flush_data_async(cache, fctx->flush_data,
+ to_clean, &fctx->attribs);
} else {
/* Update timestamp only if there are no items to be cleaned */
cache->device->runtime_meta->cleaning_thread_access =
env_ticks_to_secs(env_get_tick_count());
}
- return to_clean;
-}
-
-static int is_cleanup_possible(ocf_cache_t cache)
-{
- struct alru_cleaning_policy_config *config;
- uint32_t delta;
-
- config = (void *)&cache->conf_meta->cleaning[ocf_cleaning_alru].data;
-
- if (check_for_io_activity(cache, config)) {
- OCF_DEBUG_PARAM(cache, "IO activity detected");
- return false;
- }
-
- if (clean_later(cache, &delta)) {
- OCF_DEBUG_PARAM(cache,
- "Cleaning policy configured to clean later "
- "delta=%u wake_up=%u", delta,
- config->thread_wakeup_time);
- return false;
- }
-
- //Cleaning policy configured to not clean anything
- if (config->flush_max_buffers == 0)
- return false;
-
- return true;
-}
-
-static int cleanup(struct ocf_cache *cache, uint32_t clines_no,
- struct ocf_user_part *part, uint32_t io_queue)
-{
- struct flush_data *flush_data;
- size_t flush_data_limit;
- int flushed_blocks = 0;
-
- if (!is_cleanup_possible(cache))
- return flushed_blocks;
-
- if (OCF_METADATA_LOCK_WR_TRY())
- return flushed_blocks;
-
- OCF_REALLOC_INIT(&flush_data, &flush_data_limit);
- OCF_REALLOC(&flush_data, sizeof(flush_data[0]), clines_no,
- &flush_data_limit);
-
- if (!flush_data) {
- OCF_METADATA_UNLOCK_WR();
- ocf_cache_log(cache, log_warn, "No memory to allocate flush "
- "data for ALRU cleaning policy");
- return flushed_blocks;
- }
-
- flushed_blocks = perform_flushing(clines_no, cache, io_queue,
- flush_data, part);
-
OCF_METADATA_UNLOCK_WR();
- OCF_REALLOC_DEINIT(&flush_data, &flush_data_limit);
-
- return flushed_blocks;
+ return to_clean > 0;
}
-int cleaning_alru_perform_cleaning(ocf_cache_t cache, uint32_t io_queue)
+static void alru_clean(void *priv, int error)
{
- struct ocf_user_part *parts[OCF_IO_CLASS_MAX];
- int part_id = OCF_IO_CLASS_MAX - 1;
struct alru_cleaning_policy_config *config;
- uint32_t clines_no;
+ struct alru_flush_ctx *fctx = priv;
+ ocf_cache_t cache = fctx->cache;
+ int interval;
+
+ while (fctx->clines_no > 0 && --fctx->part_id >= 0) {
+ /*
+ * The alru_do_clean() function returns true when submitting
+ * flush request for the io class succeeded. In such case we
+ * return and wait until flush finishes - then this function
+ * will be called as completion callback and iteration over
+ * io classes will continue.
+ *
+ * If the processed io class contains nothing to clean, the
+ * alru_do_clean() function returns false, and then we try to
+ * clean another io class until we reach last io class or until
+ * requested number of cache lines will be flushed - then we
+ * call the completion and finish.
+ */
+ if (alru_do_clean(cache, fctx))
+ return;
+ }
+
+ OCF_REALLOC_DEINIT(&fctx->flush_data, &fctx->flush_data_limit);
config = (void *)&cache->conf_meta->cleaning[ocf_cleaning_alru].data;
- get_parts_sorted(parts, cache);
+ interval = (fctx->clines_no > 0) ?
+ config->thread_wakeup_time * 1000 : 0;
- clines_no = config->flush_max_buffers;
-
- while (part_id >= 0) {
- clines_no -= cleanup(cache, clines_no,
- parts[part_id], io_queue);
-
- if (clines_no > 0)
- part_id--;
- else
- break;
- }
-
- if (clines_no > 0)
- return config->thread_wakeup_time * 1000;
-
- return 0;
+ fctx->cmpl(&fctx->cache->cleaner, interval);
+}
+
+void cleaning_alru_perform_cleaning(ocf_cache_t cache, ocf_cleaner_end_t cmpl)
+{
+ struct alru_flush_ctx *fctx = cache->cleaner.cleaning_policy_context;
+ struct alru_cleaning_policy_config *config;
+
+ config = (void *)&cache->conf_meta->cleaning[ocf_cleaning_alru].data;
+
+ OCF_REALLOC_INIT(&fctx->flush_data, &fctx->flush_data_limit);
+
+ fctx->attribs.cmpl_context = fctx;
+ fctx->attribs.cmpl_fn = alru_clean;
+ fctx->attribs.cache_line_lock = true;
+ fctx->attribs.do_sort = true;
+ fctx->attribs.io_queue = cache->cleaner.io_queue;
+
+ fctx->clines_no = config->flush_max_buffers;
+ fctx->cache = cache;
+ fctx->cmpl = cmpl;
+
+ get_parts_sorted(fctx->parts, cache);
+ fctx->part_id = OCF_IO_CLASS_MAX;
+
+ alru_clean(fctx, 0);
}
diff --git a/src/cleaning/alru.h b/src/cleaning/alru.h
index fc48ac4..ce0eb9e 100644
--- a/src/cleaning/alru.h
+++ b/src/cleaning/alru.h
@@ -9,22 +9,22 @@
#include "cleaning.h"
#include "alru_structs.h"
-void cleaning_policy_alru_setup(struct ocf_cache *cache);
-int cleaning_policy_alru_initialize(struct ocf_cache *cache,
- int init_metadata);
-void cleaning_policy_alru_init_cache_block(struct ocf_cache *cache,
+void cleaning_policy_alru_setup(ocf_cache_t cache);
+int cleaning_policy_alru_initialize(ocf_cache_t cache, int init_metadata);
+void cleaning_policy_alru_deinitialize(ocf_cache_t cache);
+void cleaning_policy_alru_init_cache_block(ocf_cache_t cache,
uint32_t cache_line);
-void cleaning_policy_alru_purge_cache_block(struct ocf_cache *cache,
+void cleaning_policy_alru_purge_cache_block(ocf_cache_t cache,
uint32_t cache_line);
-int cleaning_policy_alru_purge_range(struct ocf_cache *cache, int core_id,
+int cleaning_policy_alru_purge_range(ocf_cache_t cache, int core_id,
uint64_t start_byte, uint64_t end_byte);
-void cleaning_policy_alru_set_hot_cache_line(struct ocf_cache *cache,
+void cleaning_policy_alru_set_hot_cache_line(ocf_cache_t cache,
uint32_t cache_line);
-int cleaning_policy_alru_set_cleaning_param(struct ocf_cache *cache,
+int cleaning_policy_alru_set_cleaning_param(ocf_cache_t cache,
uint32_t param_id, uint32_t param_value);
-int cleaning_policy_alru_get_cleaning_param(struct ocf_cache *cache,
+int cleaning_policy_alru_get_cleaning_param(ocf_cache_t cache,
uint32_t param_id, uint32_t *param_value);
-int cleaning_alru_perform_cleaning(struct ocf_cache *cache, uint32_t io_queue);
+void cleaning_alru_perform_cleaning(ocf_cache_t cache, ocf_cleaner_end_t cmpl);
#endif
diff --git a/src/cleaning/cleaning.c b/src/cleaning/cleaning.c
index 559fcd6..3997e71 100644
--- a/src/cleaning/cleaning.c
+++ b/src/cleaning/cleaning.c
@@ -25,6 +25,7 @@ struct cleaning_policy_ops cleaning_policy_ops[ocf_cleaning_max] = {
.purge_range = cleaning_policy_alru_purge_range,
.set_hot_cache_line = cleaning_policy_alru_set_hot_cache_line,
.initialize = cleaning_policy_alru_initialize,
+ .deinitialize = cleaning_policy_alru_deinitialize,
.set_cleaning_param = cleaning_policy_alru_set_cleaning_param,
.get_cleaning_param = cleaning_policy_alru_get_cleaning_param,
.perform_cleaning = cleaning_alru_perform_cleaning,
@@ -47,16 +48,26 @@ struct cleaning_policy_ops cleaning_policy_ops[ocf_cleaning_max] = {
},
};
-int ocf_start_cleaner(struct ocf_cache *cache)
+int ocf_start_cleaner(ocf_cache_t cache)
{
return ctx_cleaner_init(cache->owner, &cache->cleaner);
}
-void ocf_stop_cleaner(struct ocf_cache *cache)
+void ocf_stop_cleaner(ocf_cache_t cache)
{
ctx_cleaner_stop(cache->owner, &cache->cleaner);
}
+void ocf_cleaner_set_cmpl(ocf_cleaner_t cleaner, ocf_cleaner_end_t fn)
+{
+ cleaner->end = fn;
+}
+
+void ocf_cleaner_set_io_queue(ocf_cleaner_t cleaner, uint32_t io_queue)
+{
+ cleaner->io_queue = io_queue;
+}
+
void ocf_cleaner_set_priv(ocf_cleaner_t c, void *priv)
{
OCF_CHECK_NULL(c);
@@ -75,7 +86,7 @@ ocf_cache_t ocf_cleaner_get_cache(ocf_cleaner_t c)
return container_of(c, struct ocf_cache, cleaner);
}
-static int _ocf_cleaner_run_check_dirty_inactive(struct ocf_cache *cache)
+static int _ocf_cleaner_run_check_dirty_inactive(ocf_cache_t cache)
{
int i;
@@ -95,29 +106,37 @@ static int _ocf_cleaner_run_check_dirty_inactive(struct ocf_cache *cache)
return 1;
}
-uint32_t ocf_cleaner_run(ocf_cleaner_t c, uint32_t io_queue)
+static void ocf_cleaner_run_complete(ocf_cleaner_t cleaner, uint32_t interval)
{
- struct ocf_cache *cache;
- ocf_cleaning_t clean_type;
- int sleep = SLEEP_TIME_MS;
+ ocf_cache_t cache = ocf_cleaner_get_cache(cleaner);
- cache = ocf_cleaner_get_cache(c);
+ env_rwsem_up_write(&cache->lock);
+ cleaner->end(cleaner, interval);
+}
+
+void ocf_cleaner_run(ocf_cleaner_t cleaner)
+{
+ ocf_cache_t cache = ocf_cleaner_get_cache(cleaner);
+ ocf_cleaning_t clean_type;
/* Do not involve cleaning when cache is not running
* (error, etc.).
*/
if (!env_bit_test(ocf_cache_state_running, &cache->cache_state) ||
ocf_mngt_is_cache_locked(cache)) {
- return SLEEP_TIME_MS;
+ cleaner->end(cleaner, SLEEP_TIME_MS);
+ return;
}
/* Sleep in case there is management operation in progress. */
- if (env_rwsem_down_write_trylock(&cache->lock) == 0)
- return SLEEP_TIME_MS;
+ if (env_rwsem_down_write_trylock(&cache->lock) == 0) {
+ cleaner->end(cleaner, SLEEP_TIME_MS);
+ return;
+ }
if (_ocf_cleaner_run_check_dirty_inactive(cache)) {
- env_rwsem_up_write(&cache->lock);
- return SLEEP_TIME_MS;
+ cleaner->end(cleaner, SLEEP_TIME_MS);
+ return;
}
clean_type = cache->conf_meta->cleaning_policy_type;
@@ -126,12 +145,7 @@ uint32_t ocf_cleaner_run(ocf_cleaner_t c, uint32_t io_queue)
/* Call cleaning. */
if (cleaning_policy_ops[clean_type].perform_cleaning) {
- sleep = cleaning_policy_ops[clean_type].
- perform_cleaning(cache, io_queue);
+ cleaning_policy_ops[clean_type].perform_cleaning(cache,
+ ocf_cleaner_run_complete);
}
-
- env_rwsem_up_write(&cache->lock);
-
- return sleep;
}
-
diff --git a/src/cleaning/cleaning.h b/src/cleaning/cleaning.h
index dc2039b..d625e26 100644
--- a/src/cleaning/cleaning.h
+++ b/src/cleaning/cleaning.h
@@ -9,6 +9,7 @@
#include "alru_structs.h"
#include "nop_structs.h"
#include "acp_structs.h"
+#include "ocf/ocf_cleaner.h"
#define CLEANING_POLICY_CONFIG_BYTES 256
#define CLEANING_POLICY_TYPE_MAX 4
@@ -17,7 +18,6 @@ struct ocf_request;
struct cleaning_policy_config {
uint8_t data[CLEANING_POLICY_CONFIG_BYTES];
- struct acp_cleaning_policy_config acp;
};
struct cleaning_policy {
@@ -37,39 +37,35 @@ struct cleaning_policy_meta {
};
struct cleaning_policy_ops {
- void (*setup)(struct ocf_cache *cache);
- int (*initialize)(struct ocf_cache *cache, int init_metadata);
- void (*deinitialize)(struct ocf_cache *cache);
- int (*add_core)(struct ocf_cache *cache, ocf_core_id_t core_id);
- void (*remove_core)(struct ocf_cache *cache, ocf_core_id_t core_id);
- void (*init_cache_block)(struct ocf_cache *cache, uint32_t cache_line);
- void (*purge_cache_block)(struct ocf_cache *cache,
- uint32_t cache_line);
- int (*purge_range)(struct ocf_cache *cache, int core_id,
+ void (*setup)(ocf_cache_t cache);
+ int (*initialize)(ocf_cache_t cache, int init_metadata);
+ void (*deinitialize)(ocf_cache_t cache);
+ int (*add_core)(ocf_cache_t cache, ocf_core_id_t core_id);
+ void (*remove_core)(ocf_cache_t cache, ocf_core_id_t core_id);
+ void (*init_cache_block)(ocf_cache_t cache, uint32_t cache_line);
+ void (*purge_cache_block)(ocf_cache_t cache, uint32_t cache_line);
+ int (*purge_range)(ocf_cache_t cache, int core_id,
uint64_t start_byte, uint64_t end_byte);
- void (*set_hot_cache_line)(struct ocf_cache *cache,
- uint32_t cache_line);
- int (*set_cleaning_param)(struct ocf_cache *cache,
- uint32_t param_id, uint32_t param_value);
- int (*get_cleaning_param)(struct ocf_cache *cache,
- uint32_t param_id, uint32_t *param_value);
- /**
- * @brief Performs cleaning.
- * @return requested time (in ms) of next call
- */
- int (*perform_cleaning)(struct ocf_cache *cache,
- uint32_t io_queue);
+ void (*set_hot_cache_line)(ocf_cache_t cache, uint32_t cache_line);
+ int (*set_cleaning_param)(ocf_cache_t cache, uint32_t param_id,
+ uint32_t param_value);
+ int (*get_cleaning_param)(ocf_cache_t cache, uint32_t param_id,
+ uint32_t *param_value);
+ void (*perform_cleaning)(ocf_cache_t cache, ocf_cleaner_end_t cmpl);
const char *name;
};
extern struct cleaning_policy_ops cleaning_policy_ops[ocf_cleaning_max];
struct ocf_cleaner {
+ void *cleaning_policy_context;
+ uint32_t io_queue;
+ ocf_cleaner_end_t end;
void *priv;
};
-int ocf_start_cleaner(struct ocf_cache *cache);
+int ocf_start_cleaner(ocf_cache_t cache);
-void ocf_stop_cleaner(struct ocf_cache *cache);
+void ocf_stop_cleaner(ocf_cache_t cache);
#endif
diff --git a/src/mngt/ocf_mngt_flush.c b/src/mngt/ocf_mngt_flush.c
index a8612f4..7ba8807 100644
--- a/src/mngt/ocf_mngt_flush.c
+++ b/src/mngt/ocf_mngt_flush.c
@@ -316,7 +316,6 @@ static int _ocf_mngt_flush_containers(ocf_cache_t cache,
for (i = 0; i < fcnum; i++) {
fctbl[i].attribs.cache_line_lock = true;
- fctbl[i].attribs.metadata_locked = true;
fctbl[i].attribs.cmpl_context = &fctbl[i];
fctbl[i].attribs.cmpl_fn = _ocf_mngt_flush_end;
fctbl[i].attribs.io_queue = 0;
diff --git a/src/ocf_cache_priv.h b/src/ocf_cache_priv.h
index 637e366..819025c 100644
--- a/src/ocf_cache_priv.h
+++ b/src/ocf_cache_priv.h
@@ -223,8 +223,6 @@ struct ocf_cache {
bool use_submit_io_fast;
- void *cleaning_policy_context;
-
struct ocf_trace trace;
void *priv;
diff --git a/src/utils/utils_cleaner.c b/src/utils/utils_cleaner.c
index f599890..eedc92e 100644
--- a/src/utils/utils_cleaner.c
+++ b/src/utils/utils_cleaner.c
@@ -31,12 +31,6 @@
#define OCF_DEBUG_PARAM(cache, format, ...)
#endif
-
-struct ocf_cleaner_sync {
- env_completion cmpl;
- int error;
-};
-
/*
* Allocate cleaning request
*/
@@ -948,17 +942,6 @@ void ocf_cleaner_fire(struct ocf_cache *cache,
ocf_req_put(master);
}
-static void ocf_cleaner_sync_end(void *private_data, int error)
-{
- struct ocf_cleaner_sync *sync = private_data;
-
- OCF_DEBUG_TRACE(req->cache);
- if (error)
- sync->error = error;
-
- env_completion_complete(&sync->cmpl);
-}
-
static int _ocf_cleaner_do_flush_data_getter(struct ocf_cache *cache,
void *context, uint32_t item, ocf_cache_line_t *line)
{
@@ -972,34 +955,6 @@ static int _ocf_cleaner_do_flush_data_getter(struct ocf_cache *cache,
}
}
-int ocf_cleaner_do_flush_data(struct ocf_cache *cache,
- struct flush_data *flush, uint32_t count,
- struct ocf_cleaner_attribs *attribs)
-{
- struct ocf_cleaner_sync sync;
-
- env_completion_init(&sync.cmpl);
- sync.error = 0;
- attribs->cmpl_context = &sync;
- attribs->cmpl_fn = ocf_cleaner_sync_end;
- attribs->getter = _ocf_cleaner_do_flush_data_getter;
- attribs->getter_context = flush;
- attribs->count = count;
-
- ocf_cleaner_fire(cache, attribs);
-
- if (attribs->metadata_locked)
- OCF_METADATA_UNLOCK_WR();
-
- env_completion_wait(&sync.cmpl);
-
- if (attribs->metadata_locked)
- OCF_METADATA_LOCK_WR();
-
- attribs->cmpl_context = NULL;
- return sync.error;
-}
-
int ocf_cleaner_do_flush_data_async(struct ocf_cache *cache,
struct flush_data *flush, uint32_t count,
struct ocf_cleaner_attribs *attribs)
diff --git a/src/utils/utils_cleaner.h b/src/utils/utils_cleaner.h
index 78d9636..8e09fe5 100644
--- a/src/utils/utils_cleaner.h
+++ b/src/utils/utils_cleaner.h
@@ -27,8 +27,6 @@ typedef int (*ocf_cleaner_get_item)(struct ocf_cache *cache,
struct ocf_cleaner_attribs {
uint8_t cache_line_lock : 1; /*!< Clean under cache line lock */
- uint8_t metadata_locked : 1; /*< true if caller holds metadata lock */
-
uint8_t do_sort : 1; /*!< Sort cache lines which will be cleaned */
uint32_t count; /*!< max number of cache lines to be cleaned */
@@ -87,20 +85,6 @@ struct flush_container {
void ocf_cleaner_fire(struct ocf_cache *cache,
const struct ocf_cleaner_attribs *attribs);
-/**
- * @brief Perform cleaning procedure for specified flush data synchronously.
- * Only dirty cache lines will be cleaned.
- *
- * @param cache - Cache instance
- * @param flush - flush data to be cleaned
- * @param count - Count of cache lines to be cleaned
- * @param attribs - Cleaning attributes
- * @return - Cleaning result. 0 - no errors, non zero errors occurred
- */
-int ocf_cleaner_do_flush_data(struct ocf_cache *cache,
- struct flush_data *flush, uint32_t count,
- struct ocf_cleaner_attribs *attribs);
-
/**
* @brief Perform cleaning procedure for specified flush data. Only dirty
* cache lines will be cleaned.
diff --git a/tests/unit/tests/cleaning/cleaning.c/ocf_cleaner_run_test.c b/tests/unit/tests/cleaning/cleaning.c/ocf_cleaner_run_test.c
index 9125ddc..eaf32a9 100644
--- a/tests/unit/tests/cleaning/cleaning.c/ocf_cleaner_run_test.c
+++ b/tests/unit/tests/cleaning/cleaning.c/ocf_cleaner_run_test.c
@@ -13,6 +13,9 @@
//src/cleaning/cleaning.c
//ocf_cleaner_run
+//
+//ocf_cleaner_set_cmpl
+//
#include
@@ -133,6 +136,11 @@ int __wrap_cleaning_policy_alru_initialize(struct ocf_cache *cache, int partitio
}
+void __wrap_cleaning_policy_alru_deinitialize(ocf_cache_t cache)
+{
+
+}
+
int __wrap_cleaning_policy_alru_flush_block(struct ocf_cache *cache,
uint32_t io_queue, uint32_t count, uint32_t *cache_lines,
int partition_id, int core_id, uint8_t do_lock)
@@ -152,7 +160,7 @@ void __wrap_cleaning_policy_alru_get_cleaning_parameters(ocf_cache_t cache,
}
-int __wrap_cleaning_alru_perform_cleaning(struct ocf_cache *cache, uint32_t io_queue)
+int __wrap_cleaning_alru_perform_cleaning(struct ocf_cache *cache, ocf_cleaner_end_t cmpl)
{
function_called();
return mock();
@@ -178,6 +186,11 @@ int __wrap__ocf_cleaner_run_check_dirty_inactive(struct ocf_cache *cache)
return mock();
}
+void __wrap_ocf_cleaner_run_complete(ocf_cleaner_t cleaner, uint32_t interval)
+{
+ function_called();
+}
+
int __wrap_env_bit_test(int nr, const void *addr)
{
function_called();
@@ -195,6 +208,10 @@ void __wrap_env_rwsem_up_write(env_rwsem *s)
function_called();
}
+static void cleaner_complete(ocf_cleaner_t cleaner, uint32_t interval)
+{
+ function_called();
+}
/*
* Tests of functions. Every test name must be written to tests array in main().
@@ -233,10 +250,9 @@ static void ocf_cleaner_run_test01(void **state)
expect_function_call(__wrap_cleaning_alru_perform_cleaning);
will_return(__wrap_cleaning_alru_perform_cleaning, 0);
- expect_function_call(__wrap_env_rwsem_up_write);
+ ocf_cleaner_set_cmpl(&cache.cleaner, cleaner_complete);
- result = ocf_cleaner_run(&cache.cleaner, io_queue);
- assert_int_equal(result, 0);
+ ocf_cleaner_run(&cache.cleaner);
/* Release allocated memory if allocated with test_* functions */