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 188 0.0 %
Date: 2024-11-05 10:06:02 Functions: 0 19 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 : vbdev_ocf_volume_io_set_data(struct ocf_io *io, ctx_data_t *data,
      56             :                              uint32_t offset)
      57             : {
      58           0 :         struct ocf_io_ctx *io_ctx = ocf_get_io_ctx(io);
      59             : 
      60           0 :         io_ctx->offset = offset;
      61           0 :         io_ctx->data = data;
      62             : 
      63           0 :         assert(io_ctx->data != NULL);
      64           0 :         if (io_ctx->data->iovs && offset >= io_ctx->data->size) {
      65           0 :                 return -ENOBUFS;
      66             :         }
      67             : 
      68           0 :         return 0;
      69             : }
      70             : 
      71             : static ctx_data_t *
      72           0 : vbdev_ocf_volume_io_get_data(struct ocf_io *io)
      73             : {
      74           0 :         return ocf_get_io_ctx(io)->data;
      75             : }
      76             : 
      77             : static void
      78           0 : vbdev_ocf_volume_io_get(struct ocf_io *io)
      79             : {
      80           0 :         struct ocf_io_ctx *io_ctx = ocf_get_io_ctx(io);
      81             : 
      82           0 :         io_ctx->ref++;
      83           0 : }
      84             : 
      85             : static void
      86           0 : vbdev_ocf_volume_io_put(struct ocf_io *io)
      87             : {
      88           0 :         struct ocf_io_ctx *io_ctx = ocf_get_io_ctx(io);
      89             : 
      90           0 :         if (--io_ctx->ref) {
      91           0 :                 return;
      92             :         }
      93             : }
      94             : 
      95             : static int
      96           0 : get_starting_vec(struct iovec *iovs, int iovcnt, int *offset)
      97             : {
      98             :         int i;
      99             :         size_t off;
     100             : 
     101           0 :         off = *offset;
     102             : 
     103           0 :         for (i = 0; i < iovcnt; i++) {
     104           0 :                 if (off < iovs[i].iov_len) {
     105           0 :                         *offset = off;
     106           0 :                         return i;
     107             :                 }
     108           0 :                 off -= iovs[i].iov_len;
     109             :         }
     110             : 
     111           0 :         return -1;
     112             : }
     113             : 
     114             : static void
     115           0 : initialize_cpy_vector(struct iovec *cpy_vec, int cpy_vec_len, struct iovec *orig_vec,
     116             :                       int orig_vec_len,
     117             :                       size_t offset, size_t bytes)
     118             : {
     119             :         void *curr_base;
     120             :         int len, i;
     121             : 
     122           0 :         i = 0;
     123             : 
     124           0 :         while (bytes > 0) {
     125           0 :                 curr_base = orig_vec[i].iov_base + offset;
     126           0 :                 len = MIN(bytes, orig_vec[i].iov_len - offset);
     127             : 
     128           0 :                 cpy_vec[i].iov_base = curr_base;
     129           0 :                 cpy_vec[i].iov_len = len;
     130             : 
     131           0 :                 bytes -= len;
     132           0 :                 offset = 0;
     133           0 :                 i++;
     134             :         }
     135           0 : }
     136             : 
     137             : static void
     138           0 : vbdev_ocf_volume_submit_io_cb(struct spdk_bdev_io *bdev_io, bool success, void *opaque)
     139             : {
     140             :         struct ocf_io *io;
     141             :         struct ocf_io_ctx *io_ctx;
     142             : 
     143           0 :         assert(opaque);
     144             : 
     145           0 :         io = opaque;
     146           0 :         io_ctx = ocf_get_io_ctx(io);
     147           0 :         assert(io_ctx != NULL);
     148             : 
     149           0 :         if (!success) {
     150           0 :                 io_ctx->error = io_ctx->error ? : -OCF_ERR_IO;
     151             :         }
     152             : 
     153           0 :         if (io_ctx->iovs_allocated && bdev_io != NULL) {
     154           0 :                 env_free(bdev_io->u.bdev.iovs);
     155             :         }
     156             : 
     157           0 :         if (io_ctx->error) {
     158           0 :                 SPDK_DEBUGLOG(vbdev_ocf_volume,
     159             :                               "base returned error on io submission: %d\n", io_ctx->error);
     160             :         }
     161             : 
     162           0 :         if (io->io_queue == NULL && io_ctx->ch != NULL) {
     163           0 :                 spdk_put_io_channel(io_ctx->ch);
     164             :         }
     165             : 
     166           0 :         vbdev_ocf_volume_io_put(io);
     167           0 :         if (bdev_io) {
     168           0 :                 spdk_bdev_free_io(bdev_io);
     169             :         }
     170             : 
     171           0 :         if (--io_ctx->rq_cnt == 0) {
     172           0 :                 io->end(io, io_ctx->error);
     173             :         }
     174           0 : }
     175             : 
     176             : static int
     177           0 : prepare_submit(struct ocf_io *io)
     178             : {
     179           0 :         struct ocf_io_ctx *io_ctx = ocf_get_io_ctx(io);
     180             :         struct vbdev_ocf_qctx *qctx;
     181             :         struct vbdev_ocf_base *base;
     182           0 :         ocf_queue_t q = io->io_queue;
     183             :         ocf_cache_t cache;
     184             :         struct vbdev_ocf_cache_ctx *cctx;
     185           0 :         int rc = 0;
     186             : 
     187           0 :         io_ctx->rq_cnt++;
     188           0 :         if (io_ctx->rq_cnt != 1) {
     189           0 :                 return 0;
     190             :         }
     191             : 
     192           0 :         vbdev_ocf_volume_io_get(io);
     193           0 :         base = *((struct vbdev_ocf_base **)ocf_volume_get_priv(ocf_io_get_volume(io)));
     194             : 
     195           0 :         if (io->io_queue == NULL) {
     196             :                 /* In case IO is initiated by OCF, queue is unknown
     197             :                  * so we have to get io channel ourselves */
     198           0 :                 io_ctx->ch = spdk_bdev_get_io_channel(base->desc);
     199           0 :                 if (io_ctx->ch == NULL) {
     200           0 :                         return -EPERM;
     201             :                 }
     202           0 :                 return 0;
     203             :         }
     204             : 
     205           0 :         cache = ocf_queue_get_cache(q);
     206           0 :         cctx = ocf_cache_get_priv(cache);
     207           0 :         if (cctx == NULL) {
     208           0 :                 return -EFAULT;
     209             :         }
     210             : 
     211           0 :         if (q == cctx->mngt_queue) {
     212           0 :                 io_ctx->ch = base->management_channel;
     213           0 :                 return 0;
     214             :         }
     215             : 
     216           0 :         qctx = ocf_queue_get_priv(q);
     217           0 :         if (qctx == NULL) {
     218           0 :                 return -EFAULT;
     219             :         }
     220             : 
     221           0 :         if (base->is_cache) {
     222           0 :                 io_ctx->ch = qctx->cache_ch;
     223             :         } else {
     224           0 :                 io_ctx->ch = qctx->core_ch;
     225             :         }
     226             : 
     227           0 :         return rc;
     228             : }
     229             : 
     230             : static void
     231           0 : vbdev_ocf_volume_submit_flush(struct ocf_io *io)
     232             : {
     233           0 :         struct vbdev_ocf_base *base =
     234             :                 *((struct vbdev_ocf_base **)
     235           0 :                   ocf_volume_get_priv(ocf_io_get_volume(io)));
     236           0 :         struct ocf_io_ctx *io_ctx = ocf_get_io_ctx(io);
     237             :         int status;
     238             : 
     239           0 :         status = prepare_submit(io);
     240           0 :         if (status) {
     241           0 :                 SPDK_ERRLOG("Preparing io failed with status=%d\n", status);
     242           0 :                 vbdev_ocf_volume_submit_io_cb(NULL, false, io);
     243           0 :                 return;
     244             :         }
     245             : 
     246           0 :         status = spdk_bdev_flush(
     247             :                          base->desc, io_ctx->ch,
     248           0 :                          io->addr, io->bytes,
     249             :                          vbdev_ocf_volume_submit_io_cb, io);
     250           0 :         if (status) {
     251             :                 /* Since callback is not called, we need to do it manually to free io structures */
     252           0 :                 SPDK_ERRLOG("Submission failed with status=%d\n", status);
     253           0 :                 vbdev_ocf_volume_submit_io_cb(NULL, false, io);
     254             :         }
     255             : }
     256             : 
     257             : static void
     258           0 : vbdev_ocf_volume_submit_io(struct ocf_io *io)
     259             : {
     260           0 :         struct vbdev_ocf_base *base =
     261             :                 *((struct vbdev_ocf_base **)
     262           0 :                   ocf_volume_get_priv(ocf_io_get_volume(io)));
     263           0 :         struct ocf_io_ctx *io_ctx = ocf_get_io_ctx(io);
     264             :         struct iovec *iovs;
     265           0 :         int iovcnt, status = 0, i, offset;
     266             :         uint64_t addr, len;
     267             : 
     268           0 :         if (io->flags == OCF_WRITE_FLUSH) {
     269           0 :                 vbdev_ocf_volume_submit_flush(io);
     270           0 :                 return;
     271             :         }
     272             : 
     273           0 :         status = prepare_submit(io);
     274           0 :         if (status) {
     275           0 :                 SPDK_ERRLOG("Preparing io failed with status=%d\n", status);
     276           0 :                 vbdev_ocf_volume_submit_io_cb(NULL, false, io);
     277           0 :                 return;
     278             :         }
     279             : 
     280             :         /* IO fields */
     281           0 :         addr = io->addr;
     282           0 :         len = io->bytes;
     283           0 :         offset = io_ctx->offset;
     284             : 
     285           0 :         if (len < io_ctx->data->size) {
     286           0 :                 if (io_ctx->data->iovcnt == 1) {
     287           0 :                         if (io->dir == OCF_READ) {
     288           0 :                                 status = spdk_bdev_read(base->desc, io_ctx->ch,
     289           0 :                                                         io_ctx->data->iovs[0].iov_base + offset, addr, len,
     290             :                                                         vbdev_ocf_volume_submit_io_cb, io);
     291           0 :                         } else if (io->dir == OCF_WRITE) {
     292           0 :                                 status = spdk_bdev_write(base->desc, io_ctx->ch,
     293           0 :                                                          io_ctx->data->iovs[0].iov_base + offset, addr, len,
     294             :                                                          vbdev_ocf_volume_submit_io_cb, io);
     295             :                         }
     296           0 :                         goto end;
     297             :                 } else {
     298           0 :                         i = get_starting_vec(io_ctx->data->iovs, io_ctx->data->iovcnt, &offset);
     299             : 
     300           0 :                         if (i < 0) {
     301           0 :                                 SPDK_ERRLOG("offset bigger than data size\n");
     302           0 :                                 vbdev_ocf_volume_submit_io_cb(NULL, false, io);
     303           0 :                                 return;
     304             :                         }
     305             : 
     306           0 :                         iovcnt = io_ctx->data->iovcnt - i;
     307             : 
     308           0 :                         io_ctx->iovs_allocated = true;
     309           0 :                         iovs = env_malloc(sizeof(*iovs) * iovcnt, ENV_MEM_NOIO);
     310             : 
     311           0 :                         if (!iovs) {
     312           0 :                                 SPDK_ERRLOG("allocation failed\n");
     313           0 :                                 vbdev_ocf_volume_submit_io_cb(NULL, false, io);
     314           0 :                                 return;
     315             :                         }
     316             : 
     317           0 :                         initialize_cpy_vector(iovs, io_ctx->data->iovcnt, &io_ctx->data->iovs[i],
     318             :                                               iovcnt, offset, len);
     319             :                 }
     320             :         } else {
     321           0 :                 iovs = io_ctx->data->iovs;
     322           0 :                 iovcnt = io_ctx->data->iovcnt;
     323             :         }
     324             : 
     325           0 :         if (io->dir == OCF_READ) {
     326           0 :                 status = spdk_bdev_readv(base->desc, io_ctx->ch,
     327             :                                          iovs, iovcnt, addr, len, vbdev_ocf_volume_submit_io_cb, io);
     328           0 :         } else if (io->dir == OCF_WRITE) {
     329           0 :                 status = spdk_bdev_writev(base->desc, io_ctx->ch,
     330             :                                           iovs, iovcnt, addr, len, vbdev_ocf_volume_submit_io_cb, io);
     331             :         }
     332             : 
     333           0 : end:
     334           0 :         if (status) {
     335           0 :                 if (status == -ENOMEM) {
     336           0 :                         io_ctx->error = -OCF_ERR_NO_MEM;
     337             :                 } else {
     338           0 :                         SPDK_ERRLOG("submission failed with status=%d\n", status);
     339             :                 }
     340             : 
     341             :                 /* Since callback is not called, we need to do it manually to free io structures */
     342           0 :                 vbdev_ocf_volume_submit_io_cb(NULL, false, io);
     343             :         }
     344             : }
     345             : 
     346             : static void
     347           0 : vbdev_ocf_volume_submit_discard(struct ocf_io *io)
     348             : {
     349           0 :         struct vbdev_ocf_base *base =
     350             :                 *((struct vbdev_ocf_base **)
     351           0 :                   ocf_volume_get_priv(ocf_io_get_volume(io)));
     352           0 :         struct ocf_io_ctx *io_ctx = ocf_get_io_ctx(io);
     353           0 :         int status = 0;
     354             : 
     355           0 :         status = prepare_submit(io);
     356           0 :         if (status) {
     357           0 :                 SPDK_ERRLOG("Preparing io failed with status=%d\n", status);
     358           0 :                 vbdev_ocf_volume_submit_io_cb(NULL, false, io);
     359           0 :                 return;
     360             :         }
     361             : 
     362           0 :         status = spdk_bdev_unmap(
     363             :                          base->desc, io_ctx->ch,
     364           0 :                          io->addr, io->bytes,
     365             :                          vbdev_ocf_volume_submit_io_cb, io);
     366           0 :         if (status) {
     367             :                 /* Since callback is not called, we need to do it manually to free io structures */
     368           0 :                 SPDK_ERRLOG("Submission failed with status=%d\n", status);
     369           0 :                 vbdev_ocf_volume_submit_io_cb(NULL, false, io);
     370             :         }
     371             : }
     372             : 
     373             : static void
     374           0 : vbdev_ocf_volume_submit_metadata(struct ocf_io *io)
     375             : {
     376             :         /* Implement with persistent metadata support */
     377           0 : }
     378             : 
     379             : static unsigned int
     380           0 : vbdev_ocf_volume_get_max_io_size(ocf_volume_t volume)
     381             : {
     382           0 :         return 131072;
     383             : }
     384             : 
     385             : static struct ocf_volume_properties vbdev_volume_props = {
     386             :         .name = "SPDK_block_device",
     387             :         .io_priv_size = sizeof(struct ocf_io_ctx),
     388             :         .volume_priv_size = sizeof(struct vbdev_ocf_base *),
     389             :         .caps = {
     390             :                 .atomic_writes = 0 /* to enable need to have ops->submit_metadata */
     391             :         },
     392             :         .ops = {
     393             :                 .open = vbdev_ocf_volume_open,
     394             :                 .close = vbdev_ocf_volume_close,
     395             :                 .get_length = vbdev_ocf_volume_get_length,
     396             :                 .submit_io = vbdev_ocf_volume_submit_io,
     397             :                 .submit_discard = vbdev_ocf_volume_submit_discard,
     398             :                 .submit_flush = vbdev_ocf_volume_submit_flush,
     399             :                 .get_max_io_size = vbdev_ocf_volume_get_max_io_size,
     400             :                 .submit_metadata = vbdev_ocf_volume_submit_metadata,
     401             :         },
     402             :         .io_ops = {
     403             :                 .set_data = vbdev_ocf_volume_io_set_data,
     404             :                 .get_data = vbdev_ocf_volume_io_get_data,
     405             :         },
     406             : };
     407             : 
     408             : int
     409           0 : vbdev_ocf_volume_init(void)
     410             : {
     411           0 :         return ocf_ctx_register_volume_type(vbdev_ocf_ctx, SPDK_OBJECT, &vbdev_volume_props);
     412             : }
     413             : 
     414             : void
     415           0 : vbdev_ocf_volume_cleanup(void)
     416             : {
     417           0 :         ocf_ctx_unregister_volume_type(vbdev_ocf_ctx, SPDK_OBJECT);
     418           0 : }
     419             : 
     420           0 : SPDK_LOG_REGISTER_COMPONENT(vbdev_ocf_volume)

Generated by: LCOV version 1.15