]> git.proxmox.com Git - ceph.git/blame - ceph/src/spdk/ocf/src/mngt/ocf_mngt_io_class.c
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / spdk / ocf / src / mngt / ocf_mngt_io_class.c
CommitLineData
9f95a23c
TL
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_mngt_common.h"
8#include "../ocf_priv.h"
9#include "../metadata/metadata.h"
10#include "../engine/cache_engine.h"
11#include "../utils/utils_part.h"
12#include "../eviction/ops.h"
13#include "ocf_env.h"
14
15static uint64_t _ocf_mngt_count_parts_min_size(struct ocf_cache *cache)
16{
17 struct ocf_user_part *part;
18 ocf_part_id_t part_id;
19 uint64_t count = 0;
20
21 for_each_part(cache, part, part_id) {
22 if (ocf_part_is_valid(part))
23 count += part->config->min_size;
24 }
25
26 return count;
27}
28
29int ocf_mngt_add_partition_to_cache(struct ocf_cache *cache,
30 ocf_part_id_t part_id, const char *name, uint32_t min_size,
31 uint32_t max_size, uint8_t priority, bool valid)
32{
33 uint32_t size;
34
35 if (!name)
36 return -OCF_ERR_INVAL;
37
38 if (part_id >= OCF_IO_CLASS_MAX)
39 return -OCF_ERR_INVAL;
40
41 if (cache->user_parts[part_id].config->flags.valid)
42 return -OCF_ERR_INVAL;
43
44 if (max_size > PARTITION_SIZE_MAX)
45 return -OCF_ERR_INVAL;
46
47 if (env_strnlen(name, OCF_IO_CLASS_NAME_MAX) >=
48 OCF_IO_CLASS_NAME_MAX) {
49 ocf_cache_log(cache, log_info,
50 "Name of the partition is too long\n");
51 return -OCF_ERR_INVAL;
52 }
53
54 size = sizeof(cache->user_parts[part_id].config->name);
55 if (env_strncpy(cache->user_parts[part_id].config->name, size, name, size))
56 return -OCF_ERR_INVAL;
57
58 cache->user_parts[part_id].config->min_size = min_size;
59 cache->user_parts[part_id].config->max_size = max_size;
60 cache->user_parts[part_id].config->priority = priority;
61 cache->user_parts[part_id].config->cache_mode = ocf_cache_mode_max;
62
63 ocf_part_set_valid(cache, part_id, valid);
64 ocf_lst_add(&cache->lst_part, part_id);
65 ocf_part_sort(cache);
66
67 cache->user_parts[part_id].config->flags.added = 1;
68
69 return 0;
70}
71
72static int _ocf_mngt_set_partition_size(struct ocf_cache *cache,
73 ocf_part_id_t part_id, uint32_t min, uint32_t max)
74{
75 struct ocf_user_part *part = &cache->user_parts[part_id];
76
77 if (min > max)
78 return -OCF_ERR_INVAL;
79
80 if (_ocf_mngt_count_parts_min_size(cache) + min
81 >= cache->device->collision_table_entries) {
82 /* Illegal configuration in which sum of all min_sizes exceeds
83 * cache size.
84 */
85 return -OCF_ERR_INVAL;
86 }
87
88 if (max > PARTITION_SIZE_MAX)
89 max = PARTITION_SIZE_MAX;
90
91 part->config->min_size = min;
92 part->config->max_size = max;
93
94 return 0;
95}
96
97static int _ocf_mngt_io_class_configure(ocf_cache_t cache,
98 const struct ocf_mngt_io_class_config *cfg)
99{
100 int result = -1;
101 struct ocf_user_part *dest_part;
102
103 ocf_part_id_t part_id = cfg->class_id;
104 const char *name = cfg->name;
105 int16_t prio = cfg->prio;
106 ocf_cache_mode_t cache_mode = cfg->cache_mode;
107 uint32_t min = cfg->min_size;
108 uint32_t max = cfg->max_size;
109
110 OCF_CHECK_NULL(cache->device);
111
112 dest_part = &cache->user_parts[part_id];
113
114 if (!ocf_part_is_added(dest_part)) {
115 ocf_cache_log(cache, log_info, "Setting IO class, id: %u, "
116 "name: '%s' [ ERROR ]\n", part_id, dest_part->config->name);
117 return -OCF_ERR_INVAL;
118 }
119
f67539c2
TL
120 if (!name[0])
121 return -OCF_ERR_INVAL;
9f95a23c
TL
122
123 if (part_id == PARTITION_DEFAULT) {
124 /* Special behavior for default partition */
125
126 /* Try set partition size */
127 if (_ocf_mngt_set_partition_size(cache, part_id, min, max)) {
128 ocf_cache_log(cache, log_info,
129 "Setting IO class size, id: %u, name: '%s' "
130 "[ ERROR ]\n", part_id, dest_part->config->name);
131 return -OCF_ERR_INVAL;
132 }
133 ocf_part_set_prio(cache, dest_part, prio);
134 dest_part->config->cache_mode = cache_mode;
135
136 ocf_cache_log(cache, log_info,
137 "Updating unclassified IO class, id: "
138 "%u [ OK ]\n", part_id);
139
140 return 0;
141 }
142
143 /* Setting */
144 result = env_strncpy(dest_part->config->name,
145 sizeof(dest_part->config->name), name,
146 sizeof(dest_part->config->name));
147 if (result)
148 return result;
149
150 /* Try set partition size */
151 if (_ocf_mngt_set_partition_size(cache, part_id, min, max)) {
152 ocf_cache_log(cache, log_info,
153 "Setting IO class size, id: %u, name: '%s' "
154 "[ ERROR ]\n", part_id, dest_part->config->name);
155 return -OCF_ERR_INVAL;
156 }
157
158 if (ocf_part_is_valid(dest_part)) {
159 /* Updating existing */
160 ocf_cache_log(cache, log_info, "Updating existing IO "
161 "class, id: %u, name: '%s' [ OK ]\n",
162 part_id, dest_part->config->name);
163 } else {
164 /* Adding new */
165 ocf_part_set_valid(cache, part_id, true);
166
167 ocf_cache_log(cache, log_info, "Adding new IO class, "
168 "id: %u, name: '%s' [ OK ]\n", part_id,
169 dest_part->config->name);
170 }
171
172 ocf_part_set_prio(cache, dest_part, prio);
173 dest_part->config->cache_mode = cache_mode;
174
175 return result;
176}
177
f67539c2 178static void _ocf_mngt_io_class_remove(ocf_cache_t cache,
9f95a23c
TL
179 const struct ocf_mngt_io_class_config *cfg)
180{
181 struct ocf_user_part *dest_part;
182 ocf_part_id_t part_id = cfg->class_id;
9f95a23c
TL
183
184 dest_part = &cache->user_parts[part_id];
185
186 OCF_CHECK_NULL(cache->device);
187
188 if (part_id == PARTITION_DEFAULT) {
189 ocf_cache_log(cache, log_info,
190 "Cannot remove unclassified IO class, "
191 "id: %u [ ERROR ]\n", part_id);
f67539c2 192 return;
9f95a23c
TL
193 }
194
f67539c2 195 if (!ocf_part_is_valid(dest_part)) {
9f95a23c 196 /* Does not exist */
f67539c2 197 return;
9f95a23c
TL
198 }
199
f67539c2
TL
200
201 ocf_part_set_valid(cache, part_id, false);
202
203 ocf_cache_log(cache, log_info,
204 "Removing IO class, id: %u [ OK ]\n", part_id);
9f95a23c
TL
205}
206
207static int _ocf_mngt_io_class_edit(ocf_cache_t cache,
208 const struct ocf_mngt_io_class_config *cfg)
209{
f67539c2 210 int result = 0;
9f95a23c 211
f67539c2 212 if (cfg->name)
9f95a23c 213 result = _ocf_mngt_io_class_configure(cache, cfg);
f67539c2
TL
214 else
215 _ocf_mngt_io_class_remove(cache, cfg);
9f95a23c
TL
216
217 return result;
218}
219
220static int _ocf_mngt_io_class_validate_cfg(ocf_cache_t cache,
221 const struct ocf_mngt_io_class_config *cfg)
222{
223 if (cfg->class_id >= OCF_IO_CLASS_MAX)
224 return -OCF_ERR_INVAL;
225
226 /* Name set to null means particular io_class should be removed */
227 if (!cfg->name)
228 return 0;
229
9f95a23c
TL
230 if (cfg->cache_mode < ocf_cache_mode_none ||
231 cfg->cache_mode > ocf_cache_mode_max) {
232 return -OCF_ERR_INVAL;
233 }
234
235 if (!ocf_part_is_name_valid(cfg->name)) {
236 ocf_cache_log(cache, log_info,
237 "The name of the partition is not valid\n");
238 return -OCF_ERR_INVAL;
239 }
240
241 if (!ocf_part_is_prio_valid(cfg->prio)) {
242 ocf_cache_log(cache, log_info,
243 "Invalid value of the partition priority\n");
244 return -OCF_ERR_INVAL;
245 }
246
247 return 0;
248}
249
250int ocf_mngt_cache_io_classes_configure(ocf_cache_t cache,
251 const struct ocf_mngt_io_classes_config *cfg)
252{
253 struct ocf_user_part *old_config;
254 int result;
255 int i;
256
257 OCF_CHECK_NULL(cache);
258 OCF_CHECK_NULL(cfg);
259
260 for (i = 0; i < OCF_IO_CLASS_MAX; i++) {
261 result = _ocf_mngt_io_class_validate_cfg(cache, &cfg->config[i]);
262 if (result)
263 return result;
264 }
265
266 old_config = env_malloc(sizeof(cache->user_parts), ENV_MEM_NORMAL);
267 if (!old_config)
268 return -OCF_ERR_NO_MEM;
269
f67539c2 270 ocf_metadata_start_exclusive_access(&cache->metadata.lock);
9f95a23c 271
f67539c2
TL
272 result = env_memcpy(old_config, sizeof(cache->user_parts),
273 cache->user_parts, sizeof(cache->user_parts));
9f95a23c
TL
274 if (result)
275 goto out_cpy;
276
277 for (i = 0; i < OCF_IO_CLASS_MAX; i++) {
278 result = _ocf_mngt_io_class_edit(cache, &cfg->config[i]);
f67539c2 279 if (result) {
9f95a23c
TL
280 ocf_cache_log(cache, log_err,
281 "Failed to set new io class config\n");
282 goto out_edit;
283 }
284 }
285
286 ocf_part_sort(cache);
287
288out_edit:
289 if (result) {
f67539c2
TL
290 ENV_BUG_ON(env_memcpy(cache->user_parts, sizeof(cache->user_parts),
291 old_config, sizeof(cache->user_parts)));
9f95a23c
TL
292 }
293
294out_cpy:
f67539c2 295 ocf_metadata_end_exclusive_access(&cache->metadata.lock);
9f95a23c
TL
296 env_free(old_config);
297
298 return result;
299}