diff --git a/src/cleaning/acp.c b/src/cleaning/acp.c index 1a1d1d9..a294bd0 100644 --- a/src/cleaning/acp.c +++ b/src/cleaning/acp.c @@ -636,6 +636,8 @@ void cleaning_policy_acp_purge_block(struct ocf_cache *cache, struct acp_cleaning_policy_meta *acp_meta; struct acp_chunk_info *chunk; + ACP_LOCK_CHUNKS_WR(); + acp_meta = _acp_meta_get(cache, cache_line, &policy_meta); chunk = _acp_get_chunk(cache, cache_line); @@ -646,6 +648,8 @@ void cleaning_policy_acp_purge_block(struct ocf_cache *cache, } _acp_update_bucket(acp, chunk); + + ACP_UNLOCK_CHUNKS_WR(); } int cleaning_policy_acp_purge_range(struct ocf_cache *cache, diff --git a/src/cleaning/alru.c b/src/cleaning/alru.c index e3e08f4..3d6cb63 100644 --- a/src/cleaning/alru.c +++ b/src/cleaning/alru.c @@ -43,12 +43,6 @@ #define OCF_DEBUG_PARAM(cache, format, ...) #endif -struct flush_merge_struct { - ocf_cache_line_t cache_line; - ocf_core_id_t core_id; - uint64_t core_sector; -}; - struct alru_flush_ctx { struct ocf_cleaner_attribs attribs; bool flush_perfomed; @@ -59,6 +53,12 @@ struct alru_flush_ctx { size_t flush_data_limit; }; +struct alru_context { + struct alru_flush_ctx flush_ctx; + env_spinlock list_lock[OCF_IO_CLASS_MAX]; +}; + + /* -- Start of ALRU functions -- */ @@ -319,20 +319,29 @@ void cleaning_policy_alru_init_cache_block(struct ocf_cache *cache, void cleaning_policy_alru_purge_cache_block(struct ocf_cache *cache, uint32_t cache_line) { + struct alru_context *alru = cache->cleaner.cleaning_policy_context; ocf_part_id_t part_id = ocf_metadata_get_partition_id(cache, cache_line); + env_spinlock_lock(&alru->list_lock[part_id]); remove_alru_list(cache, part_id, cache_line); + env_spinlock_unlock(&alru->list_lock[part_id]); } static void __cleaning_policy_alru_purge_cache_block_any( struct ocf_cache *cache, uint32_t cache_line) { + struct alru_context *alru = cache->cleaner.cleaning_policy_context; + ocf_part_id_t part_id = ocf_metadata_get_partition_id(cache, cache_line); + env_spinlock_lock(&alru->list_lock[part_id]); + if (is_on_alru_list(cache, part_id, cache_line)) remove_alru_list(cache, part_id, cache_line); + + env_spinlock_unlock(&alru->list_lock[part_id]); } int cleaning_policy_alru_purge_range(struct ocf_cache *cache, int core_id, @@ -357,6 +366,7 @@ int cleaning_policy_alru_purge_range(struct ocf_cache *cache, int core_id, void cleaning_policy_alru_set_hot_cache_line(struct ocf_cache *cache, uint32_t cache_line) { + struct alru_context *alru = cache->cleaner.cleaning_policy_context; ocf_part_id_t part_id = ocf_metadata_get_partition_id(cache, cache_line); struct ocf_user_part *part = &cache->user_parts[part_id]; @@ -368,6 +378,8 @@ void cleaning_policy_alru_set_hot_cache_line(struct ocf_cache *cache, ENV_WARN_ON(!metadata_test_dirty(cache, cache_line)); ENV_WARN_ON(!metadata_test_valid_any(cache, cache_line)); + env_spinlock_lock(&alru->list_lock[part_id]); + ocf_metadata_get_cleaning_policy(cache, cache_line, &policy); next_lru_node = policy.meta.alru.lru_next; prev_lru_node = policy.meta.alru.lru_prev; @@ -381,6 +393,8 @@ void cleaning_policy_alru_set_hot_cache_line(struct ocf_cache *cache, remove_alru_list(cache, part_id, cache_line); add_alru_head(cache, part_id, cache_line); + + env_spinlock_unlock(&alru->list_lock[part_id]); } static void _alru_rebuild(struct ocf_cache *cache) @@ -452,15 +466,19 @@ int cleaning_policy_alru_initialize(ocf_cache_t cache, int init_metadata) { struct ocf_user_part *part; ocf_part_id_t part_id; - struct alru_flush_ctx *fctx; + struct alru_context *alru; + unsigned i; - fctx = env_vzalloc(sizeof(*fctx)); - if (!fctx) { - ocf_cache_log(cache, log_err, "alru ctx allocation error\n"); + alru = env_vzalloc(sizeof(*alru)); + if (!alru) { + ocf_cache_log(cache, log_err, "alru context allocation error\n"); return -OCF_ERR_NO_MEM; } - cache->cleaner.cleaning_policy_context = fctx; + for (i = 0; i < OCF_IO_CLASS_MAX; i++) + env_spinlock_init(&alru->list_lock[i]); + + cache->cleaner.cleaning_policy_context = alru; for_each_part(cache, part, part_id) { cleaning_policy_alru_initialize_part(cache, @@ -477,6 +495,12 @@ int cleaning_policy_alru_initialize(ocf_cache_t cache, int init_metadata) void cleaning_policy_alru_deinitialize(struct ocf_cache *cache) { + struct alru_context *alru = cache->cleaner.cleaning_policy_context; + unsigned i; + + for (i = 0; i < OCF_IO_CLASS_MAX; i++) + env_spinlock_destroy(&alru->list_lock[i]); + env_vfree(cache->cleaner.cleaning_policy_context); cache->cleaner.cleaning_policy_context = NULL; } @@ -587,36 +611,6 @@ static int check_for_io_activity(struct ocf_cache *cache, return 0; } -static int cmp_ocf_user_parts(const void *p1, const void *p2) { - const struct ocf_user_part *t1 = *(const struct ocf_user_part**)p1; - const struct ocf_user_part *t2 = *(const struct ocf_user_part**)p2; - - if (t1->config->priority > t2->config->priority) - return 1; - else if (t1->config->priority < t2->config->priority) - return -1; - - return 0; -} - -static void swp_ocf_user_part(void *part1, void *part2, int size) { - void *tmp = *(void **)part1; - - *(void **)part1 = *(void **) part2; - *(void **)part2 = tmp; -} - -static void get_parts_sorted(struct ocf_user_part **parts, - struct ocf_cache *cache) { - int i; - - for (i = 0; i < OCF_IO_CLASS_MAX; i++) - parts[i] = &cache->user_parts[i]; - - env_sort(parts, OCF_IO_CLASS_MAX, sizeof(struct ocf_user_part*), - cmp_ocf_user_parts, swp_ocf_user_part); -} - static bool clean_later(ocf_cache_t cache, uint32_t *delta) { struct alru_cleaning_policy_config *config; @@ -706,24 +700,24 @@ static bool block_is_busy(struct ocf_cache *cache, return false; } -static int get_data_to_flush(struct alru_flush_ctx *fctx) +static int get_data_to_flush(struct alru_context *alru) { + struct alru_flush_ctx *fctx = &alru->flush_ctx; ocf_cache_t cache = fctx->cache; struct alru_cleaning_policy_config *config; struct cleaning_policy_meta policy; ocf_cache_line_t cache_line; - struct ocf_user_part *parts[OCF_IO_CLASS_MAX]; + struct ocf_user_part *part; uint32_t last_access; int to_flush = 0; int part_id = OCF_IO_CLASS_ID_MAX; config = (void *)&cache->conf_meta->cleaning[ocf_cleaning_alru].data; - get_parts_sorted(parts, cache); + for_each_part(cache, part, part_id) { + env_spinlock_lock(&alru->list_lock[part_id]); - while (part_id >= OCF_IO_CLASS_ID_MIN) { - cache_line = - parts[part_id]->runtime->cleaning.policy.alru.lru_tail; + cache_line = part->runtime->cleaning.policy.alru.lru_tail; last_access = compute_timestamp(config); @@ -732,8 +726,10 @@ static int get_data_to_flush(struct alru_flush_ctx *fctx) policy.meta.alru.timestamp < last_access); while (more_blocks_to_flush(cache, cache_line, last_access)) { - if (to_flush >= fctx->clines_no) + if (to_flush >= fctx->clines_no) { + env_spinlock_unlock(&alru->list_lock[part_id]); goto end; + } if (!block_is_busy(cache, cache_line)) { get_block_to_flush(&fctx->flush_data[to_flush], cache_line, @@ -744,7 +740,8 @@ static int get_data_to_flush(struct alru_flush_ctx *fctx) ocf_metadata_get_cleaning_policy(cache, cache_line, &policy); cache_line = policy.meta.alru.lru_prev; } - part_id--; + + env_spinlock_unlock(&alru->list_lock[part_id]); } end: @@ -769,8 +766,9 @@ static void alru_clean_complete(void *priv, int err) fctx->cmpl(&fctx->cache->cleaner, interval); } -static void alru_clean(struct alru_flush_ctx *fctx) +static void alru_clean(struct alru_context *alru) { + struct alru_flush_ctx *fctx = &alru->flush_ctx; ocf_cache_t cache = fctx->cache; int to_clean; @@ -792,7 +790,7 @@ static void alru_clean(struct alru_flush_ctx *fctx) goto end; } - to_clean = get_data_to_flush(fctx); + to_clean = get_data_to_flush(alru); if (to_clean > 0) { fctx->flush_perfomed = true; ocf_cleaner_do_flush_data_async(cache, fctx->flush_data, to_clean, @@ -812,7 +810,8 @@ end: 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_context *alru = cache->cleaner.cleaning_policy_context; + struct alru_flush_ctx *fctx = &alru->flush_ctx; struct alru_cleaning_policy_config *config; config = (void *)&cache->conf_meta->cleaning[ocf_cleaning_alru].data; @@ -830,5 +829,5 @@ void cleaning_alru_perform_cleaning(ocf_cache_t cache, ocf_cleaner_end_t cmpl) fctx->cmpl = cmpl; fctx->flush_perfomed = false; - alru_clean(fctx); + alru_clean(alru); }