LCOV - code coverage report
Current view: top level - spdk/module/bdev/ocf - volume.c (source / functions) Hit Total Coverage
Test: Combined Lines: 121 156 77.6 %
Date: 2024-11-20 12:03:43 Functions: 17 17 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 34 68 50.0 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (C) 2019 Intel Corporation.
       3                 :            :  *   All rights reserved.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include <ocf/ocf.h>
       7                 :            : 
       8                 :            : #include "spdk/bdev_module.h"
       9                 :            : #include "spdk/env.h"
      10                 :            : #include "spdk/thread.h"
      11                 :            : #include "spdk/log.h"
      12                 :            : 
      13                 :            : #include "data.h"
      14                 :            : #include "volume.h"
      15                 :            : #include "ctx.h"
      16                 :            : #include "vbdev_ocf.h"
      17                 :            : 
      18                 :            : static int
      19                 :        170 : vbdev_ocf_volume_open(ocf_volume_t volume, void *opts)
      20                 :            : {
      21                 :        170 :         struct vbdev_ocf_base **priv = ocf_volume_get_priv(volume);
      22                 :            :         struct vbdev_ocf_base *base;
      23                 :            : 
      24         [ +  + ]:        170 :         if (opts) {
      25                 :        126 :                 base = opts;
      26                 :            :         } else {
      27                 :         44 :                 base = vbdev_ocf_get_base_by_name(ocf_volume_get_uuid(volume)->data);
      28         [ -  + ]:         44 :                 if (base == NULL) {
      29                 :          0 :                         return -ENODEV;
      30                 :            :                 }
      31                 :            :         }
      32                 :            : 
      33                 :        170 :         *priv = base;
      34                 :            : 
      35                 :        170 :         return 0;
      36                 :            : }
      37                 :            : 
      38                 :            : static void
      39                 :         44 : vbdev_ocf_volume_close(ocf_volume_t volume)
      40                 :            : {
      41                 :         44 : }
      42                 :            : 
      43                 :            : static uint64_t
      44                 :    1260536 : vbdev_ocf_volume_get_length(ocf_volume_t volume)
      45                 :            : {
      46                 :    1260536 :         struct vbdev_ocf_base *base = *((struct vbdev_ocf_base **)ocf_volume_get_priv(volume));
      47                 :            :         uint64_t len;
      48                 :            : 
      49                 :    1260536 :         len = base->bdev->blocklen * base->bdev->blockcnt;
      50                 :            : 
      51                 :    1260536 :         return len;
      52                 :            : }
      53                 :            : 
      54                 :            : static int
      55                 :      75012 : get_starting_vec(struct iovec *iovs, int iovcnt, uint64_t *offset)
      56                 :            : {
      57                 :            :         int i;
      58                 :            :         size_t off;
      59                 :            : 
      60                 :      75012 :         off = *offset;
      61                 :            : 
      62         [ +  - ]:      75012 :         for (i = 0; i < iovcnt; i++) {
      63         [ +  - ]:      75012 :                 if (off < iovs[i].iov_len) {
      64                 :      75012 :                         *offset = off;
      65                 :      75012 :                         return i;
      66                 :            :                 }
      67                 :          0 :                 off -= iovs[i].iov_len;
      68                 :            :         }
      69                 :            : 
      70                 :          0 :         return -1;
      71                 :            : }
      72                 :            : 
      73                 :            : static void
      74                 :      75012 : initialize_cpy_vector(struct iovec *cpy_vec, int cpy_vec_len, struct iovec *orig_vec,
      75                 :            :                       int orig_vec_len,
      76                 :            :                       size_t offset, size_t bytes)
      77                 :            : {
      78                 :            :         void *curr_base;
      79                 :            :         int len, i;
      80                 :            : 
      81                 :      75012 :         i = 0;
      82                 :            : 
      83         [ +  + ]:     150024 :         while (bytes > 0) {
      84                 :      75012 :                 curr_base = orig_vec[i].iov_base + offset;
      85                 :      75012 :                 len = MIN(bytes, orig_vec[i].iov_len - offset);
      86                 :            : 
      87                 :      75012 :                 cpy_vec[i].iov_base = curr_base;
      88                 :      75012 :                 cpy_vec[i].iov_len = len;
      89                 :            : 
      90                 :      75012 :                 bytes -= len;
      91                 :      75012 :                 offset = 0;
      92                 :      75012 :                 i++;
      93                 :            :         }
      94                 :      75012 : }
      95                 :            : 
      96                 :            : static unsigned int
      97                 :     156713 : vbdev_ocf_volume_get_max_io_size(ocf_volume_t volume)
      98                 :            : {
      99                 :     156713 :         return 131072;
     100                 :            : }
     101                 :            : 
     102                 :            : static void
     103                 :    1999862 : vbdev_forward_io_cb(struct spdk_bdev_io *bdev_io, bool success, void *opaque)
     104                 :            : {
     105                 :    1999862 :         ocf_forward_token_t token = (ocf_forward_token_t) opaque;
     106                 :            : 
     107         [ -  + ]:    1999862 :         assert(token);
     108                 :            : 
     109                 :    1999862 :         spdk_bdev_free_io(bdev_io);
     110                 :            : 
     111         [ +  - ]:    1999862 :         ocf_forward_end(token, success ? 0 : -OCF_ERR_IO);
     112                 :    1999862 : }
     113                 :            : 
     114                 :            : static void
     115                 :      75012 : vbdev_forward_io_free_iovs_cb(struct spdk_bdev_io *bdev_io, bool success, void *opaque)
     116                 :            : {
     117                 :      75012 :         env_free(bdev_io->u.bdev.iovs);
     118                 :      75012 :         vbdev_forward_io_cb(bdev_io, success, opaque);
     119                 :      75012 : }
     120                 :            : 
     121                 :            : static struct spdk_io_channel *
     122                 :    1999862 : vbdev_forward_get_channel(ocf_volume_t volume, ocf_forward_token_t token)
     123                 :            : {
     124                 :    1999862 :         struct vbdev_ocf_base *base =
     125                 :            :                 *((struct vbdev_ocf_base **)
     126                 :    1999862 :                   ocf_volume_get_priv(volume));
     127                 :    1999862 :         ocf_queue_t queue = ocf_forward_get_io_queue(token);
     128                 :            :         struct vbdev_ocf_qctx *qctx;
     129                 :            : 
     130         [ +  + ]:    1999862 :         if (unlikely(ocf_queue_is_mngt(queue))) {
     131                 :      89558 :                 return base->management_channel;
     132                 :            :         }
     133                 :            : 
     134                 :    1910304 :         qctx = ocf_queue_get_priv(queue);
     135         [ -  + ]:    1910304 :         if (unlikely(qctx == NULL)) {
     136                 :          0 :                 return NULL;
     137                 :            :         }
     138                 :            : 
     139   [ -  +  +  + ]:    1910304 :         return (base->is_cache) ? qctx->cache_ch : qctx->core_ch;
     140                 :            : }
     141                 :            : 
     142                 :            : static void
     143                 :    1007484 : vbdev_forward_io(ocf_volume_t volume, ocf_forward_token_t token,
     144                 :            :                  int dir, uint64_t addr, uint64_t bytes,
     145                 :            :                  uint64_t offset)
     146                 :            : {
     147                 :    1007484 :         struct vbdev_ocf_base *base =
     148                 :            :                 *((struct vbdev_ocf_base **)
     149                 :    1007484 :                   ocf_volume_get_priv(volume));
     150                 :    1007484 :         struct bdev_ocf_data *data = ocf_forward_get_data(token);
     151                 :            :         struct spdk_io_channel *ch;
     152                 :    1007484 :         spdk_bdev_io_completion_cb cb = vbdev_forward_io_cb;
     153                 :    1007484 :         bool iovs_allocated = false;
     154                 :    1007484 :         int iovcnt, skip, status = -1;
     155                 :            :         struct iovec *iovs;
     156                 :            : 
     157                 :    1007484 :         ch = vbdev_forward_get_channel(volume, token);
     158         [ -  + ]:    1007484 :         if (unlikely(ch == NULL)) {
     159                 :          0 :                 ocf_forward_end(token, -EFAULT);
     160                 :          0 :                 return;
     161                 :            :         }
     162                 :            : 
     163         [ +  + ]:    1007484 :         if (bytes == data->size) {
     164                 :     932472 :                 iovs = data->iovs;
     165                 :     932472 :                 iovcnt = data->iovcnt;
     166                 :            :         } else {
     167                 :      75012 :                 skip = get_starting_vec(data->iovs, data->iovcnt, &offset);
     168         [ -  + ]:      75012 :                 if (skip < 0) {
     169                 :          0 :                         SPDK_ERRLOG("Offset bigger than data size\n");
     170                 :          0 :                         ocf_forward_end(token, -OCF_ERR_IO);
     171                 :          0 :                         return;
     172                 :            :                 }
     173                 :            : 
     174                 :      75012 :                 iovcnt = data->iovcnt - skip;
     175                 :            : 
     176                 :      75012 :                 iovs_allocated = true;
     177                 :      75012 :                 cb = vbdev_forward_io_free_iovs_cb;
     178                 :      75012 :                 iovs = env_malloc(sizeof(*iovs) * iovcnt, ENV_MEM_NOIO);
     179                 :            : 
     180         [ -  + ]:      75012 :                 if (!iovs) {
     181                 :          0 :                         SPDK_ERRLOG("Allocation failed\n");
     182                 :          0 :                         ocf_forward_end(token, -OCF_ERR_NO_MEM);
     183                 :          0 :                         return;
     184                 :            :                 }
     185                 :            : 
     186                 :      75012 :                 initialize_cpy_vector(iovs, data->iovcnt, &data->iovs[skip],
     187                 :            :                                       iovcnt, offset, bytes);
     188                 :            :         }
     189                 :            : 
     190         [ +  + ]:    1007484 :         if (dir == OCF_READ) {
     191                 :     213482 :                 status = spdk_bdev_readv(base->desc, ch, iovs, iovcnt,
     192                 :            :                                          addr, bytes, cb, (void *) token);
     193         [ +  - ]:     794002 :         } else if (dir == OCF_WRITE) {
     194                 :     794002 :                 status = spdk_bdev_writev(base->desc, ch, iovs, iovcnt,
     195                 :            :                                           addr, bytes, cb, (void *) token);
     196                 :            :         }
     197                 :            : 
     198         [ -  + ]:    1007484 :         if (unlikely(status)) {
     199                 :          0 :                 SPDK_ERRLOG("Submission failed with status=%d\n", status);
     200                 :            :                 /* Since callback is not called, we need to do it manually to free iovs */
     201         [ #  # ]:          0 :                 if (iovs_allocated) {
     202                 :          0 :                         env_free(iovs);
     203                 :            :                 }
     204         [ #  # ]:          0 :                 ocf_forward_end(token, (status == -ENOMEM) ? -OCF_ERR_NO_MEM : -OCF_ERR_IO);
     205                 :            :         }
     206                 :            : }
     207                 :            : 
     208                 :            : static void
     209                 :     781690 : vbdev_forward_flush(ocf_volume_t volume, ocf_forward_token_t token)
     210                 :            : {
     211                 :     781690 :         struct vbdev_ocf_base *base =
     212                 :            :                 *((struct vbdev_ocf_base **)
     213                 :     781690 :                   ocf_volume_get_priv(volume));
     214                 :            :         struct spdk_io_channel *ch;
     215                 :     781690 :         uint64_t bytes = base->bdev->blockcnt * base->bdev->blocklen;
     216                 :            :         int status;
     217                 :            : 
     218                 :     781690 :         ch = vbdev_forward_get_channel(volume, token);
     219         [ -  + ]:     781690 :         if (unlikely(ch == NULL)) {
     220                 :          0 :                 ocf_forward_end(token, -EFAULT);
     221                 :          0 :                 return;
     222                 :            :         }
     223                 :            : 
     224                 :     781690 :         status = spdk_bdev_flush(
     225                 :            :                          base->desc, ch, 0, bytes,
     226                 :            :                          vbdev_forward_io_cb, (void *)token);
     227         [ -  + ]:     781690 :         if (unlikely(status)) {
     228                 :          0 :                 SPDK_ERRLOG("Submission failed with status=%d\n", status);
     229         [ #  # ]:          0 :                 ocf_forward_end(token, (status == -ENOMEM) ? -OCF_ERR_NO_MEM : -OCF_ERR_IO);
     230                 :            :         }
     231                 :            : }
     232                 :            : 
     233                 :            : static void
     234                 :     210688 : vbdev_forward_discard(ocf_volume_t volume, ocf_forward_token_t token,
     235                 :            :                       uint64_t addr, uint64_t bytes)
     236                 :            : {
     237                 :     210688 :         struct vbdev_ocf_base *base =
     238                 :            :                 *((struct vbdev_ocf_base **)
     239                 :     210688 :                   ocf_volume_get_priv(volume));
     240                 :            :         struct spdk_io_channel *ch;
     241                 :     210688 :         int status = 0;
     242                 :            : 
     243                 :     210688 :         ch = vbdev_forward_get_channel(volume, token);
     244         [ -  + ]:     210688 :         if (unlikely(ch == NULL)) {
     245                 :          0 :                 ocf_forward_end(token, -EFAULT);
     246                 :          0 :                 return;
     247                 :            :         }
     248                 :            : 
     249                 :     210688 :         status = spdk_bdev_unmap(
     250                 :            :                          base->desc, ch, addr, bytes,
     251                 :            :                          vbdev_forward_io_cb, (void *)token);
     252         [ -  + ]:     210688 :         if (unlikely(status)) {
     253                 :          0 :                 SPDK_ERRLOG("Submission failed with status=%d\n", status);
     254         [ #  # ]:          0 :                 ocf_forward_end(token, (status == -ENOMEM) ? -OCF_ERR_NO_MEM : -OCF_ERR_IO);
     255                 :            :         }
     256                 :            : }
     257                 :            : 
     258                 :            : struct vbdev_forward_io_simple_ctx {
     259                 :            :         ocf_forward_token_t token;
     260                 :            :         struct spdk_io_channel *ch;
     261                 :            : };
     262                 :            : 
     263                 :            : static void
     264                 :        126 : vbdev_forward_io_simple_cb(struct spdk_bdev_io *bdev_io, bool success, void *opaque)
     265                 :            : {
     266                 :        126 :         struct vbdev_forward_io_simple_ctx *ctx = opaque;
     267                 :        126 :         ocf_forward_token_t token = ctx->token;
     268                 :            : 
     269         [ -  + ]:        126 :         assert(token);
     270                 :            : 
     271                 :        126 :         spdk_bdev_free_io(bdev_io);
     272                 :        126 :         spdk_put_io_channel(ctx->ch);
     273                 :        126 :         env_free(ctx);
     274                 :            : 
     275         [ +  - ]:        126 :         ocf_forward_end(token, success ? 0 : -OCF_ERR_IO);
     276                 :        126 : }
     277                 :            : 
     278                 :            : static void
     279                 :        126 : vbdev_forward_io_simple(ocf_volume_t volume, ocf_forward_token_t token,
     280                 :            :                         int dir, uint64_t addr, uint64_t bytes)
     281                 :            : {
     282                 :        126 :         struct vbdev_ocf_base *base =
     283                 :            :                 *((struct vbdev_ocf_base **)
     284                 :        126 :                   ocf_volume_get_priv(volume));
     285                 :        126 :         struct bdev_ocf_data *data = ocf_forward_get_data(token);
     286                 :            :         struct vbdev_forward_io_simple_ctx *ctx;
     287                 :        126 :         int status = -1;
     288                 :            : 
     289                 :        126 :         ctx = env_malloc(sizeof(*ctx), ENV_MEM_NOIO);
     290         [ -  + ]:        126 :         if (unlikely(!ctx)) {
     291                 :          0 :                 ocf_forward_end(token, -OCF_ERR_NO_MEM);
     292                 :          0 :                 return;
     293                 :            :         }
     294                 :            : 
     295                 :            :         /* Forward IO simple is used in context where queue is not available
     296                 :            :          * so we have to get io channel ourselves */
     297                 :        126 :         ctx->ch = spdk_bdev_get_io_channel(base->desc);
     298         [ -  + ]:        126 :         if (unlikely(ctx->ch == NULL)) {
     299                 :          0 :                 env_free(ctx);
     300                 :          0 :                 ocf_forward_end(token, -EFAULT);
     301                 :          0 :                 return;
     302                 :            :         }
     303                 :            : 
     304                 :        126 :         ctx->token = token;
     305                 :            : 
     306         [ +  - ]:        126 :         if (dir == OCF_READ) {
     307                 :        126 :                 status = spdk_bdev_readv(base->desc, ctx->ch, data->iovs,
     308                 :            :                                          data->iovcnt, addr, bytes,
     309                 :            :                                          vbdev_forward_io_simple_cb, ctx);
     310         [ #  # ]:          0 :         } else if (dir == OCF_WRITE) {
     311                 :          0 :                 status = spdk_bdev_writev(base->desc, ctx->ch, data->iovs,
     312                 :            :                                           data->iovcnt, addr, bytes,
     313                 :            :                                           vbdev_forward_io_simple_cb, ctx);
     314                 :            :         }
     315                 :            : 
     316         [ -  + ]:        126 :         if (unlikely(status)) {
     317                 :          0 :                 SPDK_ERRLOG("Submission failed with status=%d\n", status);
     318                 :          0 :                 spdk_put_io_channel(ctx->ch);
     319                 :          0 :                 env_free(ctx);
     320         [ #  # ]:          0 :                 ocf_forward_end(token, (status == -ENOMEM) ? -OCF_ERR_NO_MEM : -OCF_ERR_IO);
     321                 :            :         }
     322                 :            : }
     323                 :            : 
     324                 :            : static struct ocf_volume_properties vbdev_volume_props = {
     325                 :            :         .name = "SPDK_block_device",
     326                 :            :         .volume_priv_size = sizeof(struct vbdev_ocf_base *),
     327                 :            :         .caps = {
     328                 :            :                 .atomic_writes = 0 /* to enable need to have ops->submit_metadata */
     329                 :            :         },
     330                 :            :         .ops = {
     331                 :            :                 .open = vbdev_ocf_volume_open,
     332                 :            :                 .close = vbdev_ocf_volume_close,
     333                 :            :                 .get_length = vbdev_ocf_volume_get_length,
     334                 :            :                 .get_max_io_size = vbdev_ocf_volume_get_max_io_size,
     335                 :            :                 .forward_io = vbdev_forward_io,
     336                 :            :                 .forward_flush = vbdev_forward_flush,
     337                 :            :                 .forward_discard = vbdev_forward_discard,
     338                 :            :                 .forward_io_simple = vbdev_forward_io_simple,
     339                 :            :         },
     340                 :            : };
     341                 :            : 
     342                 :            : int
     343                 :         69 : vbdev_ocf_volume_init(void)
     344                 :            : {
     345                 :         69 :         return ocf_ctx_register_volume_type(vbdev_ocf_ctx, SPDK_OBJECT, &vbdev_volume_props);
     346                 :            : }
     347                 :            : 
     348                 :            : void
     349                 :         69 : vbdev_ocf_volume_cleanup(void)
     350                 :            : {
     351                 :         69 :         ocf_ctx_unregister_volume_type(vbdev_ocf_ctx, SPDK_OBJECT);
     352                 :         69 : }
     353                 :            : 
     354                 :         77 : SPDK_LOG_REGISTER_COMPONENT(vbdev_ocf_volume)

Generated by: LCOV version 1.14