LCOV - code coverage report
Current view: top level - module/bdev/ocf - ctx.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 0 197 0.0 %
Date: 2024-12-16 20:53:09 Functions: 0 26 0.0 %

          Line data    Source code
       1             : /*   SPDX-License-Identifier: BSD-3-Clause
       2             :  *   Copyright (C) 2018 Intel Corporation.
       3             :  *   All rights reserved.
       4             :  */
       5             : 
       6             : #include <ocf/ocf.h>
       7             : #ifdef SPDK_HAVE_EXECINFO_H
       8             : #include <execinfo.h>
       9             : #endif
      10             : 
      11             : #include "spdk/env.h"
      12             : #include "spdk/log.h"
      13             : 
      14             : #include "ctx.h"
      15             : #include "data.h"
      16             : 
      17             : ocf_ctx_t vbdev_ocf_ctx;
      18             : 
      19             : static ctx_data_t *
      20           0 : vbdev_ocf_ctx_data_alloc(uint32_t pages)
      21             : {
      22             :         struct bdev_ocf_data *data;
      23             :         void *buf;
      24             :         uint32_t sz;
      25             : 
      26           0 :         data = vbdev_ocf_data_alloc(1);
      27           0 :         if (data == NULL) {
      28           0 :                 return NULL;
      29             :         }
      30             : 
      31           0 :         sz = pages * PAGE_SIZE;
      32           0 :         buf = spdk_malloc(sz, PAGE_SIZE, NULL,
      33             :                           SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA);
      34           0 :         if (buf == NULL) {
      35           0 :                 vbdev_ocf_data_free(data);
      36           0 :                 return NULL;
      37             :         }
      38             : 
      39           0 :         vbdev_ocf_iovs_add(data, buf, sz);
      40             : 
      41           0 :         data->size = sz;
      42             : 
      43           0 :         return data;
      44             : }
      45             : 
      46             : static void
      47           0 : vbdev_ocf_ctx_data_free(ctx_data_t *ctx_data)
      48             : {
      49           0 :         struct bdev_ocf_data *data = ctx_data;
      50             :         int i;
      51             : 
      52           0 :         if (!data) {
      53           0 :                 return;
      54             :         }
      55             : 
      56           0 :         for (i = 0; i < data->iovcnt; i++) {
      57           0 :                 spdk_free(data->iovs[i].iov_base);
      58             :         }
      59             : 
      60           0 :         vbdev_ocf_data_free(data);
      61             : }
      62             : 
      63             : static int
      64           0 : vbdev_ocf_ctx_data_mlock(ctx_data_t *ctx_data)
      65             : {
      66             :         /* TODO [mlock]: add mlock option */
      67           0 :         return 0;
      68             : }
      69             : 
      70             : static void
      71           0 : vbdev_ocf_ctx_data_munlock(ctx_data_t *ctx_data)
      72             : {
      73             :         /* TODO [mlock]: add mlock option */
      74           0 : }
      75             : 
      76             : static size_t
      77           0 : iovec_flatten(struct iovec *iov, size_t iovcnt, void *buf, size_t size, size_t offset)
      78             : {
      79           0 :         size_t i, len, done = 0;
      80             : 
      81           0 :         for (i = 0; i < iovcnt; i++) {
      82           0 :                 if (offset >= iov[i].iov_len) {
      83           0 :                         offset -= iov[i].iov_len;
      84           0 :                         continue;
      85             :                 }
      86             : 
      87           0 :                 if (iov[i].iov_base == NULL) {
      88           0 :                         continue;
      89             :                 }
      90             : 
      91           0 :                 if (done >= size) {
      92           0 :                         break;
      93             :                 }
      94             : 
      95           0 :                 len = MIN(size - done, iov[i].iov_len - offset);
      96           0 :                 memcpy(buf, iov[i].iov_base + offset, len);
      97           0 :                 buf += len;
      98           0 :                 done += len;
      99           0 :                 offset = 0;
     100             :         }
     101             : 
     102           0 :         return done;
     103             : }
     104             : 
     105             : static uint32_t
     106           0 : vbdev_ocf_ctx_data_rd(void *dst, ctx_data_t *src, uint32_t size)
     107             : {
     108           0 :         struct bdev_ocf_data *s = src;
     109             :         uint32_t size_local;
     110             : 
     111           0 :         size_local = iovec_flatten(s->iovs, s->iovcnt, dst, size, s->seek);
     112           0 :         s->seek += size_local;
     113             : 
     114           0 :         return size_local;
     115             : }
     116             : 
     117             : static size_t
     118           0 : buf_to_iovec(const void *buf, size_t size, struct iovec *iov, size_t iovcnt, size_t offset)
     119             : {
     120           0 :         size_t i, len, done = 0;
     121             : 
     122           0 :         for (i = 0; i < iovcnt; i++) {
     123           0 :                 if (offset >= iov[i].iov_len) {
     124           0 :                         offset -= iov[i].iov_len;
     125           0 :                         continue;
     126             :                 }
     127             : 
     128           0 :                 if (iov[i].iov_base == NULL) {
     129           0 :                         continue;
     130             :                 }
     131             : 
     132           0 :                 if (done >= size) {
     133           0 :                         break;
     134             :                 }
     135             : 
     136           0 :                 len = MIN(size - done, iov[i].iov_len - offset);
     137           0 :                 memcpy(iov[i].iov_base + offset, buf, len);
     138           0 :                 buf += len;
     139           0 :                 done += len;
     140           0 :                 offset = 0;
     141             :         }
     142             : 
     143           0 :         return done;
     144             : }
     145             : 
     146             : static uint32_t
     147           0 : vbdev_ocf_ctx_data_wr(ctx_data_t *dst, const void *src, uint32_t size)
     148             : {
     149           0 :         struct bdev_ocf_data *d = dst;
     150             :         uint32_t size_local;
     151             : 
     152           0 :         size_local = buf_to_iovec(src, size, d->iovs, d->iovcnt, d->seek);
     153           0 :         d->seek += size_local;
     154             : 
     155           0 :         return size_local;
     156             : }
     157             : 
     158             : static size_t
     159           0 : iovset(struct iovec *iov, size_t iovcnt, int byte, size_t size, size_t offset)
     160             : {
     161           0 :         size_t i, len, done = 0;
     162             : 
     163           0 :         for (i = 0; i < iovcnt; i++) {
     164           0 :                 if (offset >= iov[i].iov_len) {
     165           0 :                         offset -= iov[i].iov_len;
     166           0 :                         continue;
     167             :                 }
     168             : 
     169           0 :                 if (iov[i].iov_base == NULL) {
     170           0 :                         continue;
     171             :                 }
     172             : 
     173           0 :                 if (done >= size) {
     174           0 :                         break;
     175             :                 }
     176             : 
     177           0 :                 len = MIN(size - done, iov[i].iov_len - offset);
     178           0 :                 memset(iov[i].iov_base + offset, byte, len);
     179           0 :                 done += len;
     180           0 :                 offset = 0;
     181             :         }
     182             : 
     183           0 :         return done;
     184             : }
     185             : 
     186             : static uint32_t
     187           0 : vbdev_ocf_ctx_data_zero(ctx_data_t *dst, uint32_t size)
     188             : {
     189           0 :         struct bdev_ocf_data *d = dst;
     190             :         uint32_t size_local;
     191             : 
     192           0 :         size_local = iovset(d->iovs, d->iovcnt, 0, size, d->seek);
     193           0 :         d->seek += size_local;
     194             : 
     195           0 :         return size_local;
     196             : }
     197             : 
     198             : static uint32_t
     199           0 : vbdev_ocf_ctx_data_seek(ctx_data_t *dst, ctx_data_seek_t seek, uint32_t offset)
     200             : {
     201           0 :         struct bdev_ocf_data *d = dst;
     202           0 :         uint32_t off = 0;
     203             : 
     204           0 :         switch (seek) {
     205           0 :         case ctx_data_seek_begin:
     206           0 :                 off = MIN(offset, d->size);
     207           0 :                 d->seek = off;
     208           0 :                 break;
     209           0 :         case ctx_data_seek_current:
     210           0 :                 off = MIN(offset, d->size - d->seek);
     211           0 :                 d->seek += off;
     212           0 :                 break;
     213             :         }
     214             : 
     215           0 :         return off;
     216             : }
     217             : 
     218             : static uint64_t
     219           0 : vbdev_ocf_ctx_data_cpy(ctx_data_t *dst, ctx_data_t *src, uint64_t to,
     220             :                        uint64_t from, uint64_t bytes)
     221             : {
     222           0 :         struct bdev_ocf_data *s = src;
     223           0 :         struct bdev_ocf_data *d = dst;
     224           0 :         uint32_t it_iov = 0;
     225           0 :         uint32_t it_off = 0;
     226             :         uint32_t n, sz;
     227             : 
     228           0 :         bytes = MIN(bytes, s->size - from);
     229           0 :         bytes = MIN(bytes, d->size - to);
     230           0 :         sz = bytes;
     231             : 
     232           0 :         while (from || bytes) {
     233           0 :                 if (s->iovs[it_iov].iov_len == it_off) {
     234           0 :                         it_iov++;
     235           0 :                         it_off = 0;
     236           0 :                         continue;
     237             :                 }
     238             : 
     239           0 :                 if (from) {
     240           0 :                         n = MIN(from, s->iovs[it_iov].iov_len);
     241           0 :                         from -= n;
     242             :                 } else {
     243           0 :                         n = MIN(bytes, s->iovs[it_iov].iov_len);
     244           0 :                         buf_to_iovec(s->iovs[it_iov].iov_base + it_off, n, d->iovs, d->iovcnt, to);
     245           0 :                         bytes -= n;
     246           0 :                         to += n;
     247             :                 }
     248             : 
     249           0 :                 it_off += n;
     250             :         }
     251             : 
     252           0 :         return sz;
     253             : }
     254             : 
     255             : static void
     256           0 : vbdev_ocf_ctx_data_secure_erase(ctx_data_t *ctx_data)
     257             : {
     258           0 :         struct bdev_ocf_data *data = ctx_data;
     259           0 :         struct iovec *iovs = data->iovs;
     260             :         int i;
     261             : 
     262           0 :         for (i = 0; i < data->iovcnt; i++) {
     263           0 :                 if (env_memset(iovs[i].iov_base, iovs[i].iov_len, 0)) {
     264           0 :                         assert(false);
     265             :                 }
     266             :         }
     267           0 : }
     268             : 
     269             : int
     270           0 : vbdev_ocf_queue_create(ocf_cache_t cache, ocf_queue_t *queue, const struct ocf_queue_ops *ops)
     271             : {
     272             : 
     273           0 :         return ocf_queue_create(cache, queue, ops);
     274             : }
     275             : 
     276             : int
     277           0 : vbdev_ocf_queue_create_mngt(ocf_cache_t cache, ocf_queue_t *queue, const struct ocf_queue_ops *ops)
     278             : {
     279           0 :         return ocf_queue_create_mngt(cache, queue, ops);
     280             : }
     281             : 
     282             : void
     283           0 : vbdev_ocf_queue_put(ocf_queue_t queue)
     284             : {
     285           0 :         ocf_queue_put(queue);
     286           0 : }
     287             : 
     288             : void
     289           0 : vbdev_ocf_cache_ctx_put(struct vbdev_ocf_cache_ctx *ctx)
     290             : {
     291           0 :         if (env_atomic_dec_return(&ctx->refcnt) == 0) {
     292           0 :                 free(ctx);
     293             :         }
     294           0 : }
     295             : 
     296             : void
     297           0 : vbdev_ocf_cache_ctx_get(struct vbdev_ocf_cache_ctx *ctx)
     298             : {
     299           0 :         env_atomic_inc(&ctx->refcnt);
     300           0 : }
     301             : 
     302             : struct cleaner_priv {
     303             :         struct spdk_poller *poller;
     304             :         ocf_queue_t         mngt_queue;
     305             :         uint64_t            next_run;
     306             : };
     307             : 
     308             : static int
     309           0 : cleaner_poll(void *arg)
     310             : {
     311           0 :         ocf_cleaner_t cleaner = arg;
     312           0 :         struct cleaner_priv *priv = ocf_cleaner_get_priv(cleaner);
     313             : 
     314           0 :         if (spdk_get_ticks() >= priv->next_run) {
     315           0 :                 ocf_cleaner_run(cleaner, priv->mngt_queue);
     316           0 :                 return SPDK_POLLER_BUSY;
     317             :         }
     318             : 
     319           0 :         return SPDK_POLLER_IDLE;
     320             : }
     321             : 
     322             : static void
     323           0 : cleaner_cmpl(ocf_cleaner_t c, uint32_t interval)
     324             : {
     325           0 :         struct cleaner_priv *priv = ocf_cleaner_get_priv(c);
     326             : 
     327           0 :         priv->next_run = spdk_get_ticks() + ((interval * spdk_get_ticks_hz()) / 1000);
     328           0 : }
     329             : 
     330             : static int
     331           0 : vbdev_ocf_ctx_cleaner_init(ocf_cleaner_t c)
     332             : {
     333           0 :         struct cleaner_priv        *priv  = calloc(1, sizeof(*priv));
     334           0 :         ocf_cache_t                 cache = ocf_cleaner_get_cache(c);
     335           0 :         struct vbdev_ocf_cache_ctx *cctx  = ocf_cache_get_priv(cache);
     336             : 
     337           0 :         if (priv == NULL) {
     338           0 :                 return -ENOMEM;
     339             :         }
     340             : 
     341           0 :         priv->mngt_queue = cctx->mngt_queue;
     342             : 
     343           0 :         ocf_cleaner_set_cmpl(c, cleaner_cmpl);
     344           0 :         ocf_cleaner_set_priv(c, priv);
     345             : 
     346           0 :         return 0;
     347             : }
     348             : 
     349             : static void
     350           0 : vbdev_ocf_ctx_cleaner_stop(ocf_cleaner_t c)
     351             : {
     352           0 :         struct cleaner_priv *priv = ocf_cleaner_get_priv(c);
     353             : 
     354           0 :         if (priv) {
     355           0 :                 spdk_poller_unregister(&priv->poller);
     356           0 :                 free(priv);
     357             :         }
     358           0 : }
     359             : 
     360             : static void
     361           0 : vbdev_ocf_ctx_cleaner_kick(ocf_cleaner_t cleaner)
     362             : {
     363           0 :         struct cleaner_priv *priv  = ocf_cleaner_get_priv(cleaner);
     364             : 
     365           0 :         if (priv->poller) {
     366           0 :                 return;
     367             :         }
     368             : 
     369             :         /* We start cleaner poller at the same thread where cache was created
     370             :          * TODO: allow user to specify core at which cleaner should run */
     371           0 :         priv->poller = SPDK_POLLER_REGISTER(cleaner_poll, cleaner, 0);
     372             : }
     373             : 
     374             : /* This function is main way by which OCF communicates with user
     375             :  * We don't want to use SPDK_LOG here because debugging information that is
     376             :  * associated with every print message is not helpful in callback that only prints info
     377             :  * while the real source is somewhere in OCF code */
     378             : static int
     379           0 : vbdev_ocf_ctx_log_printf(ocf_logger_t logger, ocf_logger_lvl_t lvl,
     380             :                          const char *fmt, va_list args)
     381             : {
     382             :         int spdk_lvl;
     383             : 
     384           0 :         switch (lvl) {
     385           0 :         case log_emerg:
     386             :         case log_alert:
     387             :         case log_crit:
     388             :         case log_err:
     389           0 :                 spdk_lvl = SPDK_LOG_ERROR;
     390           0 :                 break;
     391             : 
     392           0 :         case log_warn:
     393           0 :                 spdk_lvl = SPDK_LOG_WARN;
     394           0 :                 break;
     395             : 
     396           0 :         case log_notice:
     397           0 :                 spdk_lvl = SPDK_LOG_NOTICE;
     398           0 :                 break;
     399             : 
     400           0 :         case log_info:
     401             :         case log_debug:
     402             :         default:
     403           0 :                 spdk_lvl = SPDK_LOG_INFO;
     404             :         }
     405             : 
     406           0 :         spdk_vlog(spdk_lvl, NULL, -1, NULL, fmt, args);
     407           0 :         return 0;
     408             : }
     409             : 
     410             : static const struct ocf_ctx_config vbdev_ocf_ctx_cfg = {
     411             :         .name = "OCF SPDK",
     412             : 
     413             :         .ops = {
     414             :                 .data = {
     415             :                         .alloc = vbdev_ocf_ctx_data_alloc,
     416             :                         .free = vbdev_ocf_ctx_data_free,
     417             :                         .mlock = vbdev_ocf_ctx_data_mlock,
     418             :                         .munlock = vbdev_ocf_ctx_data_munlock,
     419             :                         .read = vbdev_ocf_ctx_data_rd,
     420             :                         .write = vbdev_ocf_ctx_data_wr,
     421             :                         .zero = vbdev_ocf_ctx_data_zero,
     422             :                         .seek = vbdev_ocf_ctx_data_seek,
     423             :                         .copy = vbdev_ocf_ctx_data_cpy,
     424             :                         .secure_erase = vbdev_ocf_ctx_data_secure_erase,
     425             :                 },
     426             : 
     427             :                 .cleaner = {
     428             :                         .init = vbdev_ocf_ctx_cleaner_init,
     429             :                         .stop = vbdev_ocf_ctx_cleaner_stop,
     430             :                         .kick = vbdev_ocf_ctx_cleaner_kick,
     431             :                 },
     432             : 
     433             :                 .logger = {
     434             :                         .print = vbdev_ocf_ctx_log_printf,
     435             :                         .dump_stack = NULL,
     436             :                 },
     437             : 
     438             :         },
     439             : };
     440             : 
     441             : int
     442           0 : vbdev_ocf_ctx_init(void)
     443             : {
     444             :         int ret;
     445             : 
     446           0 :         ret = ocf_ctx_create(&vbdev_ocf_ctx, &vbdev_ocf_ctx_cfg);
     447           0 :         if (ret < 0) {
     448           0 :                 return ret;
     449             :         }
     450             : 
     451           0 :         return 0;
     452             : }
     453             : 
     454             : void
     455           0 : vbdev_ocf_ctx_cleanup(void)
     456             : {
     457           0 :         ocf_ctx_put(vbdev_ocf_ctx);
     458           0 :         vbdev_ocf_ctx = NULL;
     459           0 : }

Generated by: LCOV version 1.15