LCOV - code coverage report
Current view: top level - spdk/module/bdev/error - vbdev_error.c (source / functions) Hit Total Coverage
Test: Combined Lines: 186 302 61.6 %
Date: 2024-11-20 08:39:15 Functions: 22 28 78.6 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 84 846 9.9 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (C) 2017 Intel Corporation.
       3                 :            :  *   All rights reserved.
       4                 :            :  */
       5                 :            : 
       6                 :            : /*
       7                 :            :  * This is a module for test purpose which will simulate error cases for bdev.
       8                 :            :  */
       9                 :            : 
      10                 :            : #include "spdk/stdinc.h"
      11                 :            : #include "spdk/rpc.h"
      12                 :            : #include "spdk/util.h"
      13                 :            : #include "spdk/endian.h"
      14                 :            : #include "spdk/nvme_spec.h"
      15                 :            : #include "spdk/string.h"
      16                 :            : 
      17                 :            : #include "spdk/bdev_module.h"
      18                 :            : #include "spdk/log.h"
      19                 :            : 
      20                 :            : #include "vbdev_error.h"
      21                 :            : 
      22                 :            : struct spdk_vbdev_error_config {
      23                 :            :         char *base_bdev;
      24                 :            :         struct spdk_uuid uuid;
      25                 :            :         TAILQ_ENTRY(spdk_vbdev_error_config) tailq;
      26                 :            : };
      27                 :            : 
      28                 :            : static TAILQ_HEAD(, spdk_vbdev_error_config) g_error_config
      29                 :            :         = TAILQ_HEAD_INITIALIZER(g_error_config);
      30                 :            : 
      31                 :            : struct vbdev_error_info {
      32                 :            :         uint32_t                        error_type;
      33                 :            :         uint32_t                        error_num;
      34                 :            :         uint64_t                        error_qd;
      35                 :            :         uint64_t                        corrupt_offset;
      36                 :            :         uint8_t                         corrupt_value;
      37                 :            : };
      38                 :            : 
      39                 :            : struct error_io {
      40                 :            :         enum vbdev_error_type error_type;
      41                 :            :         TAILQ_ENTRY(error_io) link;
      42                 :            : };
      43                 :            : 
      44                 :            : /* Context for each error bdev */
      45                 :            : struct error_disk {
      46                 :            :         struct spdk_bdev_part           part;
      47                 :            :         struct vbdev_error_info         error_vector[SPDK_BDEV_IO_TYPE_RESET];
      48                 :            : };
      49                 :            : 
      50                 :            : struct error_channel {
      51                 :            :         struct spdk_bdev_part_channel   part_ch;
      52                 :            :         uint64_t                        io_inflight;
      53                 :            :         TAILQ_HEAD(, error_io)          pending_ios;
      54                 :            : };
      55                 :            : 
      56                 :            : static pthread_mutex_t g_vbdev_error_mutex = PTHREAD_MUTEX_INITIALIZER;
      57                 :            : static SPDK_BDEV_PART_TAILQ g_error_disks = TAILQ_HEAD_INITIALIZER(g_error_disks);
      58                 :            : 
      59                 :            : static int vbdev_error_init(void);
      60                 :            : static void vbdev_error_fini(void);
      61                 :            : 
      62                 :            : static void vbdev_error_examine(struct spdk_bdev *bdev);
      63                 :            : static int vbdev_error_config_json(struct spdk_json_write_ctx *w);
      64                 :            : 
      65                 :            : static int vbdev_error_config_add(const char *base_bdev_name, const struct spdk_uuid *uuid);
      66                 :            : static int vbdev_error_config_remove(const char *base_bdev_name);
      67                 :            : 
      68                 :            : static int
      69                 :       1939 : vbdev_error_get_ctx_size(void)
      70                 :            : {
      71                 :       1939 :         return sizeof(struct error_io);
      72                 :            : }
      73                 :            : 
      74                 :            : static struct spdk_bdev_module error_if = {
      75                 :            :         .name = "error",
      76                 :            :         .module_init = vbdev_error_init,
      77                 :            :         .module_fini = vbdev_error_fini,
      78                 :            :         .examine_config = vbdev_error_examine,
      79                 :            :         .config_json = vbdev_error_config_json,
      80                 :            :         .get_ctx_size = vbdev_error_get_ctx_size,
      81                 :            : 
      82                 :            : };
      83                 :            : 
      84                 :       2124 : SPDK_BDEV_MODULE_REGISTER(error, &error_if)
      85                 :            : 
      86                 :            : static void
      87                 :          0 : dummy_bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *ctx)
      88                 :            : {
      89                 :          0 : }
      90                 :            : 
      91                 :            : int
      92                 :         29 : vbdev_error_inject_error(char *name, const struct vbdev_error_inject_opts *opts)
      93                 :            : {
      94                 :         24 :         struct spdk_bdev_desc *desc;
      95                 :            :         struct spdk_bdev *bdev;
      96                 :            :         struct spdk_bdev_part *part;
      97                 :         29 :         struct error_disk *error_disk = NULL;
      98                 :            :         uint32_t i;
      99                 :         29 :         int rc = 0;
     100                 :            : 
     101   [ +  +  #  #  :         29 :         if (opts->error_type == VBDEV_IO_CORRUPT_DATA) {
                   #  # ]
     102   [ #  #  #  #  :          0 :                 if (opts->corrupt_value == 0) {
                   #  # ]
     103                 :            :                         /* If corrupt_value is 0, XOR cannot cause data corruption. */
     104                 :          0 :                         SPDK_ERRLOG("corrupt_value should be non-zero.\n");
     105                 :          0 :                         return -EINVAL;
     106                 :            :                 }
     107                 :          0 :         }
     108                 :            : 
     109         [ -  + ]:         29 :         pthread_mutex_lock(&g_vbdev_error_mutex);
     110                 :            : 
     111                 :         29 :         rc = spdk_bdev_open_ext(name, false, dummy_bdev_event_cb, NULL, &desc);
     112         [ -  + ]:         29 :         if (rc != 0) {
     113                 :          0 :                 SPDK_ERRLOG("Could not open ErrorInjection bdev %s\n", name);
     114         [ #  # ]:          0 :                 pthread_mutex_unlock(&g_vbdev_error_mutex);
     115                 :          0 :                 return rc;
     116                 :            :         }
     117                 :            : 
     118                 :         29 :         bdev = spdk_bdev_desc_get_bdev(desc);
     119                 :            : 
     120   [ +  +  #  #  :         29 :         TAILQ_FOREACH(part, &g_error_disks, tailq) {
             #  #  #  # ]
     121         [ +  + ]:         29 :                 if (bdev == spdk_bdev_part_get_bdev(part)) {
     122                 :         29 :                         error_disk = (struct error_disk *)part;
     123                 :         29 :                         break;
     124                 :            :                 }
     125                 :          0 :         }
     126                 :            : 
     127         [ +  + ]:         29 :         if (error_disk == NULL) {
     128                 :          0 :                 SPDK_ERRLOG("Could not find ErrorInjection bdev %s\n", name);
     129                 :          0 :                 rc = -ENODEV;
     130                 :          0 :                 goto exit;
     131                 :            :         }
     132                 :            : 
     133   [ +  +  #  #  :         31 :         if (0xffffffff == opts->io_type) {
                   #  # ]
     134         [ +  + ]:         60 :                 for (i = 0; i < SPDK_COUNTOF(error_disk->error_vector); i++) {
     135   [ #  #  #  #  :         50 :                         error_disk->error_vector[i].error_type = opts->error_type;
          #  #  #  #  #  
                #  #  # ]
     136   [ #  #  #  #  :         50 :                         error_disk->error_vector[i].error_num = opts->error_num;
          #  #  #  #  #  
                #  #  # ]
     137   [ #  #  #  #  :         50 :                         error_disk->error_vector[i].error_qd = opts->error_qd;
          #  #  #  #  #  
                #  #  # ]
     138   [ #  #  #  #  :         50 :                         error_disk->error_vector[i].corrupt_offset = opts->corrupt_offset;
          #  #  #  #  #  
                #  #  # ]
     139   [ #  #  #  #  :         50 :                         error_disk->error_vector[i].corrupt_value = opts->corrupt_value;
          #  #  #  #  #  
                #  #  # ]
     140                 :         10 :                 }
     141   [ -  +  #  #  :         21 :         } else if (0 == opts->io_type) {
                   #  # ]
     142         [ #  # ]:          0 :                 for (i = 0; i < SPDK_COUNTOF(error_disk->error_vector); i++) {
     143   [ #  #  #  #  :          0 :                         error_disk->error_vector[i].error_num = 0;
             #  #  #  # ]
     144                 :          0 :                 }
     145                 :          0 :         } else {
     146   [ #  #  #  #  :         19 :                 error_disk->error_vector[opts->io_type].error_type = opts->error_type;
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     147   [ #  #  #  #  :         19 :                 error_disk->error_vector[opts->io_type].error_num = opts->error_num;
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     148   [ #  #  #  #  :         19 :                 error_disk->error_vector[opts->io_type].error_qd = opts->error_qd;
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     149   [ #  #  #  #  :         19 :                 error_disk->error_vector[opts->io_type].corrupt_offset = opts->corrupt_offset;
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     150   [ #  #  #  #  :         19 :                 error_disk->error_vector[opts->io_type].corrupt_value = opts->corrupt_value;
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     151                 :            :         }
     152                 :            : 
     153                 :         27 : exit:
     154                 :         29 :         spdk_bdev_close(desc);
     155         [ -  + ]:         29 :         pthread_mutex_unlock(&g_vbdev_error_mutex);
     156                 :         29 :         return rc;
     157                 :          2 : }
     158                 :            : 
     159                 :            : static void
     160                 :          0 : vbdev_error_ch_abort_ios(struct spdk_io_channel_iter *i)
     161                 :            : {
     162                 :          0 :         struct error_channel *ch = spdk_io_channel_get_ctx(spdk_io_channel_iter_get_channel(i));
     163                 :            :         struct error_io *error_io, *tmp;
     164                 :            : 
     165   [ #  #  #  #  :          0 :         TAILQ_FOREACH_SAFE(error_io, &ch->pending_ios, link, tmp) {
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     166   [ #  #  #  #  :          0 :                 TAILQ_REMOVE(&ch->pending_ios, error_io, link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
     167                 :          0 :                 spdk_bdev_io_complete(spdk_bdev_io_from_ctx(error_io), SPDK_BDEV_IO_STATUS_ABORTED);
     168                 :          0 :         }
     169                 :            : 
     170                 :          0 :         spdk_for_each_channel_continue(i, 0);
     171                 :          0 : }
     172                 :            : 
     173                 :            : static void
     174                 :          0 : vbdev_error_ch_abort_ios_done(struct spdk_io_channel_iter *i, int status)
     175                 :            : {
     176                 :          0 :         struct spdk_bdev_io *reset_io = spdk_io_channel_iter_get_ctx(i);
     177                 :            : 
     178         [ #  # ]:          0 :         if (status != 0) {
     179   [ #  #  #  #  :          0 :                 SPDK_ERRLOG("Failed to abort pending I/Os on bdev %s, status = %d\n",
             #  #  #  # ]
     180                 :            :                             reset_io->bdev->name, status);
     181                 :          0 :                 spdk_bdev_io_complete(reset_io, SPDK_BDEV_IO_STATUS_FAILED);
     182                 :          0 :         } else {
     183                 :          0 :                 spdk_bdev_io_complete(reset_io, SPDK_BDEV_IO_STATUS_SUCCESS);
     184                 :            :         }
     185                 :          0 : }
     186                 :            : 
     187                 :            : static void
     188                 :          0 : vbdev_error_reset(struct error_disk *error_disk, struct spdk_bdev_io *bdev_io)
     189                 :            : {
     190         [ #  # ]:          0 :         spdk_for_each_channel(&error_disk->part, vbdev_error_ch_abort_ios, bdev_io,
     191                 :            :                               vbdev_error_ch_abort_ios_done);
     192                 :          0 : }
     193                 :            : 
     194                 :            : static uint32_t
     195                 :    1621345 : vbdev_error_get_error_type(struct error_disk *error_disk, struct error_channel *ch,
     196                 :            :                            uint32_t io_type)
     197                 :            : {
     198                 :     937509 :         uint32_t error_num;
     199                 :            :         struct vbdev_error_info *error_info;
     200                 :            : 
     201         [ +  - ]:    1621345 :         switch (io_type) {
     202                 :    1255168 :         case SPDK_BDEV_IO_TYPE_READ:
     203                 :            :         case SPDK_BDEV_IO_TYPE_WRITE:
     204                 :            :         case SPDK_BDEV_IO_TYPE_UNMAP:
     205                 :            :         case SPDK_BDEV_IO_TYPE_FLUSH:
     206                 :    1621345 :                 break;
     207                 :          0 :         default:
     208                 :          0 :                 return VBDEV_IO_NO_ERROR;
     209                 :            :         }
     210                 :            : 
     211   [ #  #  #  # ]:    1621345 :         error_info = &error_disk->error_vector[io_type];
     212                 :            : 
     213   [ +  +  #  #  :    1621345 :         if (ch->io_inflight < error_info->error_qd) {
          #  #  #  #  #  
                      # ]
     214                 :     207917 :                 return VBDEV_IO_NO_ERROR;
     215                 :            :         }
     216                 :            : 
     217   [ #  #  #  # ]:    1413428 :         error_num = error_info->error_num;
     218                 :     366177 :         do {
     219         [ +  + ]:    1413428 :                 if (error_num == 0) {
     220                 :    1413355 :                         return VBDEV_IO_NO_ERROR;
     221                 :            :                 }
     222   [ +  +  +  -  :         73 :         } while (!__atomic_compare_exchange_n(&error_info->error_num,
          +  -  #  #  #  
                      # ]
     223         [ -  + ]:         73 :                                               &error_num, error_num - 1,
     224                 :            :                                               false, __ATOMIC_RELAXED, __ATOMIC_RELAXED));
     225                 :            : 
     226   [ #  #  #  # ]:         73 :         return error_info->error_type;
     227                 :     366177 : }
     228                 :            : 
     229                 :            : static void
     230                 :          0 : vbdev_error_corrupt_io_data(struct spdk_bdev_io *bdev_io, uint64_t corrupt_offset,
     231                 :            :                             uint8_t corrupt_value)
     232                 :            : {
     233                 :            :         uint8_t *buf;
     234                 :            :         int i;
     235                 :            : 
     236   [ #  #  #  #  :          0 :         if (bdev_io->u.bdev.iovs == NULL || bdev_io->u.bdev.iovs[0].iov_base == NULL) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     237                 :          0 :                 return;
     238                 :            :         }
     239                 :            : 
     240   [ #  #  #  #  :          0 :         for (i = 0; i < bdev_io->u.bdev.iovcnt; i++) {
          #  #  #  #  #  
                #  #  # ]
     241   [ #  #  #  #  :          0 :                 if (bdev_io->u.bdev.iovs[i].iov_len > corrupt_offset) {
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     242   [ #  #  #  #  :          0 :                         buf = (uint8_t *)bdev_io->u.bdev.iovs[i].iov_base;
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     243                 :            : 
     244   [ #  #  #  # ]:          0 :                         buf[corrupt_offset] ^= corrupt_value;
     245                 :          0 :                         break;
     246                 :            :                 }
     247                 :            : 
     248   [ #  #  #  #  :          0 :                 corrupt_offset -= bdev_io->u.bdev.iovs[i].iov_len;
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     249                 :          0 :         }
     250                 :          0 : }
     251                 :            : 
     252                 :            : static void
     253                 :    1621272 : vbdev_error_complete_request(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
     254                 :            : {
     255         [ #  # ]:    1621272 :         struct error_io *error_io = (struct error_io *)bdev_io->driver_ctx;
     256         [ +  - ]:    1621272 :         int status = success ? SPDK_BDEV_IO_STATUS_SUCCESS : SPDK_BDEV_IO_STATUS_FAILED;
     257   [ #  #  #  #  :    1621272 :         struct error_disk *error_disk = bdev_io->bdev->ctxt;
             #  #  #  # ]
     258                 :    1621272 :         struct error_channel *ch = spdk_io_channel_get_ctx(spdk_bdev_io_get_io_channel(bdev_io));
     259                 :            : 
     260   [ +  +  #  #  :    1621272 :         assert(ch->io_inflight > 0);
             #  #  #  # ]
     261         [ #  # ]:    1621272 :         ch->io_inflight--;
     262                 :            : 
     263   [ +  -  +  +  :    1621272 :         if (success && bdev_io->type == SPDK_BDEV_IO_TYPE_READ) {
          #  #  #  #  #  
                      # ]
     264   [ +  +  #  #  :     938275 :                 if (error_io->error_type == VBDEV_IO_CORRUPT_DATA) {
                   #  # ]
     265                 :          0 :                         vbdev_error_corrupt_io_data(bdev_io,
     266   [ #  #  #  #  :          0 :                                                     error_disk->error_vector[bdev_io->type].corrupt_offset,
          #  #  #  #  #  
                #  #  # ]
     267   [ #  #  #  #  :          0 :                                                     error_disk->error_vector[bdev_io->type].corrupt_value);
          #  #  #  #  #  
                #  #  # ]
     268                 :          0 :                 }
     269                 :     366167 :         }
     270                 :            : 
     271                 :    1621272 :         spdk_bdev_io_complete(bdev_io, status);
     272                 :    1621272 : }
     273                 :            : 
     274                 :            : static void
     275                 :    1621345 : vbdev_error_submit_request(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_io)
     276                 :            : {
     277         [ #  # ]:    1621345 :         struct error_io *error_io = (struct error_io *)bdev_io->driver_ctx;
     278                 :    1621345 :         struct error_channel *ch = spdk_io_channel_get_ctx(_ch);
     279   [ #  #  #  #  :    1621345 :         struct error_disk *error_disk = bdev_io->bdev->ctxt;
             #  #  #  # ]
     280                 :            :         int rc;
     281                 :            : 
     282   [ -  +  #  #  :    1621345 :         if (bdev_io->type == SPDK_BDEV_IO_TYPE_RESET) {
                   #  # ]
     283                 :          0 :                 vbdev_error_reset(error_disk, bdev_io);
     284                 :          0 :                 return;
     285                 :            :         }
     286                 :            : 
     287   [ #  #  #  #  :    1621345 :         error_io->error_type = vbdev_error_get_error_type(error_disk, ch, bdev_io->type);
             #  #  #  # ]
     288                 :            : 
     289   [ +  +  +  +  :    1621345 :         switch (error_io->error_type) {
          +  -  #  #  #  
                      # ]
     290                 :         58 :         case VBDEV_IO_FAILURE:
     291                 :         68 :                 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
     292                 :         68 :                 break;
     293                 :          5 :         case VBDEV_IO_NOMEM:
     294                 :          5 :                 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_NOMEM);
     295                 :          5 :                 break;
     296                 :          0 :         case VBDEV_IO_PENDING:
     297   [ #  #  #  #  :          0 :                 TAILQ_INSERT_TAIL(&ch->pending_ios, error_io, link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     298                 :          0 :                 break;
     299                 :          0 :         case VBDEV_IO_CORRUPT_DATA:
     300   [ #  #  #  #  :          0 :                 if (bdev_io->type == SPDK_BDEV_IO_TYPE_WRITE) {
                   #  # ]
     301                 :          0 :                         vbdev_error_corrupt_io_data(bdev_io,
     302   [ #  #  #  #  :          0 :                                                     error_disk->error_vector[bdev_io->type].corrupt_offset,
          #  #  #  #  #  
                #  #  # ]
     303   [ #  #  #  #  :          0 :                                                     error_disk->error_vector[bdev_io->type].corrupt_value);
          #  #  #  #  #  
                #  #  # ]
     304                 :          0 :                 }
     305                 :            :         /* fallthrough */
     306                 :            :         case VBDEV_IO_NO_ERROR:
     307         [ #  # ]:    1621272 :                 ch->io_inflight++;
     308         [ #  # ]:    1621272 :                 rc = spdk_bdev_part_submit_request_ext(&ch->part_ch, bdev_io,
     309                 :            :                                                        vbdev_error_complete_request);
     310                 :            : 
     311         [ +  + ]:    1621272 :                 if (rc) {
     312                 :          0 :                         SPDK_ERRLOG("bdev_error: submit request failed, rc=%d\n", rc);
     313                 :          0 :                         spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
     314         [ #  # ]:          0 :                         ch->io_inflight--;
     315                 :          0 :                 }
     316                 :    1621272 :                 break;
     317                 :          0 :         default:
     318         [ #  # ]:          0 :                 assert(false);
     319                 :            :                 break;
     320                 :            :         }
     321                 :     366177 : }
     322                 :            : 
     323                 :            : static int
     324                 :         71 : vbdev_error_destruct(void *ctx)
     325                 :            : {
     326                 :         71 :         struct error_disk *error_disk = ctx;
     327         [ #  # ]:         71 :         struct spdk_bdev *base_bdev = spdk_bdev_part_get_base_bdev(&error_disk->part);
     328                 :            :         int rc;
     329                 :            : 
     330   [ #  #  #  # ]:         71 :         rc = vbdev_error_config_remove(base_bdev->name);
     331         [ -  + ]:         71 :         if (rc != 0) {
     332                 :          0 :                 SPDK_ERRLOG("vbdev_error_config_remove() failed\n");
     333                 :          0 :         }
     334                 :            : 
     335         [ #  # ]:         71 :         return spdk_bdev_part_free(&error_disk->part);
     336                 :            : }
     337                 :            : 
     338                 :            : static int
     339                 :       1816 : vbdev_error_dump_info_json(void *ctx, struct spdk_json_write_ctx *w)
     340                 :            : {
     341                 :       1816 :         struct error_disk *error_disk = ctx;
     342         [ #  # ]:       1816 :         struct spdk_bdev *base_bdev = spdk_bdev_part_get_base_bdev(&error_disk->part);
     343                 :            : 
     344                 :       1816 :         spdk_json_write_named_object_begin(w, "error_disk");
     345                 :            : 
     346   [ #  #  #  # ]:       1816 :         spdk_json_write_named_string(w, "base_bdev", base_bdev->name);
     347                 :            : 
     348                 :       1816 :         spdk_json_write_object_end(w);
     349                 :            : 
     350                 :       1816 :         return 0;
     351                 :            : }
     352                 :            : 
     353                 :            : static void
     354                 :          8 : vbdev_error_write_config_json(struct spdk_bdev *bdev, struct spdk_json_write_ctx *w)
     355                 :            : {
     356                 :            :         /* No config per bdev. */
     357                 :          8 : }
     358                 :            : 
     359                 :            : 
     360                 :            : static struct spdk_bdev_fn_table vbdev_error_fn_table = {
     361                 :            :         .destruct               = vbdev_error_destruct,
     362                 :            :         .submit_request         = vbdev_error_submit_request,
     363                 :            :         .dump_info_json         = vbdev_error_dump_info_json,
     364                 :            :         .write_config_json      = vbdev_error_write_config_json
     365                 :            : };
     366                 :            : 
     367                 :            : static void
     368                 :          0 : vbdev_error_base_bdev_hotremove_cb(void *_part_base)
     369                 :            : {
     370                 :          0 :         struct spdk_bdev_part_base *part_base = _part_base;
     371                 :            : 
     372                 :          0 :         spdk_bdev_part_base_hotremove(part_base, &g_error_disks);
     373                 :          0 : }
     374                 :            : 
     375                 :            : static int
     376                 :        245 : vbdev_error_ch_create_cb(void *io_device, void *ctx_buf)
     377                 :            : {
     378                 :        245 :         struct error_channel *ch = ctx_buf;
     379                 :            : 
     380   [ #  #  #  # ]:        245 :         ch->io_inflight = 0;
     381   [ #  #  #  #  :        245 :         TAILQ_INIT(&ch->pending_ios);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     382                 :            : 
     383                 :        245 :         return 0;
     384                 :            : }
     385                 :            : 
     386                 :            : static void
     387                 :        245 : vbdev_error_ch_destroy_cb(void *io_device, void *ctx_buf)
     388                 :            : {
     389                 :        245 : }
     390                 :            : 
     391                 :            : static int
     392                 :         75 : _vbdev_error_create(const char *base_bdev_name, const struct spdk_uuid *uuid)
     393                 :            : {
     394                 :         75 :         struct spdk_bdev_part_base *base = NULL;
     395                 :         75 :         struct error_disk *disk = NULL;
     396                 :            :         struct spdk_bdev *base_bdev, *bdev;
     397                 :            :         char *name;
     398                 :            :         int rc;
     399                 :            : 
     400                 :         75 :         rc = spdk_bdev_part_base_construct_ext(base_bdev_name,
     401                 :            :                                                vbdev_error_base_bdev_hotremove_cb,
     402                 :            :                                                &error_if, &vbdev_error_fn_table, &g_error_disks,
     403                 :            :                                                NULL, NULL, sizeof(struct error_channel),
     404                 :            :                                                vbdev_error_ch_create_cb, vbdev_error_ch_destroy_cb,
     405                 :            :                                                &base);
     406         [ +  + ]:         75 :         if (rc != 0) {
     407         [ -  + ]:          4 :                 if (rc != -ENODEV) {
     408                 :          0 :                         SPDK_ERRLOG("could not construct part base for bdev %s\n", base_bdev_name);
     409                 :          0 :                 }
     410                 :          4 :                 return rc;
     411                 :            :         }
     412                 :            : 
     413                 :         71 :         base_bdev = spdk_bdev_part_base_get_bdev(base);
     414                 :            : 
     415                 :         71 :         disk = calloc(1, sizeof(*disk));
     416         [ +  + ]:         71 :         if (!disk) {
     417                 :          0 :                 SPDK_ERRLOG("Memory allocation failure\n");
     418                 :          0 :                 spdk_bdev_part_base_free(base);
     419                 :          0 :                 return -ENOMEM;
     420                 :            :         }
     421                 :            : 
     422                 :         71 :         name = spdk_sprintf_alloc("EE_%s", base_bdev_name);
     423         [ +  + ]:         71 :         if (!name) {
     424                 :          0 :                 SPDK_ERRLOG("name allocation failure\n");
     425                 :          0 :                 spdk_bdev_part_base_free(base);
     426                 :          0 :                 free(disk);
     427                 :          0 :                 return -ENOMEM;
     428                 :            :         }
     429                 :            : 
     430         [ +  + ]:         71 :         if (!spdk_uuid_is_null(uuid)) {
     431         [ #  # ]:          0 :                 bdev = spdk_bdev_part_get_bdev(&disk->part);
     432         [ #  # ]:          0 :                 spdk_uuid_copy(&bdev->uuid, uuid);
     433                 :          0 :         }
     434                 :            : 
     435   [ #  #  #  #  :         71 :         rc = spdk_bdev_part_construct(&disk->part, base, name, 0, base_bdev->blockcnt,
                   #  # ]
     436                 :            :                                       "Error Injection Disk");
     437                 :         71 :         free(name);
     438         [ +  + ]:         71 :         if (rc) {
     439                 :          0 :                 SPDK_ERRLOG("could not construct part for bdev %s\n", base_bdev_name);
     440                 :            :                 /* spdk_bdev_part_construct will free name on failure */
     441                 :          0 :                 spdk_bdev_part_base_free(base);
     442                 :          0 :                 free(disk);
     443                 :          0 :                 return rc;
     444                 :            :         }
     445                 :            : 
     446                 :         71 :         return 0;
     447                 :          2 : }
     448                 :            : 
     449                 :            : int
     450                 :         71 : vbdev_error_create(const char *base_bdev_name, const struct spdk_uuid *uuid)
     451                 :            : {
     452                 :            :         int rc;
     453                 :            : 
     454                 :         71 :         rc = vbdev_error_config_add(base_bdev_name, uuid);
     455         [ -  + ]:         71 :         if (rc != 0) {
     456                 :          0 :                 SPDK_ERRLOG("Adding config for ErrorInjection bdev %s failed (rc=%d)\n",
     457                 :            :                             base_bdev_name, rc);
     458                 :          0 :                 return rc;
     459                 :            :         }
     460                 :            : 
     461                 :         71 :         rc = _vbdev_error_create(base_bdev_name, uuid);
     462         [ +  + ]:         71 :         if (rc == -ENODEV) {
     463                 :          4 :                 rc = 0;
     464         [ -  + ]:         67 :         } else if (rc != 0) {
     465                 :          0 :                 vbdev_error_config_remove(base_bdev_name);
     466                 :          0 :                 SPDK_ERRLOG("Could not create ErrorInjection bdev %s (rc=%d)\n",
     467                 :            :                             base_bdev_name, rc);
     468                 :          0 :         }
     469                 :            : 
     470                 :         71 :         return rc;
     471                 :          2 : }
     472                 :            : 
     473                 :            : void
     474                 :         11 : vbdev_error_delete(const char *error_vbdev_name, spdk_delete_error_complete cb_fn, void *cb_arg)
     475                 :            : {
     476                 :            :         int rc;
     477                 :            : 
     478                 :         11 :         rc = spdk_bdev_unregister_by_name(error_vbdev_name, &error_if, cb_fn, cb_arg);
     479         [ -  + ]:         11 :         if (rc != 0) {
     480   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, rc);
     481                 :          0 :         }
     482                 :         11 : }
     483                 :            : 
     484                 :            : static void
     485                 :       1939 : vbdev_error_clear_config(void)
     486                 :            : {
     487                 :            :         struct spdk_vbdev_error_config *cfg;
     488                 :            : 
     489         [ -  + ]:       1939 :         while ((cfg = TAILQ_FIRST(&g_error_config))) {
     490   [ #  #  #  #  :          0 :                 TAILQ_REMOVE(&g_error_config, cfg, tailq);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     491   [ #  #  #  # ]:          0 :                 free(cfg->base_bdev);
     492                 :          0 :                 free(cfg);
     493                 :            :         }
     494                 :       1939 : }
     495                 :            : 
     496                 :            : static struct spdk_vbdev_error_config *
     497                 :       5814 : vbdev_error_config_find_by_base_name(const char *base_bdev_name)
     498                 :            : {
     499                 :            :         struct spdk_vbdev_error_config *cfg;
     500                 :            : 
     501   [ +  +  #  #  :       6396 :         TAILQ_FOREACH(cfg, &g_error_config, tailq) {
             #  #  #  # ]
     502   [ +  +  -  +  :        657 :                 if (strcmp(cfg->base_bdev, base_bdev_name) == 0) {
          +  +  #  #  #  
                      # ]
     503                 :         75 :                         return cfg;
     504                 :            :                 }
     505                 :          4 :         }
     506                 :            : 
     507                 :       5739 :         return NULL;
     508                 :        320 : }
     509                 :            : 
     510                 :            : static int
     511                 :         71 : vbdev_error_config_add(const char *base_bdev_name, const struct spdk_uuid *uuid)
     512                 :            : {
     513                 :            :         struct spdk_vbdev_error_config *cfg;
     514                 :            : 
     515                 :         71 :         cfg = vbdev_error_config_find_by_base_name(base_bdev_name);
     516         [ -  + ]:         71 :         if (cfg) {
     517                 :          0 :                 SPDK_ERRLOG("vbdev_error_config for bdev %s already exists\n",
     518                 :            :                             base_bdev_name);
     519                 :          0 :                 return -EEXIST;
     520                 :            :         }
     521                 :            : 
     522                 :         71 :         cfg = calloc(1, sizeof(*cfg));
     523         [ +  + ]:         71 :         if (!cfg) {
     524                 :          0 :                 SPDK_ERRLOG("calloc() failed for vbdev_error_config\n");
     525                 :          0 :                 return -ENOMEM;
     526                 :            :         }
     527                 :            : 
     528   [ -  +  #  #  :         71 :         cfg->base_bdev = strdup(base_bdev_name);
                   #  # ]
     529   [ -  +  #  #  :         71 :         if (!cfg->base_bdev) {
                   #  # ]
     530                 :          0 :                 free(cfg);
     531                 :          0 :                 SPDK_ERRLOG("strdup() failed for base_bdev_name\n");
     532                 :          0 :                 return -ENOMEM;
     533                 :            :         }
     534                 :            : 
     535         [ #  # ]:         71 :         spdk_uuid_copy(&cfg->uuid, uuid);
     536   [ #  #  #  #  :         71 :         TAILQ_INSERT_TAIL(&g_error_config, cfg, tailq);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     537                 :            : 
     538                 :         71 :         return 0;
     539                 :          2 : }
     540                 :            : 
     541                 :            : static int
     542                 :         71 : vbdev_error_config_remove(const char *base_bdev_name)
     543                 :            : {
     544                 :            :         struct spdk_vbdev_error_config *cfg;
     545                 :            : 
     546                 :         71 :         cfg = vbdev_error_config_find_by_base_name(base_bdev_name);
     547         [ +  + ]:         71 :         if (!cfg) {
     548                 :          0 :                 return -ENOENT;
     549                 :            :         }
     550                 :            : 
     551   [ +  +  #  #  :         71 :         TAILQ_REMOVE(&g_error_config, cfg, tailq);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     552   [ #  #  #  # ]:         71 :         free(cfg->base_bdev);
     553                 :         71 :         free(cfg);
     554                 :         71 :         return 0;
     555                 :          2 : }
     556                 :            : 
     557                 :            : static int
     558                 :       1939 : vbdev_error_init(void)
     559                 :            : {
     560                 :       1939 :         return 0;
     561                 :            : }
     562                 :            : 
     563                 :            : static void
     564                 :       1939 : vbdev_error_fini(void)
     565                 :            : {
     566                 :       1939 :         vbdev_error_clear_config();
     567                 :       1939 : }
     568                 :            : 
     569                 :            : static void
     570                 :       5672 : vbdev_error_examine(struct spdk_bdev *bdev)
     571                 :            : {
     572                 :            :         struct spdk_vbdev_error_config *cfg;
     573                 :            :         int rc;
     574                 :            : 
     575   [ +  -  +  - ]:       5672 :         cfg = vbdev_error_config_find_by_base_name(bdev->name);
     576         [ +  + ]:       5672 :         if (cfg != NULL) {
     577   [ #  #  #  #  :          4 :                 rc = _vbdev_error_create(bdev->name, &cfg->uuid);
                   #  # ]
     578         [ -  + ]:          4 :                 if (rc != 0) {
     579   [ #  #  #  # ]:          0 :                         SPDK_ERRLOG("could not create error vbdev for bdev %s at examine\n",
     580                 :            :                                     bdev->name);
     581                 :          0 :                 }
     582                 :          0 :         }
     583                 :            : 
     584                 :       5672 :         spdk_bdev_module_examine_done(&error_if);
     585                 :       5672 : }
     586                 :            : 
     587                 :            : static int
     588                 :        173 : vbdev_error_config_json(struct spdk_json_write_ctx *w)
     589                 :            : {
     590                 :            :         struct spdk_vbdev_error_config *cfg;
     591                 :            : 
     592   [ +  +  #  #  :        181 :         TAILQ_FOREACH(cfg, &g_error_config, tailq) {
             #  #  #  # ]
     593                 :          8 :                 spdk_json_write_object_begin(w);
     594                 :            : 
     595                 :          8 :                 spdk_json_write_named_string(w, "method", "bdev_error_create");
     596                 :          8 :                 spdk_json_write_named_object_begin(w, "params");
     597   [ #  #  #  # ]:          8 :                 spdk_json_write_named_string(w, "base_name", cfg->base_bdev);
     598   [ -  +  #  # ]:          8 :                 if (!spdk_uuid_is_null(&cfg->uuid)) {
     599         [ #  # ]:          0 :                         spdk_json_write_named_uuid(w, "uuid", &cfg->uuid);
     600                 :          0 :                 }
     601                 :          8 :                 spdk_json_write_object_end(w);
     602                 :            : 
     603                 :          8 :                 spdk_json_write_object_end(w);
     604                 :          0 :         }
     605                 :            : 
     606                 :        173 :         return 0;
     607                 :            : }

Generated by: LCOV version 1.14