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 p2
->config
->flags
.eviction
= true;
70 p2
->config
->flags
.eviction
= false;
75 v1
= p1
- cache
->user_parts
;
76 v2
= p2
- cache
->user_parts
;
82 void 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
);
88 void ocf_part_move(struct ocf_request
*req
)
90 struct ocf_cache
*cache
= req
->cache
;
91 struct ocf_map_info
*entry
;
92 ocf_cache_line_t line
;
93 ocf_part_id_t id_old
, id_new
;
95 ocf_cleaning_t type
= cache
->conf_meta
->cleaning_policy_type
;
97 ENV_BUG_ON(type
>= ocf_cleaning_max
);
100 for (i
= 0; i
< req
->core_line_count
; i
++, entry
++) {
101 if (!entry
->re_part
) {
102 /* Changing partition not required */
106 if (entry
->status
!= LOOKUP_HIT
) {
111 line
= entry
->coll_idx
;
112 id_old
= ocf_metadata_get_partition_id(cache
, line
);
113 id_new
= req
->part_id
;
115 ENV_BUG_ON(id_old
>= OCF_IO_CLASS_MAX
||
116 id_new
>= OCF_IO_CLASS_MAX
);
118 if (id_old
== id_new
) {
119 /* Partition of the request and cache line is the same,
120 * no need to change partition
125 /* Remove from old eviction */
126 ocf_eviction_purge_cache_line(cache
, line
);
128 if (metadata_test_dirty(cache
, line
)) {
130 * Remove cline from cleaning - this if for ioclass
131 * oriented cleaning policy (e.g. ALRU).
132 * TODO: Consider adding update_cache_line() ops
133 * to cleaning policy to let policies handle this.
135 if (cleaning_policy_ops
[type
].purge_cache_block
)
136 cleaning_policy_ops
[type
].
137 purge_cache_block(cache
, line
);
140 /* Let's change partition */
141 ocf_metadata_remove_from_partition(cache
, id_old
, line
);
142 ocf_metadata_add_to_partition(cache
, id_new
, line
);
144 /* Add to new eviction */
145 ocf_eviction_init_cache_line(cache
, line
, id_new
);
146 ocf_eviction_set_hot_cache_line(cache
, line
);
148 /* Check if cache line is dirty. If yes then need to change
149 * cleaning policy and update partition dirty clines
152 if (metadata_test_dirty(cache
, line
)) {
153 /* Add cline back to cleaning policy */
154 if (cleaning_policy_ops
[type
].set_hot_cache_line
)
155 cleaning_policy_ops
[type
].
156 set_hot_cache_line(cache
, line
);
158 env_atomic_inc(&req
->core
->runtime_meta
->
159 part_counters
[id_new
].dirty_clines
);
160 env_atomic_dec(&req
->core
->runtime_meta
->
161 part_counters
[id_old
].dirty_clines
);
164 env_atomic_inc(&req
->core
->runtime_meta
->
165 part_counters
[id_new
].cached_clines
);
166 env_atomic_dec(&req
->core
->runtime_meta
->
167 part_counters
[id_old
].cached_clines
);
173 void ocf_part_set_valid(struct ocf_cache
*cache
, ocf_part_id_t id
,
176 struct ocf_user_part
*part
= &cache
->user_parts
[id
];
178 if (valid
^ part
->config
->flags
.valid
) {
180 part
->config
->flags
.valid
= true;
181 cache
->conf_meta
->valid_parts_no
++;
183 part
->config
->flags
.valid
= false;
184 cache
->conf_meta
->valid_parts_no
--;
185 part
->config
->priority
= OCF_IO_CLASS_PRIO_LOWEST
;
186 part
->config
->min_size
= 0;
187 part
->config
->max_size
= PARTITION_SIZE_MAX
;
188 ENV_BUG_ON(env_strncpy(part
->config
->name
, sizeof(part
->config
->name
),