LCOV - code coverage report
Current view: top level - spdk/module/bdev/ocf - volume.c (source / functions) Hit Total Coverage
Test: Combined Lines: 126 188 67.0 %
Date: 2024-07-15 10:11:53 Functions: 16 19 84.2 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 47 94 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                 :        168 : vbdev_ocf_volume_open(ocf_volume_t volume, void *opts)
      20                 :            : {
      21                 :        168 :         struct vbdev_ocf_base **priv = ocf_volume_get_priv(volume);
      22                 :            :         struct vbdev_ocf_base *base;
      23                 :            : 
      24         [ +  + ]:        168 :         if (opts) {
      25                 :        124 :                 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                 :        168 :         *priv = base;
      34                 :            : 
      35                 :        168 :         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                 :    1115550 : vbdev_ocf_volume_get_length(ocf_volume_t volume)
      45                 :            : {
      46                 :    1115550 :         struct vbdev_ocf_base *base = *((struct vbdev_ocf_base **)ocf_volume_get_priv(volume));
      47                 :            :         uint64_t len;
      48                 :            : 
      49                 :    1115550 :         len = base->bdev->blocklen * base->bdev->blockcnt;
      50                 :            : 
      51                 :    1115550 :         return len;
      52                 :            : }
      53                 :            : 
      54                 :            : static int
      55                 :    1350796 : vbdev_ocf_volume_io_set_data(struct ocf_io *io, ctx_data_t *data,
      56                 :            :                              uint32_t offset)
      57                 :            : {
      58                 :    1350796 :         struct ocf_io_ctx *io_ctx = ocf_get_io_ctx(io);
      59                 :            : 
      60                 :    1350796 :         io_ctx->offset = offset;
      61                 :    1350796 :         io_ctx->data = data;
      62                 :            : 
      63         [ -  + ]:    1350796 :         assert(io_ctx->data != NULL);
      64   [ +  +  -  + ]:    1350796 :         if (io_ctx->data->iovs && offset >= io_ctx->data->size) {
      65                 :          0 :                 return -ENOBUFS;
      66                 :            :         }
      67                 :            : 
      68                 :    1350796 :         return 0;
      69                 :            : }
      70                 :            : 
      71                 :            : static ctx_data_t *
      72                 :        124 : vbdev_ocf_volume_io_get_data(struct ocf_io *io)
      73                 :            : {
      74                 :        124 :         return ocf_get_io_ctx(io)->data;
      75                 :            : }
      76                 :            : 
      77                 :            : static void
      78                 :    1744642 : vbdev_ocf_volume_io_get(struct ocf_io *io)
      79                 :            : {
      80                 :    1744642 :         struct ocf_io_ctx *io_ctx = ocf_get_io_ctx(io);
      81                 :            : 
      82                 :    1744642 :         io_ctx->ref++;
      83                 :    1744642 : }
      84                 :            : 
      85                 :            : static void
      86                 :    1744642 : vbdev_ocf_volume_io_put(struct ocf_io *io)
      87                 :            : {
      88                 :    1744642 :         struct ocf_io_ctx *io_ctx = ocf_get_io_ctx(io);
      89                 :            : 
      90         [ -  + ]:    1744642 :         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                 :    1744642 : 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         [ -  + ]:    1744642 :         assert(opaque);
     144                 :            : 
     145                 :    1744642 :         io = opaque;
     146                 :    1744642 :         io_ctx = ocf_get_io_ctx(io);
     147         [ -  + ]:    1744642 :         assert(io_ctx != NULL);
     148                 :            : 
     149         [ -  + ]:    1744642 :         if (!success) {
     150         [ #  # ]:          0 :                 io_ctx->error = io_ctx->error ? : -OCF_ERR_IO;
     151                 :            :         }
     152                 :            : 
     153   [ -  +  -  +  :    1744642 :         if (io_ctx->iovs_allocated && bdev_io != NULL) {
                   -  - ]
     154                 :          0 :                 env_free(bdev_io->u.bdev.iovs);
     155                 :            :         }
     156                 :            : 
     157         [ -  + ]:    1744642 :         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   [ +  +  +  - ]:    1744642 :         if (io->io_queue == NULL && io_ctx->ch != NULL) {
     163                 :        302 :                 spdk_put_io_channel(io_ctx->ch);
     164                 :            :         }
     165                 :            : 
     166                 :    1744642 :         vbdev_ocf_volume_io_put(io);
     167         [ +  - ]:    1744642 :         if (bdev_io) {
     168                 :    1744642 :                 spdk_bdev_free_io(bdev_io);
     169                 :            :         }
     170                 :            : 
     171         [ +  - ]:    1744642 :         if (--io_ctx->rq_cnt == 0) {
     172                 :    1744642 :                 io->end(io, io_ctx->error);
     173                 :            :         }
     174                 :    1744642 : }
     175                 :            : 
     176                 :            : static int
     177                 :    1744642 : prepare_submit(struct ocf_io *io)
     178                 :            : {
     179                 :    1744642 :         struct ocf_io_ctx *io_ctx = ocf_get_io_ctx(io);
     180                 :            :         struct vbdev_ocf_qctx *qctx;
     181                 :            :         struct vbdev_ocf_base *base;
     182                 :    1744642 :         ocf_queue_t q = io->io_queue;
     183                 :            :         ocf_cache_t cache;
     184                 :            :         struct vbdev_ocf_cache_ctx *cctx;
     185                 :    1744642 :         int rc = 0;
     186                 :            : 
     187                 :    1744642 :         io_ctx->rq_cnt++;
     188         [ -  + ]:    1744642 :         if (io_ctx->rq_cnt != 1) {
     189                 :          0 :                 return 0;
     190                 :            :         }
     191                 :            : 
     192                 :    1744642 :         vbdev_ocf_volume_io_get(io);
     193                 :    1744642 :         base = *((struct vbdev_ocf_base **)ocf_volume_get_priv(ocf_io_get_volume(io)));
     194                 :            : 
     195         [ +  + ]:    1744642 :         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                 :        302 :                 io_ctx->ch = spdk_bdev_get_io_channel(base->desc);
     199         [ -  + ]:        302 :                 if (io_ctx->ch == NULL) {
     200                 :          0 :                         return -EPERM;
     201                 :            :                 }
     202                 :        302 :                 return 0;
     203                 :            :         }
     204                 :            : 
     205                 :    1744340 :         cache = ocf_queue_get_cache(q);
     206                 :    1744340 :         cctx = ocf_cache_get_priv(cache);
     207         [ -  + ]:    1744340 :         if (cctx == NULL) {
     208                 :          0 :                 return -EFAULT;
     209                 :            :         }
     210                 :            : 
     211         [ +  + ]:    1744340 :         if (q == cctx->mngt_queue) {
     212                 :      81981 :                 io_ctx->ch = base->management_channel;
     213                 :      81981 :                 return 0;
     214                 :            :         }
     215                 :            : 
     216                 :    1662359 :         qctx = ocf_queue_get_priv(q);
     217         [ -  + ]:    1662359 :         if (qctx == NULL) {
     218                 :          0 :                 return -EFAULT;
     219                 :            :         }
     220                 :            : 
     221   [ -  +  +  + ]:    1662359 :         if (base->is_cache) {
     222                 :     713083 :                 io_ctx->ch = qctx->cache_ch;
     223                 :            :         } else {
     224                 :     949276 :                 io_ctx->ch = qctx->core_ch;
     225                 :            :         }
     226                 :            : 
     227                 :    1662359 :         return rc;
     228                 :            : }
     229                 :            : 
     230                 :            : static void
     231                 :     615670 : vbdev_ocf_volume_submit_flush(struct ocf_io *io)
     232                 :            : {
     233                 :     615670 :         struct vbdev_ocf_base *base =
     234                 :            :                 *((struct vbdev_ocf_base **)
     235                 :     615670 :                   ocf_volume_get_priv(ocf_io_get_volume(io)));
     236                 :     615670 :         struct ocf_io_ctx *io_ctx = ocf_get_io_ctx(io);
     237                 :            :         int status;
     238                 :            : 
     239                 :     615670 :         status = prepare_submit(io);
     240         [ -  + ]:     615670 :         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                 :     615670 :         status = spdk_bdev_flush(
     247                 :            :                          base->desc, io_ctx->ch,
     248                 :     615670 :                          io->addr, io->bytes,
     249                 :            :                          vbdev_ocf_volume_submit_io_cb, io);
     250         [ -  + ]:     615670 :         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                 :    1179500 : vbdev_ocf_volume_submit_io(struct ocf_io *io)
     259                 :            : {
     260                 :    1179500 :         struct vbdev_ocf_base *base =
     261                 :            :                 *((struct vbdev_ocf_base **)
     262                 :    1179500 :                   ocf_volume_get_priv(ocf_io_get_volume(io)));
     263                 :    1179500 :         struct ocf_io_ctx *io_ctx = ocf_get_io_ctx(io);
     264                 :            :         struct iovec *iovs;
     265                 :    1179500 :         int iovcnt, status = 0, i, offset;
     266                 :            :         uint64_t addr, len;
     267                 :            : 
     268         [ +  + ]:    1179500 :         if (io->flags == OCF_WRITE_FLUSH) {
     269                 :     221824 :                 vbdev_ocf_volume_submit_flush(io);
     270                 :     221824 :                 return;
     271                 :            :         }
     272                 :            : 
     273                 :     957676 :         status = prepare_submit(io);
     274         [ -  + ]:     957676 :         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                 :     957676 :         addr = io->addr;
     282                 :     957676 :         len = io->bytes;
     283                 :     957676 :         offset = io_ctx->offset;
     284                 :            : 
     285         [ +  + ]:     957676 :         if (len < io_ctx->data->size) {
     286         [ +  - ]:      68338 :                 if (io_ctx->data->iovcnt == 1) {
     287         [ +  + ]:      68338 :                         if (io->dir == OCF_READ) {
     288                 :      34086 :                                 status = spdk_bdev_read(base->desc, io_ctx->ch,
     289                 :      34086 :                                                         io_ctx->data->iovs[0].iov_base + offset, addr, len,
     290                 :            :                                                         vbdev_ocf_volume_submit_io_cb, io);
     291         [ +  - ]:      34252 :                         } else if (io->dir == OCF_WRITE) {
     292                 :      34252 :                                 status = spdk_bdev_write(base->desc, io_ctx->ch,
     293                 :      34252 :                                                          io_ctx->data->iovs[0].iov_base + offset, addr, len,
     294                 :            :                                                          vbdev_ocf_volume_submit_io_cb, io);
     295                 :            :                         }
     296                 :      68338 :                         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                 :     889338 :                 iovs = io_ctx->data->iovs;
     322                 :     889338 :                 iovcnt = io_ctx->data->iovcnt;
     323                 :            :         }
     324                 :            : 
     325         [ +  + ]:     889338 :         if (io->dir == OCF_READ) {
     326                 :     205031 :                 status = spdk_bdev_readv(base->desc, io_ctx->ch,
     327                 :            :                                          iovs, iovcnt, addr, len, vbdev_ocf_volume_submit_io_cb, io);
     328         [ -  + ]:     684307 :         } else if (io->dir == OCF_WRITE) {
     329                 :     684307 :                 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         [ -  + ]:     957676 :         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                 :     171296 : vbdev_ocf_volume_submit_discard(struct ocf_io *io)
     348                 :            : {
     349                 :     171296 :         struct vbdev_ocf_base *base =
     350                 :            :                 *((struct vbdev_ocf_base **)
     351                 :     171296 :                   ocf_volume_get_priv(ocf_io_get_volume(io)));
     352                 :     171296 :         struct ocf_io_ctx *io_ctx = ocf_get_io_ctx(io);
     353                 :     171296 :         int status = 0;
     354                 :            : 
     355                 :     171296 :         status = prepare_submit(io);
     356         [ -  + ]:     171296 :         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                 :     171296 :         status = spdk_bdev_unmap(
     363                 :            :                          base->desc, io_ctx->ch,
     364                 :     171296 :                          io->addr, io->bytes,
     365                 :            :                          vbdev_ocf_volume_submit_io_cb, io);
     366         [ -  + ]:     171296 :         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                 :     162742 : vbdev_ocf_volume_get_max_io_size(ocf_volume_t volume)
     381                 :            : {
     382                 :     162742 :         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                 :         63 : vbdev_ocf_volume_init(void)
     410                 :            : {
     411                 :         63 :         return ocf_ctx_register_volume_type(vbdev_ocf_ctx, SPDK_OBJECT, &vbdev_volume_props);
     412                 :            : }
     413                 :            : 
     414                 :            : void
     415                 :         63 : vbdev_ocf_volume_cleanup(void)
     416                 :            : {
     417                 :         63 :         ocf_ctx_unregister_volume_type(vbdev_ocf_ctx, SPDK_OBJECT);
     418                 :         63 : }
     419                 :            : 
     420                 :         71 : SPDK_LOG_REGISTER_COMPONENT(vbdev_ocf_volume)

Generated by: LCOV version 1.14