]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/ocf/src/utils/utils_part.c
import 15.2.0 Octopus source
[ceph.git] / ceph / src / spdk / ocf / src / utils / utils_part.c
1 /*
2 * Copyright(c) 2012-2018 Intel Corporation
3 * SPDX-License-Identifier: BSD-3-Clause-Clear
4 */
5
6 #include "ocf/ocf.h"
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"
13
14 static struct ocf_lst_entry *ocf_part_lst_getter_valid(
15 struct ocf_cache *cache, ocf_cache_line_t idx)
16 {
17 ENV_BUG_ON(idx > OCF_IO_CLASS_MAX);
18 return &cache->user_parts[idx].lst_valid;
19 }
20
21
22 static int ocf_part_lst_cmp_valid(struct ocf_cache *cache,
23 struct ocf_lst_entry *e1, struct ocf_lst_entry *e2)
24 {
25 struct ocf_user_part *p1 = container_of(e1, struct ocf_user_part,
26 lst_valid);
27 struct ocf_user_part *p2 = container_of(e2, struct ocf_user_part,
28 lst_valid);
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;
33
34 int v1 = p1->config->priority;
35 int v2 = p2->config->priority;
36
37 /*
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
42 */
43
44 if (p1->config->priority == OCF_IO_CLASS_PRIO_PINNED)
45 p1->config->flags.eviction = false;
46 else
47 p1->config->flags.eviction = true;
48
49 if (p2->config->priority == OCF_IO_CLASS_PRIO_PINNED)
50 p2->config->flags.eviction = false;
51 else
52 p2->config->flags.eviction = true;
53
54 if (!p1->config->flags.valid) {
55 if (p1_size) {
56 v1 = SHRT_MAX;
57 p1->config->flags.eviction = true;
58 } else {
59 v1 = SHRT_MIN;
60 p1->config->flags.eviction = false;
61 }
62 }
63
64 if (!p2->config->flags.valid) {
65 if (p2_size) {
66 v2 = SHRT_MAX;
67 p1->config->flags.eviction = true;
68 } else {
69 v2 = SHRT_MIN;
70 p2->config->flags.eviction = false;
71 }
72 }
73
74 if (v1 == v2) {
75 v1 = p1 - cache->user_parts;
76 v2 = p2 - cache->user_parts;
77 }
78
79 return v2 - v1;
80 }
81
82 int ocf_part_init(struct ocf_cache *cache)
83 {
84 ocf_lst_init(cache, &cache->lst_part, OCF_IO_CLASS_MAX,
85 ocf_part_lst_getter_valid, ocf_part_lst_cmp_valid);
86
87 return 0;
88 }
89
90 void ocf_part_move(struct ocf_request *req)
91 {
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;
96 uint32_t i;
97 ocf_cleaning_t type = cache->conf_meta->cleaning_policy_type;
98
99 ENV_BUG_ON(type >= ocf_cleaning_max);
100
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 */
105 continue;
106 }
107
108 if (entry->status != LOOKUP_HIT) {
109 /* No HIT */
110 continue;
111 }
112
113 line = entry->coll_idx;
114 id_old = ocf_metadata_get_partition_id(cache, line);
115 id_new = req->part_id;
116
117 ENV_BUG_ON(id_old >= OCF_IO_CLASS_MAX ||
118 id_new >= OCF_IO_CLASS_MAX);
119
120 if (id_old == id_new) {
121 /* Partition of the request and cache line is the same,
122 * no need to change partition
123 */
124 continue;
125 }
126
127 /* Remove from old eviction */
128 ocf_eviction_purge_cache_line(cache, line);
129
130 if (metadata_test_dirty(cache, line)) {
131 /*
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.
136 */
137 if (cleaning_policy_ops[type].purge_cache_block)
138 cleaning_policy_ops[type].
139 purge_cache_block(cache, line);
140 }
141
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);
145
146 /* Add to new eviction */
147 ocf_eviction_init_cache_line(cache, line, id_new);
148 ocf_eviction_set_hot_cache_line(cache, line);
149
150 /* Check if cache line is dirty. If yes then need to change
151 * cleaning policy and update partition dirty clines
152 * statistics.
153 */
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);
159
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);
164 }
165
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);
170
171 /* DONE */
172 }
173 }
174
175 void ocf_part_set_valid(struct ocf_cache *cache, ocf_part_id_t id,
176 bool valid)
177 {
178 struct ocf_user_part *part = &cache->user_parts[id];
179
180 if (valid ^ part->config->flags.valid) {
181 if (valid) {
182 part->config->flags.valid = true;
183 cache->conf_meta->valid_parts_no++;
184 } else {
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),
191 "Inactive", 9));
192 }
193 }
194 }