|
19 | 19 | #include "ocf_cache_priv.h" |
20 | 20 | #include "ocf_request.h" |
21 | 21 | #include "engine/engine_common.h" |
| 22 | +#include "utils/utils_user_part.h" |
22 | 23 |
|
23 | 24 | #define OCF_LRU_MAX_LRU_ELEMENT_IDX 256 |
24 | 25 |
|
@@ -792,9 +793,14 @@ uint32_t ocf_lru_req_clines(struct ocf_request *req, |
792 | 793 | struct ocf_part *dst_part; |
793 | 794 | ocf_part_id_t actual_src_part_id; |
794 | 795 |
|
| 796 | + uint32_t dst_max_size; |
| 797 | + |
795 | 798 | if (cline_no == 0) |
796 | 799 | return 0; |
797 | 800 |
|
| 801 | + dst_max_size = ocf_user_part_get_max_size(cache, |
| 802 | + &cache->user_parts[req->part_id]); |
| 803 | + |
798 | 804 | if (unlikely(ocf_engine_unmapped_count(req) < cline_no)) { |
799 | 805 | ocf_cache_log(req->cache, log_err, "Not enough space in" |
800 | 806 | "request: unmapped %u, requested %u", |
@@ -868,6 +874,18 @@ uint32_t ocf_lru_req_clines(struct ocf_request *req, |
868 | 874 |
|
869 | 875 | ++req_idx; |
870 | 876 | ++i; |
| 877 | + |
| 878 | + /* When allocating from freelist or another partition (not |
| 879 | + * self-eviction), curr_size was incremented. Stop if the |
| 880 | + * destination partition has reached its occupancy limit. |
| 881 | + * This bounds the TOCTOU race in ocf_user_part_has_space() |
| 882 | + * to at most OCF_NUM_LRU_LISTS cache lines of overshoot. */ |
| 883 | + if (actual_src_part_id != dst_part->id && |
| 884 | + (uint32_t)env_atomic_read( |
| 885 | + &dst_part->runtime->curr_size) >= |
| 886 | + dst_max_size) |
| 887 | + break; |
| 888 | + |
871 | 889 | /* Number of cachelines to evict have to match space in the |
872 | 890 | * request */ |
873 | 891 | ENV_BUG_ON(req_idx == req->core_line_count && i != cline_no); |
|
0 commit comments