]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/ocf/src/ocf_volume.c
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / spdk / ocf / src / ocf_volume.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_priv.h"
8 #include "ocf_volume_priv.h"
9 #include "ocf_io_priv.h"
10 #include "ocf_env.h"
11
12 /* *** Bottom interface *** */
13
14 /*
15 * Volume type
16 */
17
18 int ocf_volume_type_init(struct ocf_volume_type **type,
19 const struct ocf_volume_properties *properties,
20 const struct ocf_volume_extended *extended)
21 {
22 const struct ocf_volume_ops *ops = &properties->ops;
23 ocf_io_allocator_type_t allocator_type;
24 struct ocf_volume_type *new_type;
25 int ret;
26
27 if (!ops->submit_io || !ops->open || !ops->close ||
28 !ops->get_max_io_size || !ops->get_length) {
29 return -OCF_ERR_INVAL;
30 }
31
32 if (properties->caps.atomic_writes && !ops->submit_metadata)
33 return -OCF_ERR_INVAL;
34
35 new_type = env_zalloc(sizeof(**type), ENV_MEM_NORMAL);
36 if (!new_type)
37 return -OCF_ERR_NO_MEM;
38
39 if (extended && extended->allocator_type)
40 allocator_type = extended->allocator_type;
41 else
42 allocator_type = ocf_io_allocator_get_type_default();
43
44 ret = ocf_io_allocator_init(&new_type->allocator, allocator_type,
45 properties->io_priv_size, properties->name);
46 if (ret)
47 goto err;
48
49 new_type->properties = properties;
50
51 *type = new_type;
52
53 return 0;
54
55 err:
56 env_free(new_type);
57 return ret;
58 }
59
60 void ocf_volume_type_deinit(struct ocf_volume_type *type)
61 {
62 if (type->properties->deinit)
63 type->properties->deinit();
64
65 ocf_io_allocator_deinit(&type->allocator);
66 env_free(type);
67 }
68
69 /*
70 * Volume frontend API
71 */
72
73 int ocf_volume_init(ocf_volume_t volume, ocf_volume_type_t type,
74 struct ocf_volume_uuid *uuid, bool uuid_copy)
75 {
76 uint32_t priv_size;
77 void *data;
78 int ret;
79
80 if (!volume || !type)
81 return -OCF_ERR_INVAL;
82
83 priv_size = type->properties->volume_priv_size;
84
85 volume->opened = false;
86 volume->type = type;
87
88 volume->priv = env_zalloc(priv_size, ENV_MEM_NORMAL);
89 if (!volume->priv)
90 return -OCF_ERR_NO_MEM;
91
92 ocf_refcnt_init(&volume->refcnt);
93 ocf_refcnt_freeze(&volume->refcnt);
94
95 if (!uuid) {
96 volume->uuid.size = 0;
97 volume->uuid.data = NULL;
98 volume->uuid_copy = false;
99 return 0;
100 }
101
102 volume->uuid_copy = uuid_copy;
103
104 if (uuid_copy) {
105 data = env_vmalloc(uuid->size);
106 if (!data)
107 goto err;
108
109 ret = env_memcpy(data, uuid->size, uuid->data, uuid->size);
110 if (ret) {
111 env_vfree(data);
112 goto err;
113 }
114
115 volume->uuid.data = data;
116 } else {
117 volume->uuid.data = uuid->data;
118 }
119
120 volume->uuid.size = uuid->size;
121
122 return 0;
123
124 err:
125 ocf_refcnt_unfreeze(&volume->refcnt);
126 env_free(volume->priv);
127 return -OCF_ERR_NO_MEM;
128 }
129
130 void ocf_volume_deinit(ocf_volume_t volume)
131 {
132 OCF_CHECK_NULL(volume);
133
134 env_free(volume->priv);
135
136 if (volume->uuid_copy && volume->uuid.data) {
137 env_vfree(volume->uuid.data);
138 volume->uuid.data = NULL;
139 volume->uuid.size = 0;
140 }
141 }
142
143 void ocf_volume_move(ocf_volume_t volume, ocf_volume_t from)
144 {
145 OCF_CHECK_NULL(volume);
146 OCF_CHECK_NULL(from);
147
148 ocf_volume_deinit(volume);
149
150 volume->opened = from->opened;
151 volume->type = from->type;
152 volume->uuid = from->uuid;
153 volume->uuid_copy = from->uuid_copy;
154 volume->priv = from->priv;
155 volume->cache = from->cache;
156 volume->features = from->features;
157 volume->refcnt = from->refcnt;
158
159 /*
160 * Deinitialize original volume without freeing resources.
161 */
162 from->opened = false;
163 from->priv = NULL;
164 from->uuid.data = NULL;
165 }
166
167 int ocf_volume_create(ocf_volume_t *volume, ocf_volume_type_t type,
168 struct ocf_volume_uuid *uuid)
169 {
170 ocf_volume_t tmp_volume;
171 int ret;
172
173 OCF_CHECK_NULL(volume);
174
175 tmp_volume = env_zalloc(sizeof(*tmp_volume), ENV_MEM_NORMAL);
176 if (!tmp_volume)
177 return -OCF_ERR_NO_MEM;
178
179 ret = ocf_volume_init(tmp_volume, type, uuid, true);
180 if (ret) {
181 env_free(tmp_volume);
182 return ret;
183 }
184
185 *volume = tmp_volume;
186
187 return 0;
188 }
189
190 void ocf_volume_destroy(ocf_volume_t volume)
191 {
192 OCF_CHECK_NULL(volume);
193
194 ocf_volume_deinit(volume);
195 env_free(volume);
196 }
197
198 ocf_volume_type_t ocf_volume_get_type(ocf_volume_t volume)
199 {
200 OCF_CHECK_NULL(volume);
201
202 return volume->type;
203 }
204
205 const struct ocf_volume_uuid *ocf_volume_get_uuid(ocf_volume_t volume)
206 {
207 OCF_CHECK_NULL(volume);
208
209 return &volume->uuid;
210 }
211
212 void ocf_volume_set_uuid(ocf_volume_t volume, const struct ocf_volume_uuid *uuid)
213 {
214 OCF_CHECK_NULL(volume);
215
216 if (volume->uuid_copy && volume->uuid.data)
217 env_vfree(volume->uuid.data);
218
219 volume->uuid.data = uuid->data;
220 volume->uuid.size = uuid->size;
221 }
222
223 void *ocf_volume_get_priv(ocf_volume_t volume)
224 {
225 return volume->priv;
226 }
227
228 ocf_cache_t ocf_volume_get_cache(ocf_volume_t volume)
229 {
230 OCF_CHECK_NULL(volume);
231
232 return volume->cache;
233 }
234
235 int ocf_volume_is_atomic(ocf_volume_t volume)
236 {
237 return volume->type->properties->caps.atomic_writes;
238 }
239
240 struct ocf_io *ocf_volume_new_io(ocf_volume_t volume, ocf_queue_t queue,
241 uint64_t addr, uint32_t bytes, uint32_t dir,
242 uint32_t io_class, uint64_t flags)
243 {
244 return ocf_io_new(volume, queue, addr, bytes, dir, io_class, flags);
245 }
246
247 void ocf_volume_submit_io(struct ocf_io *io)
248 {
249 ocf_volume_t volume = ocf_io_get_volume(io);
250
251 ENV_BUG_ON(!volume->type->properties->ops.submit_io);
252
253 if (!volume->opened)
254 io->end(io, -OCF_ERR_IO);
255
256 volume->type->properties->ops.submit_io(io);
257 }
258
259 void ocf_volume_submit_flush(struct ocf_io *io)
260 {
261 ocf_volume_t volume = ocf_io_get_volume(io);
262
263 ENV_BUG_ON(!volume->type->properties->ops.submit_flush);
264
265 if (!volume->opened)
266 io->end(io, -OCF_ERR_IO);
267
268 if (!volume->type->properties->ops.submit_flush) {
269 ocf_io_end(io, 0);
270 return;
271 }
272
273 volume->type->properties->ops.submit_flush(io);
274 }
275
276 void ocf_volume_submit_discard(struct ocf_io *io)
277 {
278 ocf_volume_t volume = ocf_io_get_volume(io);
279
280 if (!volume->opened)
281 io->end(io, -OCF_ERR_IO);
282
283 if (!volume->type->properties->ops.submit_discard) {
284 ocf_io_end(io, 0);
285 return;
286 }
287
288 volume->type->properties->ops.submit_discard(io);
289 }
290
291 int ocf_volume_open(ocf_volume_t volume, void *volume_params)
292 {
293 int ret;
294
295 ENV_BUG_ON(!volume->type->properties->ops.open);
296 ENV_BUG_ON(volume->opened);
297
298 ret = volume->type->properties->ops.open(volume, volume_params);
299 if (ret)
300 return ret;
301
302 ocf_refcnt_unfreeze(&volume->refcnt);
303 volume->opened = true;
304
305 return 0;
306 }
307
308 static void ocf_volume_close_end(void *ctx)
309 {
310 env_completion *cmpl = ctx;
311
312 env_completion_complete(cmpl);
313 env_completion_destroy(cmpl);
314 }
315
316 void ocf_volume_close(ocf_volume_t volume)
317 {
318 env_completion cmpl;
319
320 ENV_BUG_ON(!volume->type->properties->ops.close);
321 ENV_BUG_ON(!volume->opened);
322
323 env_completion_init(&cmpl);
324 ocf_refcnt_freeze(&volume->refcnt);
325 ocf_refcnt_register_zero_cb(&volume->refcnt, ocf_volume_close_end,
326 &cmpl);
327 env_completion_wait(&cmpl);
328
329 volume->type->properties->ops.close(volume);
330 volume->opened = false;
331 }
332
333 unsigned int ocf_volume_get_max_io_size(ocf_volume_t volume)
334 {
335 ENV_BUG_ON(!volume->type->properties->ops.get_max_io_size);
336
337 if (!volume->opened)
338 return 0;
339
340 return volume->type->properties->ops.get_max_io_size(volume);
341 }
342
343 uint64_t ocf_volume_get_length(ocf_volume_t volume)
344 {
345 ENV_BUG_ON(!volume->type->properties->ops.get_length);
346
347 if (!volume->opened)
348 return 0;
349
350 return volume->type->properties->ops.get_length(volume);
351 }