4 * Copyright (c) Intel Corporation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 #include "spdk/bdev_module.h"
38 #include "spdk/thread.h"
39 #include "spdk_internal/log.h"
44 #include "vbdev_ocf.h"
47 vbdev_ocf_volume_open(ocf_volume_t volume
, void *opts
)
49 struct vbdev_ocf_base
**priv
= ocf_volume_get_priv(volume
);
50 struct vbdev_ocf_base
*base
;
55 base
= vbdev_ocf_get_base_by_name(ocf_volume_get_uuid(volume
)->data
);
67 vbdev_ocf_volume_close(ocf_volume_t volume
)
72 vbdev_ocf_volume_get_length(ocf_volume_t volume
)
74 struct vbdev_ocf_base
*base
= *((struct vbdev_ocf_base
**)ocf_volume_get_priv(volume
));
77 len
= base
->bdev
->blocklen
* base
->bdev
->blockcnt
;
83 vbdev_ocf_volume_io_set_data(struct ocf_io
*io
, ctx_data_t
*data
,
86 struct ocf_io_ctx
*io_ctx
= ocf_get_io_ctx(io
);
88 io_ctx
->offset
= offset
;
91 if (io_ctx
->data
&& offset
>= io_ctx
->data
->size
) {
99 vbdev_ocf_volume_io_get_data(struct ocf_io
*io
)
101 return ocf_get_io_ctx(io
)->data
;
105 vbdev_ocf_volume_io_get(struct ocf_io
*io
)
107 struct ocf_io_ctx
*io_ctx
= ocf_get_io_ctx(io
);
113 vbdev_ocf_volume_io_put(struct ocf_io
*io
)
115 struct ocf_io_ctx
*io_ctx
= ocf_get_io_ctx(io
);
123 get_starting_vec(struct iovec
*iovs
, int iovcnt
, int *offset
)
130 for (i
= 0; i
< iovcnt
; i
++) {
131 if (off
< iovs
[i
].iov_len
) {
135 off
-= iovs
[i
].iov_len
;
142 initialize_cpy_vector(struct iovec
*cpy_vec
, int cpy_vec_len
, struct iovec
*orig_vec
,
144 size_t offset
, size_t bytes
)
152 curr_base
= orig_vec
[i
].iov_base
+ offset
;
153 len
= MIN(bytes
, orig_vec
[i
].iov_len
- offset
);
155 cpy_vec
[i
].iov_base
= curr_base
;
156 cpy_vec
[i
].iov_len
= len
;
165 vbdev_ocf_volume_submit_io_cb(struct spdk_bdev_io
*bdev_io
, bool success
, void *opaque
)
168 struct ocf_io_ctx
*io_ctx
;
173 io_ctx
= ocf_get_io_ctx(io
);
174 assert(io_ctx
!= NULL
);
180 if (io_ctx
->iovs_allocated
&& bdev_io
!= NULL
) {
181 env_free(bdev_io
->u
.bdev
.iovs
);
185 SPDK_DEBUGLOG(SPDK_TRACE_VBDEV_OCF_VOLUME
,
186 "base returned error on io submission: %d\n", io_ctx
->error
);
189 if (io
->io_queue
== NULL
&& io_ctx
->ch
!= NULL
) {
190 spdk_put_io_channel(io_ctx
->ch
);
193 vbdev_ocf_volume_io_put(io
);
195 spdk_bdev_free_io(bdev_io
);
198 if (--io_ctx
->rq_cnt
== 0) {
199 io
->end(io
, io_ctx
->error
);
204 prepare_submit(struct ocf_io
*io
)
206 struct ocf_io_ctx
*io_ctx
= ocf_get_io_ctx(io
);
207 struct vbdev_ocf_qctx
*qctx
;
208 struct vbdev_ocf_base
*base
;
209 ocf_queue_t q
= io
->io_queue
;
211 struct vbdev_ocf_cache_ctx
*cctx
;
215 if (io_ctx
->rq_cnt
!= 1) {
219 vbdev_ocf_volume_io_get(io
);
220 base
= *((struct vbdev_ocf_base
**)ocf_volume_get_priv(ocf_io_get_volume(io
)));
222 if (io
->io_queue
== NULL
) {
223 /* In case IO is initiated by OCF, queue is unknown
224 * so we have to get io channel ourselves */
225 io_ctx
->ch
= spdk_bdev_get_io_channel(base
->desc
);
226 if (io_ctx
->ch
== NULL
) {
232 cache
= ocf_queue_get_cache(q
);
233 cctx
= ocf_cache_get_priv(cache
);
235 if (q
== cctx
->cleaner_queue
|| q
== cctx
->mngt_queue
) {
236 io_ctx
->ch
= base
->management_channel
;
240 qctx
= ocf_queue_get_priv(q
);
245 if (base
->is_cache
) {
246 io_ctx
->ch
= qctx
->cache_ch
;
248 io_ctx
->ch
= qctx
->core_ch
;
255 vbdev_ocf_volume_submit_flush(struct ocf_io
*io
)
257 struct vbdev_ocf_base
*base
=
258 *((struct vbdev_ocf_base
**)
259 ocf_volume_get_priv(ocf_io_get_volume(io
)));
260 struct ocf_io_ctx
*io_ctx
= ocf_get_io_ctx(io
);
263 status
= prepare_submit(io
);
265 SPDK_ERRLOG("Preparing io failed with status=%d\n", status
);
266 vbdev_ocf_volume_submit_io_cb(NULL
, false, io
);
270 status
= spdk_bdev_flush(
271 base
->desc
, io_ctx
->ch
,
273 vbdev_ocf_volume_submit_io_cb
, io
);
275 /* Since callback is not called, we need to do it manually to free io structures */
276 SPDK_ERRLOG("Submission failed with status=%d\n", status
);
277 vbdev_ocf_volume_submit_io_cb(NULL
, false, io
);
282 vbdev_ocf_volume_submit_io(struct ocf_io
*io
)
284 struct vbdev_ocf_base
*base
=
285 *((struct vbdev_ocf_base
**)
286 ocf_volume_get_priv(ocf_io_get_volume(io
)));
287 struct ocf_io_ctx
*io_ctx
= ocf_get_io_ctx(io
);
289 int iovcnt
, status
= 0, i
, offset
;
292 if (io
->flags
== OCF_WRITE_FLUSH
) {
293 vbdev_ocf_volume_submit_flush(io
);
297 status
= prepare_submit(io
);
299 SPDK_ERRLOG("Preparing io failed with status=%d\n", status
);
300 vbdev_ocf_volume_submit_io_cb(NULL
, false, io
);
307 offset
= io_ctx
->offset
;
309 if (len
< io_ctx
->data
->size
) {
310 if (io_ctx
->data
->iovcnt
== 1) {
311 if (io
->dir
== OCF_READ
) {
312 status
= spdk_bdev_read(base
->desc
, io_ctx
->ch
,
313 io_ctx
->data
->iovs
[0].iov_base
+ offset
, addr
, len
,
314 vbdev_ocf_volume_submit_io_cb
, io
);
315 } else if (io
->dir
== OCF_WRITE
) {
316 status
= spdk_bdev_write(base
->desc
, io_ctx
->ch
,
317 io_ctx
->data
->iovs
[0].iov_base
+ offset
, addr
, len
,
318 vbdev_ocf_volume_submit_io_cb
, io
);
322 i
= get_starting_vec(io_ctx
->data
->iovs
, io_ctx
->data
->iovcnt
, &offset
);
325 SPDK_ERRLOG("offset bigger than data size\n");
326 vbdev_ocf_volume_submit_io_cb(NULL
, false, io
);
330 iovcnt
= io_ctx
->data
->iovcnt
- i
;
332 io_ctx
->iovs_allocated
= true;
333 iovs
= env_malloc(sizeof(*iovs
) * iovcnt
, ENV_MEM_NOIO
);
336 SPDK_ERRLOG("allocation failed\n");
337 vbdev_ocf_volume_submit_io_cb(NULL
, false, io
);
341 initialize_cpy_vector(iovs
, io_ctx
->data
->iovcnt
, &io_ctx
->data
->iovs
[i
],
342 iovcnt
, offset
, len
);
345 iovs
= io_ctx
->data
->iovs
;
346 iovcnt
= io_ctx
->data
->iovcnt
;
349 if (io
->dir
== OCF_READ
) {
350 status
= spdk_bdev_readv(base
->desc
, io_ctx
->ch
,
351 iovs
, iovcnt
, addr
, len
, vbdev_ocf_volume_submit_io_cb
, io
);
352 } else if (io
->dir
== OCF_WRITE
) {
353 status
= spdk_bdev_writev(base
->desc
, io_ctx
->ch
,
354 iovs
, iovcnt
, addr
, len
, vbdev_ocf_volume_submit_io_cb
, io
);
359 /* TODO [ENOMEM]: implement ENOMEM handling when submitting IO to base device */
361 /* Since callback is not called, we need to do it manually to free io structures */
362 SPDK_ERRLOG("submission failed with status=%d\n", status
);
363 vbdev_ocf_volume_submit_io_cb(NULL
, false, io
);
368 vbdev_ocf_volume_submit_discard(struct ocf_io
*io
)
370 struct vbdev_ocf_base
*base
=
371 *((struct vbdev_ocf_base
**)
372 ocf_volume_get_priv(ocf_io_get_volume(io
)));
373 struct ocf_io_ctx
*io_ctx
= ocf_get_io_ctx(io
);
376 status
= prepare_submit(io
);
378 SPDK_ERRLOG("Preparing io failed with status=%d\n", status
);
379 vbdev_ocf_volume_submit_io_cb(NULL
, false, io
);
383 status
= spdk_bdev_unmap(
384 base
->desc
, io_ctx
->ch
,
386 vbdev_ocf_volume_submit_io_cb
, io
);
388 /* Since callback is not called, we need to do it manually to free io structures */
389 SPDK_ERRLOG("Submission failed with status=%d\n", status
);
390 vbdev_ocf_volume_submit_io_cb(NULL
, false, io
);
395 vbdev_ocf_volume_submit_metadata(struct ocf_io
*io
)
397 /* Implement with persistent metadata support */
401 vbdev_ocf_volume_get_max_io_size(ocf_volume_t volume
)
406 static struct ocf_volume_properties vbdev_volume_props
= {
407 .name
= "SPDK block device",
408 .io_priv_size
= sizeof(struct ocf_io_ctx
),
409 .volume_priv_size
= sizeof(struct vbdev_ocf_base
*),
411 .atomic_writes
= 0 /* to enable need to have ops->submit_metadata */
414 .open
= vbdev_ocf_volume_open
,
415 .close
= vbdev_ocf_volume_close
,
416 .get_length
= vbdev_ocf_volume_get_length
,
417 .submit_io
= vbdev_ocf_volume_submit_io
,
418 .submit_discard
= vbdev_ocf_volume_submit_discard
,
419 .submit_flush
= vbdev_ocf_volume_submit_flush
,
420 .get_max_io_size
= vbdev_ocf_volume_get_max_io_size
,
421 .submit_metadata
= vbdev_ocf_volume_submit_metadata
,
424 .set_data
= vbdev_ocf_volume_io_set_data
,
425 .get_data
= vbdev_ocf_volume_io_get_data
,
430 vbdev_ocf_volume_init(void)
432 return ocf_ctx_register_volume_type(vbdev_ocf_ctx
, SPDK_OBJECT
, &vbdev_volume_props
);
436 vbdev_ocf_volume_cleanup(void)
438 ocf_ctx_unregister_volume_type(vbdev_ocf_ctx
, SPDK_OBJECT
);
441 SPDK_LOG_REGISTER_COMPONENT("vbdev_ocf_volume", SPDK_TRACE_VBDEV_OCF_VOLUME
)