LCOV - code coverage report
Current view: top level - module/bdev/error - vbdev_error.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 0 292 0.0 %
Date: 2024-12-09 09:19:17 Functions: 0 28 0.0 %

          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           0 : vbdev_error_get_ctx_size(void)
      70             : {
      71           0 :         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           0 : 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           0 : vbdev_error_inject_error(char *name, const struct vbdev_error_inject_opts *opts)
      93             : {
      94             :         struct spdk_bdev_desc *desc;
      95             :         struct spdk_bdev *bdev;
      96             :         struct spdk_bdev_part *part;
      97           0 :         struct error_disk *error_disk = NULL;
      98             :         uint32_t i;
      99           0 :         int rc = 0;
     100             : 
     101           0 :         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           0 :         pthread_mutex_lock(&g_vbdev_error_mutex);
     110             : 
     111           0 :         rc = spdk_bdev_open_ext(name, false, dummy_bdev_event_cb, NULL, &desc);
     112           0 :         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           0 :         bdev = spdk_bdev_desc_get_bdev(desc);
     119             : 
     120           0 :         TAILQ_FOREACH(part, &g_error_disks, tailq) {
     121           0 :                 if (bdev == spdk_bdev_part_get_bdev(part)) {
     122           0 :                         error_disk = (struct error_disk *)part;
     123           0 :                         break;
     124             :                 }
     125           0 :         }
     126             : 
     127           0 :         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           0 :         if (0xffffffff == opts->io_type) {
     134           0 :                 for (i = 0; i < SPDK_COUNTOF(error_disk->error_vector); i++) {
     135           0 :                         error_disk->error_vector[i].error_type = opts->error_type;
     136           0 :                         error_disk->error_vector[i].error_num = opts->error_num;
     137           0 :                         error_disk->error_vector[i].error_qd = opts->error_qd;
     138           0 :                         error_disk->error_vector[i].corrupt_offset = opts->corrupt_offset;
     139           0 :                         error_disk->error_vector[i].corrupt_value = opts->corrupt_value;
     140           0 :                 }
     141           0 :         } 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           0 :                 error_disk->error_vector[opts->io_type].error_type = opts->error_type;
     147           0 :                 error_disk->error_vector[opts->io_type].error_num = opts->error_num;
     148           0 :                 error_disk->error_vector[opts->io_type].error_qd = opts->error_qd;
     149           0 :                 error_disk->error_vector[opts->io_type].corrupt_offset = opts->corrupt_offset;
     150           0 :                 error_disk->error_vector[opts->io_type].corrupt_value = opts->corrupt_value;
     151             :         }
     152             : 
     153             : exit:
     154           0 :         spdk_bdev_close(desc);
     155           0 :         pthread_mutex_unlock(&g_vbdev_error_mutex);
     156           0 :         return rc;
     157           0 : }
     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           0 : vbdev_error_get_error_type(struct error_disk *error_disk, struct error_channel *ch,
     196             :                            uint32_t io_type)
     197             : {
     198             :         uint32_t error_num;
     199             :         struct vbdev_error_info *error_info;
     200             : 
     201           0 :         switch (io_type) {
     202             :         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           0 :                 break;
     207             :         default:
     208           0 :                 return VBDEV_IO_NO_ERROR;
     209             :         }
     210             : 
     211           0 :         error_info = &error_disk->error_vector[io_type];
     212             : 
     213           0 :         if (ch->io_inflight < error_info->error_qd) {
     214           0 :                 return VBDEV_IO_NO_ERROR;
     215             :         }
     216             : 
     217           0 :         error_num = error_info->error_num;
     218           0 :         do {
     219           0 :                 if (error_num == 0) {
     220           0 :                         return VBDEV_IO_NO_ERROR;
     221             :                 }
     222           0 :         } while (!__atomic_compare_exchange_n(&error_info->error_num,
     223           0 :                                               &error_num, error_num - 1,
     224             :                                               false, __ATOMIC_RELAXED, __ATOMIC_RELAXED));
     225             : 
     226           0 :         return error_info->error_type;
     227           0 : }
     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           0 : vbdev_error_complete_request(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
     254             : {
     255           0 :         struct error_io *error_io = (struct error_io *)bdev_io->driver_ctx;
     256           0 :         int status = success ? SPDK_BDEV_IO_STATUS_SUCCESS : SPDK_BDEV_IO_STATUS_FAILED;
     257           0 :         struct error_disk *error_disk = bdev_io->bdev->ctxt;
     258           0 :         struct error_channel *ch = spdk_io_channel_get_ctx(spdk_bdev_io_get_io_channel(bdev_io));
     259             : 
     260           0 :         assert(ch->io_inflight > 0);
     261           0 :         ch->io_inflight--;
     262             : 
     263           0 :         if (success && bdev_io->type == SPDK_BDEV_IO_TYPE_READ) {
     264           0 :                 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           0 :         }
     270             : 
     271           0 :         spdk_bdev_io_complete(bdev_io, status);
     272           0 : }
     273             : 
     274             : static void
     275           0 : vbdev_error_submit_request(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_io)
     276             : {
     277           0 :         struct error_io *error_io = (struct error_io *)bdev_io->driver_ctx;
     278           0 :         struct error_channel *ch = spdk_io_channel_get_ctx(_ch);
     279           0 :         struct error_disk *error_disk = bdev_io->bdev->ctxt;
     280             :         int rc;
     281             : 
     282           0 :         if (bdev_io->type == SPDK_BDEV_IO_TYPE_RESET) {
     283           0 :                 vbdev_error_reset(error_disk, bdev_io);
     284           0 :                 return;
     285             :         }
     286             : 
     287           0 :         error_io->error_type = vbdev_error_get_error_type(error_disk, ch, bdev_io->type);
     288             : 
     289           0 :         switch (error_io->error_type) {
     290             :         case VBDEV_IO_FAILURE:
     291           0 :                 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
     292           0 :                 break;
     293             :         case VBDEV_IO_NOMEM:
     294           0 :                 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_NOMEM);
     295           0 :                 break;
     296             :         case VBDEV_IO_PENDING:
     297           0 :                 TAILQ_INSERT_TAIL(&ch->pending_ios, error_io, link);
     298           0 :                 break;
     299             :         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           0 :                 ch->io_inflight++;
     308           0 :                 rc = spdk_bdev_part_submit_request_ext(&ch->part_ch, bdev_io,
     309             :                                                        vbdev_error_complete_request);
     310             : 
     311           0 :                 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           0 :                 break;
     317             :         default:
     318           0 :                 assert(false);
     319             :                 break;
     320             :         }
     321           0 : }
     322             : 
     323             : static int
     324           0 : vbdev_error_destruct(void *ctx)
     325             : {
     326           0 :         struct error_disk *error_disk = ctx;
     327           0 :         struct spdk_bdev *base_bdev = spdk_bdev_part_get_base_bdev(&error_disk->part);
     328             :         int rc;
     329             : 
     330           0 :         rc = vbdev_error_config_remove(base_bdev->name);
     331           0 :         if (rc != 0) {
     332           0 :                 SPDK_ERRLOG("vbdev_error_config_remove() failed\n");
     333           0 :         }
     334             : 
     335           0 :         return spdk_bdev_part_free(&error_disk->part);
     336             : }
     337             : 
     338             : static int
     339           0 : vbdev_error_dump_info_json(void *ctx, struct spdk_json_write_ctx *w)
     340             : {
     341           0 :         struct error_disk *error_disk = ctx;
     342           0 :         struct spdk_bdev *base_bdev = spdk_bdev_part_get_base_bdev(&error_disk->part);
     343             : 
     344           0 :         spdk_json_write_named_object_begin(w, "error_disk");
     345             : 
     346           0 :         spdk_json_write_named_string(w, "base_bdev", base_bdev->name);
     347             : 
     348           0 :         spdk_json_write_object_end(w);
     349             : 
     350           0 :         return 0;
     351             : }
     352             : 
     353             : static void
     354           0 : vbdev_error_write_config_json(struct spdk_bdev *bdev, struct spdk_json_write_ctx *w)
     355             : {
     356             :         /* No config per bdev. */
     357           0 : }
     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           0 : vbdev_error_ch_create_cb(void *io_device, void *ctx_buf)
     377             : {
     378           0 :         struct error_channel *ch = ctx_buf;
     379             : 
     380           0 :         ch->io_inflight = 0;
     381           0 :         TAILQ_INIT(&ch->pending_ios);
     382             : 
     383           0 :         return 0;
     384             : }
     385             : 
     386             : static void
     387           0 : vbdev_error_ch_destroy_cb(void *io_device, void *ctx_buf)
     388             : {
     389           0 : }
     390             : 
     391             : static int
     392           0 : _vbdev_error_create(const char *base_bdev_name, const struct spdk_uuid *uuid)
     393             : {
     394           0 :         struct spdk_bdev_part_base *base = NULL;
     395           0 :         struct error_disk *disk = NULL;
     396             :         struct spdk_bdev *base_bdev, *bdev;
     397             :         char *name;
     398             :         int rc;
     399             : 
     400           0 :         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           0 :         if (rc != 0) {
     407           0 :                 if (rc != -ENODEV) {
     408           0 :                         SPDK_ERRLOG("could not construct part base for bdev %s\n", base_bdev_name);
     409           0 :                 }
     410           0 :                 return rc;
     411             :         }
     412             : 
     413           0 :         base_bdev = spdk_bdev_part_base_get_bdev(base);
     414             : 
     415           0 :         disk = calloc(1, sizeof(*disk));
     416           0 :         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           0 :         name = spdk_sprintf_alloc("EE_%s", base_bdev_name);
     423           0 :         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           0 :         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           0 :         rc = spdk_bdev_part_construct(&disk->part, base, name, 0, base_bdev->blockcnt,
     436             :                                       "Error Injection Disk");
     437           0 :         free(name);
     438           0 :         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           0 :         return 0;
     447           0 : }
     448             : 
     449             : int
     450           0 : vbdev_error_create(const char *base_bdev_name, const struct spdk_uuid *uuid)
     451             : {
     452             :         int rc;
     453             : 
     454           0 :         rc = vbdev_error_config_add(base_bdev_name, uuid);
     455           0 :         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           0 :         rc = _vbdev_error_create(base_bdev_name, uuid);
     462           0 :         if (rc == -ENODEV) {
     463           0 :                 rc = 0;
     464           0 :         } 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           0 :         return rc;
     471           0 : }
     472             : 
     473             : void
     474           0 : vbdev_error_delete(const char *error_vbdev_name, spdk_delete_error_complete cb_fn, void *cb_arg)
     475             : {
     476             :         int rc;
     477             : 
     478           0 :         rc = spdk_bdev_unregister_by_name(error_vbdev_name, &error_if, cb_fn, cb_arg);
     479           0 :         if (rc != 0) {
     480           0 :                 cb_fn(cb_arg, rc);
     481           0 :         }
     482           0 : }
     483             : 
     484             : static void
     485           0 : vbdev_error_clear_config(void)
     486             : {
     487             :         struct spdk_vbdev_error_config *cfg;
     488             : 
     489           0 :         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           0 : }
     495             : 
     496             : static struct spdk_vbdev_error_config *
     497           0 : vbdev_error_config_find_by_base_name(const char *base_bdev_name)
     498             : {
     499             :         struct spdk_vbdev_error_config *cfg;
     500             : 
     501           0 :         TAILQ_FOREACH(cfg, &g_error_config, tailq) {
     502           0 :                 if (strcmp(cfg->base_bdev, base_bdev_name) == 0) {
     503           0 :                         return cfg;
     504             :                 }
     505           0 :         }
     506             : 
     507           0 :         return NULL;
     508           0 : }
     509             : 
     510             : static int
     511           0 : vbdev_error_config_add(const char *base_bdev_name, const struct spdk_uuid *uuid)
     512             : {
     513             :         struct spdk_vbdev_error_config *cfg;
     514             : 
     515           0 :         cfg = vbdev_error_config_find_by_base_name(base_bdev_name);
     516           0 :         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           0 :         cfg = calloc(1, sizeof(*cfg));
     523           0 :         if (!cfg) {
     524           0 :                 SPDK_ERRLOG("calloc() failed for vbdev_error_config\n");
     525           0 :                 return -ENOMEM;
     526             :         }
     527             : 
     528           0 :         cfg->base_bdev = strdup(base_bdev_name);
     529           0 :         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           0 :         spdk_uuid_copy(&cfg->uuid, uuid);
     536           0 :         TAILQ_INSERT_TAIL(&g_error_config, cfg, tailq);
     537             : 
     538           0 :         return 0;
     539           0 : }
     540             : 
     541             : static int
     542           0 : vbdev_error_config_remove(const char *base_bdev_name)
     543             : {
     544             :         struct spdk_vbdev_error_config *cfg;
     545             : 
     546           0 :         cfg = vbdev_error_config_find_by_base_name(base_bdev_name);
     547           0 :         if (!cfg) {
     548           0 :                 return -ENOENT;
     549             :         }
     550             : 
     551           0 :         TAILQ_REMOVE(&g_error_config, cfg, tailq);
     552           0 :         free(cfg->base_bdev);
     553           0 :         free(cfg);
     554           0 :         return 0;
     555           0 : }
     556             : 
     557             : static int
     558           0 : vbdev_error_init(void)
     559             : {
     560           0 :         return 0;
     561             : }
     562             : 
     563             : static void
     564           0 : vbdev_error_fini(void)
     565             : {
     566           0 :         vbdev_error_clear_config();
     567           0 : }
     568             : 
     569             : static void
     570           0 : vbdev_error_examine(struct spdk_bdev *bdev)
     571             : {
     572             :         struct spdk_vbdev_error_config *cfg;
     573             :         int rc;
     574             : 
     575           0 :         cfg = vbdev_error_config_find_by_base_name(bdev->name);
     576           0 :         if (cfg != NULL) {
     577           0 :                 rc = _vbdev_error_create(bdev->name, &cfg->uuid);
     578           0 :                 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           0 :         spdk_bdev_module_examine_done(&error_if);
     585           0 : }
     586             : 
     587             : static int
     588           0 : vbdev_error_config_json(struct spdk_json_write_ctx *w)
     589             : {
     590             :         struct spdk_vbdev_error_config *cfg;
     591             : 
     592           0 :         TAILQ_FOREACH(cfg, &g_error_config, tailq) {
     593           0 :                 spdk_json_write_object_begin(w);
     594             : 
     595           0 :                 spdk_json_write_named_string(w, "method", "bdev_error_create");
     596           0 :                 spdk_json_write_named_object_begin(w, "params");
     597           0 :                 spdk_json_write_named_string(w, "base_name", cfg->base_bdev);
     598           0 :                 if (!spdk_uuid_is_null(&cfg->uuid)) {
     599           0 :                         spdk_json_write_named_uuid(w, "uuid", &cfg->uuid);
     600           0 :                 }
     601           0 :                 spdk_json_write_object_end(w);
     602             : 
     603           0 :                 spdk_json_write_object_end(w);
     604           0 :         }
     605             : 
     606           0 :         return 0;
     607             : }

Generated by: LCOV version 1.15