diff --git a/src/utils/utils_part.c b/src/utils/utils_part.c index 3da853b..7ee28d8 100644 --- a/src/utils/utils_part.c +++ b/src/utils/utils_part.c @@ -190,3 +190,82 @@ void ocf_part_set_valid(struct ocf_cache *cache, ocf_part_id_t id, } } } + +static inline uint32_t ocf_part_evict_size(struct ocf_request *req) +{ + uint32_t needed_cache_lines, part_available, cache_lines_to_evict; + uint32_t part_occupancy, part_occupancy_debt; + struct ocf_user_part *target_part = &req->cache->user_parts[req->part_id]; + uint32_t part_occupancy_limit = + ocf_part_get_max_size(req->cache, target_part); + + needed_cache_lines = ocf_engine_repart_count(req) + + ocf_engine_unmapped_count(req); + + part_occupancy = ocf_part_get_occupancy(target_part); + + if (part_occupancy_limit >= part_occupancy) { + part_available = part_occupancy_limit - part_occupancy; + part_occupancy_debt = 0; + } else { + /* Occupancy is greater than occupancy limit. Evict missing number of + * cachelines, but no more than single eviction limit */ + part_occupancy_debt = min((uint32_t)OCF_PENDING_EVICTION_LIMIT, + part_occupancy - part_occupancy_limit); + part_available = 0; + } + + if (ocf_freelist_num_free(req->cache->freelist) < + ocf_engine_unmapped_count(req)) { + /* Number of cachelines to insert greater than number of free + * cachelines */ + if (part_available >= needed_cache_lines) { + /* Cache is full, but target's part occupancy limit is not reached + */ + ocf_req_clear_part_evict(req); + cache_lines_to_evict = needed_cache_lines; + } else { + /* Cache is full and target part reached it's occupancy limit */ + ocf_req_set_part_evict(req); + cache_lines_to_evict = needed_cache_lines - part_available; + } + + } else if (part_available < needed_cache_lines) { + /* Enough of free cache lines, but partition reached it's occupancy + * limit */ + cache_lines_to_evict = needed_cache_lines - part_available; + ocf_req_set_part_evict(req); + + } else if (part_available >= needed_cache_lines) { + /* Enough free cachelines available and they can be assigned to target + * partition */ + cache_lines_to_evict = 0; + + } + + return cache_lines_to_evict + part_occupancy_debt; +} + +uint32_t ocf_part_check_space(struct ocf_request *req, uint32_t *to_evict) +{ + uint32_t ret = OCF_PART_IS_FULL; + uint32_t _to_evict; + struct ocf_user_part *target_part = &req->cache->user_parts[req->part_id]; + + if (!ocf_part_is_enabled(target_part) && + ocf_part_get_occupancy(target_part) == 0) { + /* If partition is disabled, but has assigned cachelines, eviction has + * to be triggered */ + return OCF_PART_IS_DISABLED; + } + + _to_evict = ocf_part_evict_size(req); + + if (_to_evict == 0) + ret = OCF_PART_HAS_SPACE; + + if (to_evict) + *to_evict = _to_evict; + + return ret; +} diff --git a/src/utils/utils_part.h b/src/utils/utils_part.h index 6f951f7..f993061 100644 --- a/src/utils/utils_part.h +++ b/src/utils/utils_part.h @@ -8,6 +8,7 @@ #include "../ocf_request.h" #include "../engine/cache_engine.h" +#include "../engine/engine_common.h" #include "../metadata/metadata_partition.h" void ocf_part_init(struct ocf_cache *cache); @@ -72,7 +73,27 @@ static inline void ocf_part_sort(struct ocf_cache *cache) ocf_lst_sort(&cache->lst_part); } -static inline ocf_cache_mode_t ocf_part_get_cache_mode(struct ocf_cache *cache, +static inline bool ocf_part_is_enabled(struct ocf_user_part *part) +{ + return part->config->max_size != 0; +} + +#define OCF_PART_HAS_SPACE 0 +#define OCF_PART_IS_FULL 1 +#define OCF_PART_IS_DISABLED 2 +/** + * Check whether there is enough free cachelines to serve request. If partition + * occupancy limit is reached, `req->part_evict` is set to true. Otherwise + * flag is set to false and eviction from any partition should be triggered. + * + * @return + * OCF_PART_HAS_SPACE when cachelines alloted successfully + * OCF_PART_IS_FULL when need to evict some cachelines to serve request + * OCF_PART_IS_DISABLED when caching for particular partition is disabled + */ +uint32_t ocf_part_check_space(struct ocf_request *req, uint32_t *to_evict); + +static inline ocf_cache_mode_t ocf_part_get_cache_mode(ocf_cache_t cache, ocf_part_id_t part_id) { if (part_id < OCF_IO_CLASS_MAX)