2 * Copyright(c) 2012-2018 Intel Corporation
3 * SPDX-License-Identifier: BSD-3-Clause-Clear
8 #include "ocf_volume_priv.h"
9 #include "ocf_io_priv.h"
12 /* *** Bottom interface *** */
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
)
22 const struct ocf_volume_ops
*ops
= &properties
->ops
;
23 ocf_io_allocator_type_t allocator_type
;
24 struct ocf_volume_type
*new_type
;
27 if (!ops
->submit_io
|| !ops
->open
|| !ops
->close
||
28 !ops
->get_max_io_size
|| !ops
->get_length
) {
29 return -OCF_ERR_INVAL
;
32 if (properties
->caps
.atomic_writes
&& !ops
->submit_metadata
)
33 return -OCF_ERR_INVAL
;
35 new_type
= env_zalloc(sizeof(**type
), ENV_MEM_NORMAL
);
37 return -OCF_ERR_NO_MEM
;
39 if (extended
&& extended
->allocator_type
)
40 allocator_type
= extended
->allocator_type
;
42 allocator_type
= ocf_io_allocator_get_type_default();
44 ret
= ocf_io_allocator_init(&new_type
->allocator
, allocator_type
,
45 properties
->io_priv_size
, properties
->name
);
49 new_type
->properties
= properties
;
60 void ocf_volume_type_deinit(struct ocf_volume_type
*type
)
62 if (type
->properties
->deinit
)
63 type
->properties
->deinit();
65 ocf_io_allocator_deinit(&type
->allocator
);
73 int ocf_volume_init(ocf_volume_t volume
, ocf_volume_type_t type
,
74 struct ocf_volume_uuid
*uuid
, bool uuid_copy
)
81 return -OCF_ERR_INVAL
;
83 priv_size
= type
->properties
->volume_priv_size
;
85 volume
->opened
= false;
88 volume
->priv
= env_zalloc(priv_size
, ENV_MEM_NORMAL
);
90 return -OCF_ERR_NO_MEM
;
92 ocf_refcnt_init(&volume
->refcnt
);
93 ocf_refcnt_freeze(&volume
->refcnt
);
96 volume
->uuid
.size
= 0;
97 volume
->uuid
.data
= NULL
;
98 volume
->uuid_copy
= false;
102 volume
->uuid_copy
= uuid_copy
;
105 data
= env_vmalloc(uuid
->size
);
109 ret
= env_memcpy(data
, uuid
->size
, uuid
->data
, uuid
->size
);
115 volume
->uuid
.data
= data
;
117 volume
->uuid
.data
= uuid
->data
;
120 volume
->uuid
.size
= uuid
->size
;
125 ocf_refcnt_unfreeze(&volume
->refcnt
);
126 env_free(volume
->priv
);
127 return -OCF_ERR_NO_MEM
;
130 void ocf_volume_deinit(ocf_volume_t volume
)
132 OCF_CHECK_NULL(volume
);
134 env_free(volume
->priv
);
136 if (volume
->uuid_copy
&& volume
->uuid
.data
) {
137 env_vfree(volume
->uuid
.data
);
138 volume
->uuid
.data
= NULL
;
139 volume
->uuid
.size
= 0;
143 void ocf_volume_move(ocf_volume_t volume
, ocf_volume_t from
)
145 OCF_CHECK_NULL(volume
);
146 OCF_CHECK_NULL(from
);
148 ocf_volume_deinit(volume
);
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
;
160 * Deinitialize original volume without freeing resources.
162 from
->opened
= false;
164 from
->uuid
.data
= NULL
;
167 int ocf_volume_create(ocf_volume_t
*volume
, ocf_volume_type_t type
,
168 struct ocf_volume_uuid
*uuid
)
170 ocf_volume_t tmp_volume
;
173 OCF_CHECK_NULL(volume
);
175 tmp_volume
= env_zalloc(sizeof(*tmp_volume
), ENV_MEM_NORMAL
);
177 return -OCF_ERR_NO_MEM
;
179 ret
= ocf_volume_init(tmp_volume
, type
, uuid
, true);
181 env_free(tmp_volume
);
185 *volume
= tmp_volume
;
190 void ocf_volume_destroy(ocf_volume_t volume
)
192 OCF_CHECK_NULL(volume
);
194 ocf_volume_deinit(volume
);
198 ocf_volume_type_t
ocf_volume_get_type(ocf_volume_t volume
)
200 OCF_CHECK_NULL(volume
);
205 const struct ocf_volume_uuid
*ocf_volume_get_uuid(ocf_volume_t volume
)
207 OCF_CHECK_NULL(volume
);
209 return &volume
->uuid
;
212 void ocf_volume_set_uuid(ocf_volume_t volume
, const struct ocf_volume_uuid
*uuid
)
214 OCF_CHECK_NULL(volume
);
216 if (volume
->uuid_copy
&& volume
->uuid
.data
)
217 env_vfree(volume
->uuid
.data
);
219 volume
->uuid
.data
= uuid
->data
;
220 volume
->uuid
.size
= uuid
->size
;
223 void *ocf_volume_get_priv(ocf_volume_t volume
)
228 ocf_cache_t
ocf_volume_get_cache(ocf_volume_t volume
)
230 OCF_CHECK_NULL(volume
);
232 return volume
->cache
;
235 int ocf_volume_is_atomic(ocf_volume_t volume
)
237 return volume
->type
->properties
->caps
.atomic_writes
;
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
)
244 return ocf_io_new(volume
, queue
, addr
, bytes
, dir
, io_class
, flags
);
247 void ocf_volume_submit_io(struct ocf_io
*io
)
249 ocf_volume_t volume
= ocf_io_get_volume(io
);
251 ENV_BUG_ON(!volume
->type
->properties
->ops
.submit_io
);
254 io
->end(io
, -OCF_ERR_IO
);
256 volume
->type
->properties
->ops
.submit_io(io
);
259 void ocf_volume_submit_flush(struct ocf_io
*io
)
261 ocf_volume_t volume
= ocf_io_get_volume(io
);
263 ENV_BUG_ON(!volume
->type
->properties
->ops
.submit_flush
);
266 io
->end(io
, -OCF_ERR_IO
);
268 if (!volume
->type
->properties
->ops
.submit_flush
) {
273 volume
->type
->properties
->ops
.submit_flush(io
);
276 void ocf_volume_submit_discard(struct ocf_io
*io
)
278 ocf_volume_t volume
= ocf_io_get_volume(io
);
281 io
->end(io
, -OCF_ERR_IO
);
283 if (!volume
->type
->properties
->ops
.submit_discard
) {
288 volume
->type
->properties
->ops
.submit_discard(io
);
291 int ocf_volume_open(ocf_volume_t volume
, void *volume_params
)
295 ENV_BUG_ON(!volume
->type
->properties
->ops
.open
);
296 ENV_BUG_ON(volume
->opened
);
298 ret
= volume
->type
->properties
->ops
.open(volume
, volume_params
);
302 ocf_refcnt_unfreeze(&volume
->refcnt
);
303 volume
->opened
= true;
308 static void ocf_volume_close_end(void *ctx
)
310 env_completion
*cmpl
= ctx
;
312 env_completion_complete(cmpl
);
313 env_completion_destroy(cmpl
);
316 void ocf_volume_close(ocf_volume_t volume
)
320 ENV_BUG_ON(!volume
->type
->properties
->ops
.close
);
321 ENV_BUG_ON(!volume
->opened
);
323 env_completion_init(&cmpl
);
324 ocf_refcnt_freeze(&volume
->refcnt
);
325 ocf_refcnt_register_zero_cb(&volume
->refcnt
, ocf_volume_close_end
,
327 env_completion_wait(&cmpl
);
329 volume
->type
->properties
->ops
.close(volume
);
330 volume
->opened
= false;
333 unsigned int ocf_volume_get_max_io_size(ocf_volume_t volume
)
335 ENV_BUG_ON(!volume
->type
->properties
->ops
.get_max_io_size
);
340 return volume
->type
->properties
->ops
.get_max_io_size(volume
);
343 uint64_t ocf_volume_get_length(ocf_volume_t volume
)
345 ENV_BUG_ON(!volume
->type
->properties
->ops
.get_length
);
350 return volume
->type
->properties
->ops
.get_length(volume
);