2 * Copyright(c) 2012-2018 Intel Corporation
3 * SPDX-License-Identifier: BSD-3-Clause-Clear
7 #include "../ocf_cache_priv.h"
8 #include "../ocf_request.h"
9 #include "../metadata/metadata.h"
10 #include "../engine/cache_engine.h"
11 #include "../eviction/ops.h"
12 #include "utils_part.h"
14 static struct ocf_lst_entry
*ocf_part_lst_getter_valid(
15 struct ocf_cache
*cache
, ocf_cache_line_t idx
)
17 ENV_BUG_ON(idx
> OCF_IO_CLASS_MAX
);
18 return &cache
->user_parts
[idx
].lst_valid
;
22 static int ocf_part_lst_cmp_valid(struct ocf_cache
*cache
,
23 struct ocf_lst_entry
*e1
, struct ocf_lst_entry
*e2
)
25 struct ocf_user_part
*p1
= container_of(e1
, struct ocf_user_part
,
27 struct ocf_user_part
*p2
= container_of(e2
, struct ocf_user_part
,
29 size_t p1_size
= ocf_cache_is_device_attached(cache
) ?
30 p1
->runtime
->curr_size
: 0;
31 size_t p2_size
= ocf_cache_is_device_attached(cache
) ?
32 p2
->runtime
->curr_size
: 0;
34 int v1
= p1
->config
->priority
;
35 int v2
= p2
->config
->priority
;
38 * If partition is invalid the priority depends on current size:
39 * 1. Partition is empty - move to the end of list
40 * 2. Partition is not empty - move to the beginning of the list. This
41 * partition will be evicted first
44 if (p1
->config
->priority
== OCF_IO_CLASS_PRIO_PINNED
)
45 p1
->config
->flags
.eviction
= false;
47 p1
->config
->flags
.eviction
= true;
49 if (p2
->config
->priority
== OCF_IO_CLASS_PRIO_PINNED
)
50 p2
->config
->flags
.eviction
= false;
52 p2
->config
->flags
.eviction
= true;
54 if (!p1
->config
->flags
.valid
) {
57 p1
->config
->flags
.eviction
= true;
60 p1
->config
->flags
.eviction
= false;
64 if (!p2
->config
->flags
.valid
) {
67 p1
->config
->flags
.eviction
= true;
70 p2
->config
->flags
.eviction
= false;
75 v1
= p1
- cache
->user_parts
;
76 v2
= p2
- cache
->user_parts
;
82 int ocf_part_init(struct ocf_cache
*cache
)
84 ocf_lst_init(cache
, &cache
->lst_part
, OCF_IO_CLASS_MAX
,
85 ocf_part_lst_getter_valid
, ocf_part_lst_cmp_valid
);
90 void ocf_part_move(struct ocf_request
*req
)
92 struct ocf_cache
*cache
= req
->cache
;
93 struct ocf_map_info
*entry
;
94 ocf_cache_line_t line
;
95 ocf_part_id_t id_old
, id_new
;
97 ocf_cleaning_t type
= cache
->conf_meta
->cleaning_policy_type
;
99 ENV_BUG_ON(type
>= ocf_cleaning_max
);
101 entry
= &req
->map
[0];
102 for (i
= 0; i
< req
->core_line_count
; i
++, entry
++) {
103 if (!entry
->re_part
) {
104 /* Changing partition not required */
108 if (entry
->status
!= LOOKUP_HIT
) {
113 line
= entry
->coll_idx
;
114 id_old
= ocf_metadata_get_partition_id(cache
, line
);
115 id_new
= req
->part_id
;
117 ENV_BUG_ON(id_old
>= OCF_IO_CLASS_MAX
||
118 id_new
>= OCF_IO_CLASS_MAX
);
120 if (id_old
== id_new
) {
121 /* Partition of the request and cache line is the same,
122 * no need to change partition
127 /* Remove from old eviction */
128 ocf_eviction_purge_cache_line(cache
, line
);
130 if (metadata_test_dirty(cache
, line
)) {
132 * Remove cline from cleaning - this if for ioclass
133 * oriented cleaning policy (e.g. ALRU).
134 * TODO: Consider adding update_cache_line() ops
135 * to cleaning policy to let policies handle this.
137 if (cleaning_policy_ops
[type
].purge_cache_block
)
138 cleaning_policy_ops
[type
].
139 purge_cache_block(cache
, line
);
142 /* Let's change partition */
143 ocf_metadata_remove_from_partition(cache
, id_old
, line
);
144 ocf_metadata_add_to_partition(cache
, id_new
, line
);
146 /* Add to new eviction */
147 ocf_eviction_init_cache_line(cache
, line
, id_new
);
148 ocf_eviction_set_hot_cache_line(cache
, line
);
150 /* Check if cache line is dirty. If yes then need to change
151 * cleaning policy and update partition dirty clines
154 if (metadata_test_dirty(cache
, line
)) {
155 /* Add cline back to cleaning policy */
156 if (cleaning_policy_ops
[type
].set_hot_cache_line
)
157 cleaning_policy_ops
[type
].
158 set_hot_cache_line(cache
, line
);
160 env_atomic_inc(&cache
->core_runtime_meta
[req
->core_id
].
161 part_counters
[id_new
].dirty_clines
);
162 env_atomic_dec(&cache
->core_runtime_meta
[req
->core_id
].
163 part_counters
[id_old
].dirty_clines
);
166 env_atomic_inc(&cache
->core_runtime_meta
[req
->core_id
].
167 part_counters
[id_new
].cached_clines
);
168 env_atomic_dec(&cache
->core_runtime_meta
[req
->core_id
].
169 part_counters
[id_old
].cached_clines
);
175 void ocf_part_set_valid(struct ocf_cache
*cache
, ocf_part_id_t id
,
178 struct ocf_user_part
*part
= &cache
->user_parts
[id
];
180 if (valid
^ part
->config
->flags
.valid
) {
182 part
->config
->flags
.valid
= true;
183 cache
->conf_meta
->valid_parts_no
++;
185 part
->config
->flags
.valid
= false;
186 cache
->conf_meta
->valid_parts_no
--;
187 part
->config
->priority
= OCF_IO_CLASS_PRIO_LOWEST
;
188 part
->config
->min_size
= 0;
189 part
->config
->max_size
= PARTITION_SIZE_MAX
;
190 ENV_BUG_ON(env_strncpy(part
->config
->name
, sizeof(part
->config
->name
),