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.
37 #include "spdk_internal/log.h"
43 ocf_ctx_t vbdev_ocf_ctx
;
46 vbdev_ocf_ctx_data_alloc(uint32_t pages
)
48 struct bdev_ocf_data
*data
;
52 data
= vbdev_ocf_data_alloc(1);
54 sz
= pages
* PAGE_SIZE
;
55 buf
= spdk_malloc(sz
, PAGE_SIZE
, NULL
,
56 SPDK_ENV_LCORE_ID_ANY
, SPDK_MALLOC_DMA
);
61 vbdev_ocf_iovs_add(data
, buf
, sz
);
69 vbdev_ocf_ctx_data_free(ctx_data_t
*ctx_data
)
71 struct bdev_ocf_data
*data
= ctx_data
;
78 for (i
= 0; i
< data
->iovcnt
; i
++) {
79 spdk_free(data
->iovs
[i
].iov_base
);
82 vbdev_ocf_data_free(data
);
86 vbdev_ocf_ctx_data_mlock(ctx_data_t
*ctx_data
)
88 /* TODO [mlock]: add mlock option */
93 vbdev_ocf_ctx_data_munlock(ctx_data_t
*ctx_data
)
95 /* TODO [mlock]: add mlock option */
99 iovec_flatten(struct iovec
*iov
, size_t iovcnt
, void *buf
, size_t size
, size_t offset
)
101 size_t i
, len
, done
= 0;
103 for (i
= 0; i
< iovcnt
; i
++) {
104 if (offset
>= iov
[i
].iov_len
) {
105 offset
-= iov
[i
].iov_len
;
109 if (iov
[i
].iov_base
== NULL
) {
117 len
= MIN(size
- done
, iov
[i
].iov_len
- offset
);
118 memcpy(buf
, iov
[i
].iov_base
+ offset
, len
);
128 vbdev_ocf_ctx_data_rd(void *dst
, ctx_data_t
*src
, uint32_t size
)
130 struct bdev_ocf_data
*s
= src
;
133 size_local
= iovec_flatten(s
->iovs
, s
->iovcnt
, dst
, size
, s
->seek
);
134 s
->seek
+= size_local
;
140 buf_to_iovec(const void *buf
, size_t size
, struct iovec
*iov
, size_t iovcnt
, size_t offset
)
142 size_t i
, len
, done
= 0;
144 for (i
= 0; i
< iovcnt
; i
++) {
145 if (offset
>= iov
[i
].iov_len
) {
146 offset
-= iov
[i
].iov_len
;
150 if (iov
[i
].iov_base
== NULL
) {
158 len
= MIN(size
- done
, iov
[i
].iov_len
- offset
);
159 memcpy(iov
[i
].iov_base
+ offset
, buf
, len
);
169 vbdev_ocf_ctx_data_wr(ctx_data_t
*dst
, const void *src
, uint32_t size
)
171 struct bdev_ocf_data
*d
= dst
;
174 size_local
= buf_to_iovec(src
, size
, d
->iovs
, d
->iovcnt
, d
->seek
);
175 d
->seek
+= size_local
;
181 iovset(struct iovec
*iov
, size_t iovcnt
, int byte
, size_t size
, size_t offset
)
183 size_t i
, len
, done
= 0;
185 for (i
= 0; i
< iovcnt
; i
++) {
186 if (offset
>= iov
[i
].iov_len
) {
187 offset
-= iov
[i
].iov_len
;
191 if (iov
[i
].iov_base
== NULL
) {
199 len
= MIN(size
- done
, iov
[i
].iov_len
- offset
);
200 memset(iov
[i
].iov_base
+ offset
, byte
, len
);
209 vbdev_ocf_ctx_data_zero(ctx_data_t
*dst
, uint32_t size
)
211 struct bdev_ocf_data
*d
= dst
;
214 size_local
= iovset(d
->iovs
, d
->iovcnt
, 0, size
, d
->seek
);
215 d
->seek
+= size_local
;
221 vbdev_ocf_ctx_data_seek(ctx_data_t
*dst
, ctx_data_seek_t seek
, uint32_t offset
)
223 struct bdev_ocf_data
*d
= dst
;
227 case ctx_data_seek_begin
:
228 off
= MIN(offset
, d
->size
);
231 case ctx_data_seek_current
:
232 off
= MIN(offset
, d
->size
- d
->seek
);
241 vbdev_ocf_ctx_data_cpy(ctx_data_t
*dst
, ctx_data_t
*src
, uint64_t to
,
242 uint64_t from
, uint64_t bytes
)
244 struct bdev_ocf_data
*s
= src
;
245 struct bdev_ocf_data
*d
= dst
;
250 bytes
= MIN(bytes
, s
->size
- from
);
251 bytes
= MIN(bytes
, d
->size
- to
);
254 while (from
|| bytes
) {
255 if (s
->iovs
[it_iov
].iov_len
== it_off
) {
262 n
= MIN(from
, s
->iovs
[it_iov
].iov_len
);
265 n
= MIN(bytes
, s
->iovs
[it_iov
].iov_len
);
266 buf_to_iovec(s
->iovs
[it_iov
].iov_base
+ it_off
, n
, d
->iovs
, d
->iovcnt
, to
);
278 vbdev_ocf_ctx_data_secure_erase(ctx_data_t
*ctx_data
)
280 struct bdev_ocf_data
*data
= ctx_data
;
281 struct iovec
*iovs
= data
->iovs
;
284 for (i
= 0; i
< data
->iovcnt
; i
++) {
285 if (env_memset(iovs
[i
].iov_base
, iovs
[i
].iov_len
, 0)) {
291 int vbdev_ocf_queue_create(ocf_cache_t cache
, ocf_queue_t
*queue
, const struct ocf_queue_ops
*ops
)
294 struct vbdev_ocf_cache_ctx
*ctx
= ocf_cache_get_priv(cache
);
296 pthread_mutex_lock(&ctx
->lock
);
297 rc
= ocf_queue_create(cache
, queue
, ops
);
298 pthread_mutex_unlock(&ctx
->lock
);
302 void vbdev_ocf_queue_put(ocf_queue_t queue
)
304 ocf_cache_t cache
= ocf_queue_get_cache(queue
);
305 struct vbdev_ocf_cache_ctx
*ctx
= ocf_cache_get_priv(cache
);
307 pthread_mutex_lock(&ctx
->lock
);
308 ocf_queue_put(queue
);
309 pthread_mutex_unlock(&ctx
->lock
);
312 void vbdev_ocf_cache_ctx_put(struct vbdev_ocf_cache_ctx
*ctx
)
314 if (env_atomic_dec_return(&ctx
->refcnt
) == 0) {
315 pthread_mutex_destroy(&ctx
->lock
);
320 void vbdev_ocf_cache_ctx_get(struct vbdev_ocf_cache_ctx
*ctx
)
322 env_atomic_inc(&ctx
->refcnt
);
325 struct cleaner_priv
{
326 struct spdk_poller
*poller
;
332 cleaner_poll(void *arg
)
334 ocf_cleaner_t cleaner
= arg
;
335 struct cleaner_priv
*priv
= ocf_cleaner_get_priv(cleaner
);
336 uint32_t iono
= ocf_queue_pending_io(priv
->queue
);
337 int i
, max
= spdk_min(32, iono
);
339 for (i
= 0; i
< max
; i
++) {
340 ocf_queue_run_single(priv
->queue
);
343 if (spdk_get_ticks() >= priv
->next_run
) {
344 ocf_cleaner_run(cleaner
, priv
->queue
);
356 cleaner_cmpl(ocf_cleaner_t c
, uint32_t interval
)
358 struct cleaner_priv
*priv
= ocf_cleaner_get_priv(c
);
360 priv
->next_run
= spdk_get_ticks() + ((interval
* spdk_get_ticks_hz()) / 1000);
364 cleaner_queue_kick(ocf_queue_t q
)
369 cleaner_queue_stop(ocf_queue_t q
)
371 struct cleaner_priv
*cpriv
= ocf_queue_get_priv(q
);
374 spdk_poller_unregister(&cpriv
->poller
);
379 const struct ocf_queue_ops cleaner_queue_ops
= {
380 .kick_sync
= cleaner_queue_kick
,
381 .kick
= cleaner_queue_kick
,
382 .stop
= cleaner_queue_stop
,
386 vbdev_ocf_ctx_cleaner_init(ocf_cleaner_t c
)
389 struct cleaner_priv
*priv
= calloc(1, sizeof(*priv
));
390 ocf_cache_t cache
= ocf_cleaner_get_cache(c
);
391 struct vbdev_ocf_cache_ctx
*cctx
= ocf_cache_get_priv(cache
);
397 rc
= vbdev_ocf_queue_create(cache
, &priv
->queue
, &cleaner_queue_ops
);
403 ocf_queue_set_priv(priv
->queue
, priv
);
405 cctx
->cleaner_queue
= priv
->queue
;
407 ocf_cleaner_set_cmpl(c
, cleaner_cmpl
);
408 ocf_cleaner_set_priv(c
, priv
);
414 vbdev_ocf_ctx_cleaner_stop(ocf_cleaner_t c
)
416 struct cleaner_priv
*priv
= ocf_cleaner_get_priv(c
);
418 vbdev_ocf_queue_put(priv
->queue
);
422 vbdev_ocf_ctx_cleaner_kick(ocf_cleaner_t cleaner
)
424 struct cleaner_priv
*priv
= ocf_cleaner_get_priv(cleaner
);
430 /* We start cleaner poller at the same thread where cache was created
431 * TODO: allow user to specify core at which cleaner should run */
432 priv
->poller
= spdk_poller_register(cleaner_poll
, cleaner
, 0);
436 vbdev_ocf_md_kick(void *ctx
)
438 ocf_metadata_updater_t mu
= ctx
;
439 ocf_cache_t cache
= ocf_metadata_updater_get_cache(mu
);
441 if (ocf_cache_is_running(cache
)) {
442 ocf_metadata_updater_run(mu
);
447 vbdev_ocf_volume_updater_init(ocf_metadata_updater_t mu
)
449 struct spdk_thread
*md_thread
= spdk_get_thread();
451 ocf_metadata_updater_set_priv(mu
, md_thread
);
457 vbdev_ocf_volume_updater_stop(ocf_metadata_updater_t mu
)
463 vbdev_ocf_volume_updater_kick(ocf_metadata_updater_t mu
)
465 struct spdk_thread
*md_thread
= ocf_metadata_updater_get_priv(mu
);
467 /* We need to send message to updater thread because
468 * kick can happen from any thread */
469 spdk_thread_send_msg(md_thread
, vbdev_ocf_md_kick
, mu
);
472 /* This function is main way by which OCF communicates with user
473 * We don't want to use SPDK_LOG here because debugging information that is
474 * associated with every print message is not helpful in callback that only prints info
475 * while the real source is somewhere in OCF code */
477 vbdev_ocf_ctx_log_printf(ocf_logger_t logger
, ocf_logger_lvl_t lvl
,
478 const char *fmt
, va_list args
)
480 FILE *lfile
= stdout
;
482 if (lvl
> log_info
) {
486 if (lvl
<= log_warn
) {
490 return vfprintf(lfile
, fmt
, args
);
493 static const struct ocf_ctx_config vbdev_ocf_ctx_cfg
= {
498 .alloc
= vbdev_ocf_ctx_data_alloc
,
499 .free
= vbdev_ocf_ctx_data_free
,
500 .mlock
= vbdev_ocf_ctx_data_mlock
,
501 .munlock
= vbdev_ocf_ctx_data_munlock
,
502 .read
= vbdev_ocf_ctx_data_rd
,
503 .write
= vbdev_ocf_ctx_data_wr
,
504 .zero
= vbdev_ocf_ctx_data_zero
,
505 .seek
= vbdev_ocf_ctx_data_seek
,
506 .copy
= vbdev_ocf_ctx_data_cpy
,
507 .secure_erase
= vbdev_ocf_ctx_data_secure_erase
,
510 .metadata_updater
= {
511 .init
= vbdev_ocf_volume_updater_init
,
512 .stop
= vbdev_ocf_volume_updater_stop
,
513 .kick
= vbdev_ocf_volume_updater_kick
,
517 .init
= vbdev_ocf_ctx_cleaner_init
,
518 .stop
= vbdev_ocf_ctx_cleaner_stop
,
519 .kick
= vbdev_ocf_ctx_cleaner_kick
,
523 .print
= vbdev_ocf_ctx_log_printf
,
531 vbdev_ocf_ctx_init(void)
535 ret
= ocf_ctx_init(&vbdev_ocf_ctx
, &vbdev_ocf_ctx_cfg
);
544 vbdev_ocf_ctx_cleanup(void)
546 ocf_ctx_exit(vbdev_ocf_ctx
);
547 vbdev_ocf_ctx
= NULL
;
550 SPDK_LOG_REGISTER_COMPONENT("ocf_ocfctx", SPDK_LOG_OCFCTX
)