LCOV - code coverage report
Current view: top level - module/bdev/ocf - volume.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 0 156 0.0 %
Date: 2024-12-14 14:11:24 Functions: 0 17 0.0 %

          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           0 : vbdev_ocf_volume_open(ocf_volume_t volume, void *opts)
      20             : {
      21           0 :         struct vbdev_ocf_base **priv = ocf_volume_get_priv(volume);
      22             :         struct vbdev_ocf_base *base;
      23             : 
      24           0 :         if (opts) {
      25           0 :                 base = opts;
      26             :         } else {
      27           0 :                 base = vbdev_ocf_get_base_by_name(ocf_volume_get_uuid(volume)->data);
      28           0 :                 if (base == NULL) {
      29           0 :                         return -ENODEV;
      30             :                 }
      31             :         }
      32             : 
      33           0 :         *priv = base;
      34             : 
      35           0 :         return 0;
      36             : }
      37             : 
      38             : static void
      39           0 : vbdev_ocf_volume_close(ocf_volume_t volume)
      40             : {
      41           0 : }
      42             : 
      43             : static uint64_t
      44           0 : vbdev_ocf_volume_get_length(ocf_volume_t volume)
      45             : {
      46           0 :         struct vbdev_ocf_base *base = *((struct vbdev_ocf_base **)ocf_volume_get_priv(volume));
      47             :         uint64_t len;
      48             : 
      49           0 :         len = base->bdev->blocklen * base->bdev->blockcnt;
      50             : 
      51           0 :         return len;
      52             : }
      53             : 
      54             : static int
      55           0 : get_starting_vec(struct iovec *iovs, int iovcnt, uint64_t *offset)
      56             : {
      57             :         int i;
      58             :         size_t off;
      59             : 
      60           0 :         off = *offset;
      61             : 
      62           0 :         for (i = 0; i < iovcnt; i++) {
      63           0 :                 if (off < iovs[i].iov_len) {
      64           0 :                         *offset = off;
      65           0 :                         return i;
      66             :                 }
      67           0 :                 off -= iovs[i].iov_len;
      68             :         }
      69             : 
      70           0 :         return -1;
      71             : }
      72             : 
      73             : static void
      74           0 : 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           0 :         i = 0;
      82             : 
      83           0 :         while (bytes > 0) {
      84           0 :                 curr_base = orig_vec[i].iov_base + offset;
      85           0 :                 len = MIN(bytes, orig_vec[i].iov_len - offset);
      86             : 
      87           0 :                 cpy_vec[i].iov_base = curr_base;
      88           0 :                 cpy_vec[i].iov_len = len;
      89             : 
      90           0 :                 bytes -= len;
      91           0 :                 offset = 0;
      92           0 :                 i++;
      93             :         }
      94           0 : }
      95             : 
      96             : static unsigned int
      97           0 : vbdev_ocf_volume_get_max_io_size(ocf_volume_t volume)
      98             : {
      99           0 :         return 131072;
     100             : }
     101             : 
     102             : static void
     103           0 : vbdev_forward_io_cb(struct spdk_bdev_io *bdev_io, bool success, void *opaque)
     104             : {
     105           0 :         ocf_forward_token_t token = (ocf_forward_token_t) opaque;
     106             : 
     107           0 :         assert(token);
     108             : 
     109           0 :         spdk_bdev_free_io(bdev_io);
     110             : 
     111           0 :         ocf_forward_end(token, success ? 0 : -OCF_ERR_IO);
     112           0 : }
     113             : 
     114             : static void
     115           0 : vbdev_forward_io_free_iovs_cb(struct spdk_bdev_io *bdev_io, bool success, void *opaque)
     116             : {
     117           0 :         env_free(bdev_io->u.bdev.iovs);
     118           0 :         vbdev_forward_io_cb(bdev_io, success, opaque);
     119           0 : }
     120             : 
     121             : static struct spdk_io_channel *
     122           0 : vbdev_forward_get_channel(ocf_volume_t volume, ocf_forward_token_t token)
     123             : {
     124           0 :         struct vbdev_ocf_base *base =
     125             :                 *((struct vbdev_ocf_base **)
     126           0 :                   ocf_volume_get_priv(volume));
     127           0 :         ocf_queue_t queue = ocf_forward_get_io_queue(token);
     128             :         struct vbdev_ocf_qctx *qctx;
     129             : 
     130           0 :         if (unlikely(ocf_queue_is_mngt(queue))) {
     131           0 :                 return base->management_channel;
     132             :         }
     133             : 
     134           0 :         qctx = ocf_queue_get_priv(queue);
     135           0 :         if (unlikely(qctx == NULL)) {
     136           0 :                 return NULL;
     137             :         }
     138             : 
     139           0 :         return (base->is_cache) ? qctx->cache_ch : qctx->core_ch;
     140             : }
     141             : 
     142             : static void
     143           0 : 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           0 :         struct vbdev_ocf_base *base =
     148             :                 *((struct vbdev_ocf_base **)
     149           0 :                   ocf_volume_get_priv(volume));
     150           0 :         struct bdev_ocf_data *data = ocf_forward_get_data(token);
     151             :         struct spdk_io_channel *ch;
     152           0 :         spdk_bdev_io_completion_cb cb = vbdev_forward_io_cb;
     153           0 :         bool iovs_allocated = false;
     154           0 :         int iovcnt, skip, status = -1;
     155             :         struct iovec *iovs;
     156             : 
     157           0 :         ch = vbdev_forward_get_channel(volume, token);
     158           0 :         if (unlikely(ch == NULL)) {
     159           0 :                 ocf_forward_end(token, -EFAULT);
     160           0 :                 return;
     161             :         }
     162             : 
     163           0 :         if (bytes == data->size) {
     164           0 :                 iovs = data->iovs;
     165           0 :                 iovcnt = data->iovcnt;
     166             :         } else {
     167           0 :                 skip = get_starting_vec(data->iovs, data->iovcnt, &offset);
     168           0 :                 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           0 :                 iovcnt = data->iovcnt - skip;
     175             : 
     176           0 :                 iovs_allocated = true;
     177           0 :                 cb = vbdev_forward_io_free_iovs_cb;
     178           0 :                 iovs = env_malloc(sizeof(*iovs) * iovcnt, ENV_MEM_NOIO);
     179             : 
     180           0 :                 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           0 :                 initialize_cpy_vector(iovs, data->iovcnt, &data->iovs[skip],
     187             :                                       iovcnt, offset, bytes);
     188             :         }
     189             : 
     190           0 :         if (dir == OCF_READ) {
     191           0 :                 status = spdk_bdev_readv(base->desc, ch, iovs, iovcnt,
     192             :                                          addr, bytes, cb, (void *) token);
     193           0 :         } else if (dir == OCF_WRITE) {
     194           0 :                 status = spdk_bdev_writev(base->desc, ch, iovs, iovcnt,
     195             :                                           addr, bytes, cb, (void *) token);
     196             :         }
     197             : 
     198           0 :         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           0 : vbdev_forward_flush(ocf_volume_t volume, ocf_forward_token_t token)
     210             : {
     211           0 :         struct vbdev_ocf_base *base =
     212             :                 *((struct vbdev_ocf_base **)
     213           0 :                   ocf_volume_get_priv(volume));
     214             :         struct spdk_io_channel *ch;
     215           0 :         uint64_t bytes = base->bdev->blockcnt * base->bdev->blocklen;
     216             :         int status;
     217             : 
     218           0 :         ch = vbdev_forward_get_channel(volume, token);
     219           0 :         if (unlikely(ch == NULL)) {
     220           0 :                 ocf_forward_end(token, -EFAULT);
     221           0 :                 return;
     222             :         }
     223             : 
     224           0 :         status = spdk_bdev_flush(
     225             :                          base->desc, ch, 0, bytes,
     226             :                          vbdev_forward_io_cb, (void *)token);
     227           0 :         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           0 : vbdev_forward_discard(ocf_volume_t volume, ocf_forward_token_t token,
     235             :                       uint64_t addr, uint64_t bytes)
     236             : {
     237           0 :         struct vbdev_ocf_base *base =
     238             :                 *((struct vbdev_ocf_base **)
     239           0 :                   ocf_volume_get_priv(volume));
     240             :         struct spdk_io_channel *ch;
     241           0 :         int status = 0;
     242             : 
     243           0 :         ch = vbdev_forward_get_channel(volume, token);
     244           0 :         if (unlikely(ch == NULL)) {
     245           0 :                 ocf_forward_end(token, -EFAULT);
     246           0 :                 return;
     247             :         }
     248             : 
     249           0 :         status = spdk_bdev_unmap(
     250             :                          base->desc, ch, addr, bytes,
     251             :                          vbdev_forward_io_cb, (void *)token);
     252           0 :         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           0 : vbdev_forward_io_simple_cb(struct spdk_bdev_io *bdev_io, bool success, void *opaque)
     265             : {
     266           0 :         struct vbdev_forward_io_simple_ctx *ctx = opaque;
     267           0 :         ocf_forward_token_t token = ctx->token;
     268             : 
     269           0 :         assert(token);
     270             : 
     271           0 :         spdk_bdev_free_io(bdev_io);
     272           0 :         spdk_put_io_channel(ctx->ch);
     273           0 :         env_free(ctx);
     274             : 
     275           0 :         ocf_forward_end(token, success ? 0 : -OCF_ERR_IO);
     276           0 : }
     277             : 
     278             : static void
     279           0 : vbdev_forward_io_simple(ocf_volume_t volume, ocf_forward_token_t token,
     280             :                         int dir, uint64_t addr, uint64_t bytes)
     281             : {
     282           0 :         struct vbdev_ocf_base *base =
     283             :                 *((struct vbdev_ocf_base **)
     284           0 :                   ocf_volume_get_priv(volume));
     285           0 :         struct bdev_ocf_data *data = ocf_forward_get_data(token);
     286             :         struct vbdev_forward_io_simple_ctx *ctx;
     287           0 :         int status = -1;
     288             : 
     289           0 :         ctx = env_malloc(sizeof(*ctx), ENV_MEM_NOIO);
     290           0 :         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           0 :         ctx->ch = spdk_bdev_get_io_channel(base->desc);
     298           0 :         if (unlikely(ctx->ch == NULL)) {
     299           0 :                 env_free(ctx);
     300           0 :                 ocf_forward_end(token, -EFAULT);
     301           0 :                 return;
     302             :         }
     303             : 
     304           0 :         ctx->token = token;
     305             : 
     306           0 :         if (dir == OCF_READ) {
     307           0 :                 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           0 :         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           0 : vbdev_ocf_volume_init(void)
     344             : {
     345           0 :         return ocf_ctx_register_volume_type(vbdev_ocf_ctx, SPDK_OBJECT, &vbdev_volume_props);
     346             : }
     347             : 
     348             : void
     349           0 : vbdev_ocf_volume_cleanup(void)
     350             : {
     351           0 :         ocf_ctx_unregister_volume_type(vbdev_ocf_ctx, SPDK_OBJECT);
     352           0 : }
     353             : 
     354           0 : SPDK_LOG_REGISTER_COMPONENT(vbdev_ocf_volume)

Generated by: LCOV version 1.15