LCOV - code coverage report
Current view: top level - spdk/module/bdev/raid - bdev_raid.c (source / functions) Hit Total Coverage
Test: Combined Lines: 1476 2074 71.2 %
Date: 2024-12-17 02:02:38 Functions: 138 145 95.2 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 870 6727 12.9 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (C) 2018 Intel Corporation.
       3                 :            :  *   All rights reserved.
       4                 :            :  *   Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
       5                 :            :  */
       6                 :            : 
       7                 :            : #include "bdev_raid.h"
       8                 :            : #include "spdk/env.h"
       9                 :            : #include "spdk/thread.h"
      10                 :            : #include "spdk/log.h"
      11                 :            : #include "spdk/string.h"
      12                 :            : #include "spdk/util.h"
      13                 :            : #include "spdk/json.h"
      14                 :            : #include "spdk/likely.h"
      15                 :            : #include "spdk/trace.h"
      16                 :            : #include "spdk_internal/trace_defs.h"
      17                 :            : 
      18                 :            : #define RAID_OFFSET_BLOCKS_INVALID      UINT64_MAX
      19                 :            : #define RAID_BDEV_PROCESS_MAX_QD        16
      20                 :            : 
      21                 :            : #define RAID_BDEV_PROCESS_WINDOW_SIZE_KB_DEFAULT        1024
      22                 :            : #define RAID_BDEV_PROCESS_MAX_BANDWIDTH_MB_SEC_DEFAULT  0
      23                 :            : 
      24                 :            : static bool g_shutdown_started = false;
      25                 :            : 
      26                 :            : /* List of all raid bdevs */
      27                 :            : struct raid_all_tailq g_raid_bdev_list = TAILQ_HEAD_INITIALIZER(g_raid_bdev_list);
      28                 :            : 
      29                 :            : static TAILQ_HEAD(, raid_bdev_module) g_raid_modules = TAILQ_HEAD_INITIALIZER(g_raid_modules);
      30                 :            : 
      31                 :            : /*
      32                 :            :  * raid_bdev_io_channel is the context of spdk_io_channel for raid bdev device. It
      33                 :            :  * contains the relationship of raid bdev io channel with base bdev io channels.
      34                 :            :  */
      35                 :            : struct raid_bdev_io_channel {
      36                 :            :         /* Array of IO channels of base bdevs */
      37                 :            :         struct spdk_io_channel  **base_channel;
      38                 :            : 
      39                 :            :         /* Private raid module IO channel */
      40                 :            :         struct spdk_io_channel  *module_channel;
      41                 :            : 
      42                 :            :         /* Background process data */
      43                 :            :         struct {
      44                 :            :                 uint64_t offset;
      45                 :            :                 struct spdk_io_channel *target_ch;
      46                 :            :                 struct raid_bdev_io_channel *ch_processed;
      47                 :            :         } process;
      48                 :            : };
      49                 :            : 
      50                 :            : enum raid_bdev_process_state {
      51                 :            :         RAID_PROCESS_STATE_INIT,
      52                 :            :         RAID_PROCESS_STATE_RUNNING,
      53                 :            :         RAID_PROCESS_STATE_STOPPING,
      54                 :            :         RAID_PROCESS_STATE_STOPPED,
      55                 :            : };
      56                 :            : 
      57                 :            : struct raid_process_qos {
      58                 :            :         bool enable_qos;
      59                 :            :         uint64_t last_tsc;
      60                 :            :         double bytes_per_tsc;
      61                 :            :         double bytes_available;
      62                 :            :         double bytes_max;
      63                 :            :         struct spdk_poller *process_continue_poller;
      64                 :            : };
      65                 :            : 
      66                 :            : struct raid_bdev_process {
      67                 :            :         struct raid_bdev                *raid_bdev;
      68                 :            :         enum raid_process_type          type;
      69                 :            :         enum raid_bdev_process_state    state;
      70                 :            :         struct spdk_thread              *thread;
      71                 :            :         struct raid_bdev_io_channel     *raid_ch;
      72                 :            :         TAILQ_HEAD(, raid_bdev_process_request) requests;
      73                 :            :         uint64_t                        max_window_size;
      74                 :            :         uint64_t                        window_size;
      75                 :            :         uint64_t                        window_remaining;
      76                 :            :         int                             window_status;
      77                 :            :         uint64_t                        window_offset;
      78                 :            :         bool                            window_range_locked;
      79                 :            :         struct raid_base_bdev_info      *target;
      80                 :            :         int                             status;
      81                 :            :         TAILQ_HEAD(, raid_process_finish_action) finish_actions;
      82                 :            :         struct raid_process_qos         qos;
      83                 :            : };
      84                 :            : 
      85                 :            : struct raid_process_finish_action {
      86                 :            :         spdk_msg_fn cb;
      87                 :            :         void *cb_ctx;
      88                 :            :         TAILQ_ENTRY(raid_process_finish_action) link;
      89                 :            : };
      90                 :            : 
      91                 :            : static struct spdk_raid_bdev_opts g_opts = {
      92                 :            :         .process_window_size_kb = RAID_BDEV_PROCESS_WINDOW_SIZE_KB_DEFAULT,
      93                 :            :         .process_max_bandwidth_mb_sec = RAID_BDEV_PROCESS_MAX_BANDWIDTH_MB_SEC_DEFAULT,
      94                 :            : };
      95                 :            : 
      96                 :            : void
      97                 :        243 : raid_bdev_get_opts(struct spdk_raid_bdev_opts *opts)
      98                 :            : {
      99                 :        243 :         *opts = g_opts;
     100                 :        243 : }
     101                 :            : 
     102                 :            : int
     103                 :        246 : raid_bdev_set_opts(const struct spdk_raid_bdev_opts *opts)
     104                 :            : {
     105   [ +  +  +  -  :        246 :         if (opts->process_window_size_kb == 0) {
                   +  - ]
     106                 :          0 :                 return -EINVAL;
     107                 :            :         }
     108                 :            : 
     109                 :        246 :         g_opts = *opts;
     110                 :            : 
     111                 :        246 :         return 0;
     112                 :          1 : }
     113                 :            : 
     114                 :            : static struct raid_bdev_module *
     115                 :       6888 : raid_bdev_module_find(enum raid_level level)
     116                 :            : {
     117                 :            :         struct raid_bdev_module *raid_module;
     118                 :            : 
     119   [ +  +  -  +  :      14016 :         TAILQ_FOREACH(raid_module, &g_raid_modules, link) {
             -  +  -  + ]
     120   [ +  +  +  -  :       7538 :                 if (raid_module->level == level) {
                   +  - ]
     121                 :        410 :                         return raid_module;
     122                 :            :                 }
     123                 :        174 :         }
     124                 :            : 
     125                 :       6478 :         return NULL;
     126                 :        174 : }
     127                 :            : 
     128                 :            : void
     129                 :       6475 : raid_bdev_module_list_add(struct raid_bdev_module *raid_module)
     130                 :            : {
     131   [ +  +  +  -  :       6475 :         if (raid_bdev_module_find(raid_module->level) != NULL) {
                   +  - ]
     132   [ #  #  #  # ]:          0 :                 SPDK_ERRLOG("module for raid level '%s' already registered.\n",
     133                 :            :                             raid_bdev_level_to_str(raid_module->level));
     134         [ #  # ]:          0 :                 assert(false);
     135                 :            :         } else {
     136   [ +  -  +  -  :       6475 :                 TAILQ_INSERT_TAIL(&g_raid_modules, raid_module, link);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     137                 :            :         }
     138                 :       6475 : }
     139                 :            : 
     140                 :            : struct spdk_io_channel *
     141                 :   16470032 : raid_bdev_channel_get_base_channel(struct raid_bdev_io_channel *raid_ch, uint8_t idx)
     142                 :            : {
     143   [ #  #  #  #  :   16470032 :         return raid_ch->base_channel[idx];
             #  #  #  # ]
     144                 :            : }
     145                 :            : 
     146                 :            : void *
     147                 :    1536190 : raid_bdev_channel_get_module_ctx(struct raid_bdev_io_channel *raid_ch)
     148                 :            : {
     149   [ -  +  #  #  :    1536190 :         assert(raid_ch->module_channel != NULL);
             #  #  #  # ]
     150                 :            : 
     151   [ #  #  #  # ]:    1536190 :         return spdk_io_channel_get_ctx(raid_ch->module_channel);
     152                 :            : }
     153                 :            : 
     154                 :            : struct raid_base_bdev_info *
     155                 :          3 : raid_bdev_channel_get_base_info(struct raid_bdev_io_channel *raid_ch, struct spdk_bdev *base_bdev)
     156                 :            : {
     157                 :          3 :         struct spdk_io_channel *ch = spdk_io_channel_from_ctx(raid_ch);
     158                 :          3 :         struct raid_bdev *raid_bdev = spdk_io_channel_get_io_device(ch);
     159                 :            :         uint8_t i;
     160                 :            : 
     161   [ +  -  #  #  :          3 :         for (i = 0; i < raid_bdev->num_base_bdevs; i++) {
                   #  # ]
     162   [ #  #  #  #  :          3 :                 struct raid_base_bdev_info *base_info = &raid_bdev->base_bdev_info[i];
                   #  # ]
     163                 :            : 
     164   [ -  +  +  -  :          6 :                 if (base_info->is_configured &&
          +  -  #  #  #  
                      # ]
     165   [ #  #  #  # ]:          3 :                     spdk_bdev_desc_get_bdev(base_info->desc) == base_bdev) {
     166                 :          3 :                         return base_info;
     167                 :            :                 }
     168                 :          0 :         }
     169                 :            : 
     170                 :          0 :         return NULL;
     171                 :          0 : }
     172                 :            : 
     173                 :            : /* Function declarations */
     174                 :            : static void     raid_bdev_examine(struct spdk_bdev *bdev);
     175                 :            : static int      raid_bdev_init(void);
     176                 :            : static void     raid_bdev_deconfigure(struct raid_bdev *raid_bdev,
     177                 :            :                                       raid_bdev_destruct_cb cb_fn, void *cb_arg);
     178                 :            : 
     179                 :            : static void
     180                 :        670 : raid_bdev_ch_process_cleanup(struct raid_bdev_io_channel *raid_ch)
     181                 :            : {
     182   [ #  #  #  #  :        670 :         raid_ch->process.offset = RAID_OFFSET_BLOCKS_INVALID;
                   #  # ]
     183                 :            : 
     184   [ +  +  #  #  :        670 :         if (raid_ch->process.target_ch != NULL) {
             #  #  #  # ]
     185   [ #  #  #  #  :         41 :                 spdk_put_io_channel(raid_ch->process.target_ch);
                   #  # ]
     186   [ #  #  #  #  :         41 :                 raid_ch->process.target_ch = NULL;
                   #  # ]
     187                 :          0 :         }
     188                 :            : 
     189   [ +  +  #  #  :        670 :         if (raid_ch->process.ch_processed != NULL) {
             #  #  #  # ]
     190   [ #  #  #  #  :         66 :                 free(raid_ch->process.ch_processed->base_channel);
          #  #  #  #  #  
                      # ]
     191   [ #  #  #  #  :         66 :                 free(raid_ch->process.ch_processed);
                   #  # ]
     192   [ #  #  #  #  :         66 :                 raid_ch->process.ch_processed = NULL;
                   #  # ]
     193                 :          0 :         }
     194                 :        670 : }
     195                 :            : 
     196                 :            : static int
     197                 :         66 : raid_bdev_ch_process_setup(struct raid_bdev_io_channel *raid_ch, struct raid_bdev_process *process)
     198                 :            : {
     199   [ #  #  #  # ]:         66 :         struct raid_bdev *raid_bdev = process->raid_bdev;
     200                 :            :         struct raid_bdev_io_channel *raid_ch_processed;
     201                 :            :         struct raid_base_bdev_info *base_info;
     202                 :            : 
     203   [ #  #  #  #  :         66 :         raid_ch->process.offset = process->window_offset;
          #  #  #  #  #  
                      # ]
     204                 :            : 
     205                 :            :         /* In the future we may have other types of processes which don't use a target bdev,
     206                 :            :          * like data scrubbing or strip size migration. Until then, expect that there always is
     207                 :            :          * a process target. */
     208   [ -  +  #  #  :         66 :         assert(process->target != NULL);
             #  #  #  # ]
     209                 :            : 
     210   [ #  #  #  #  :         66 :         raid_ch->process.target_ch = spdk_bdev_get_io_channel(process->target->desc);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     211   [ -  +  #  #  :         66 :         if (raid_ch->process.target_ch == NULL) {
             #  #  #  # ]
     212                 :          0 :                 goto err;
     213                 :            :         }
     214                 :            : 
     215                 :         66 :         raid_ch_processed = calloc(1, sizeof(*raid_ch_processed));
     216         [ -  + ]:         66 :         if (raid_ch_processed == NULL) {
     217                 :          0 :                 goto err;
     218                 :            :         }
     219   [ #  #  #  #  :         66 :         raid_ch->process.ch_processed = raid_ch_processed;
                   #  # ]
     220                 :            : 
     221   [ #  #  #  #  :         66 :         raid_ch_processed->base_channel = calloc(raid_bdev->num_base_bdevs,
             #  #  #  # ]
     222                 :            :                                           sizeof(*raid_ch_processed->base_channel));
     223   [ -  +  #  #  :         66 :         if (raid_ch_processed->base_channel == NULL) {
                   #  # ]
     224                 :          0 :                 goto err;
     225                 :            :         }
     226                 :            : 
     227   [ +  +  #  #  :        519 :         RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) {
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     228                 :        453 :                 uint8_t slot = raid_bdev_base_bdev_slot(base_info);
     229                 :            : 
     230   [ +  +  #  #  :        453 :                 if (base_info != process->target) {
                   #  # ]
     231   [ #  #  #  #  :        387 :                         raid_ch_processed->base_channel[slot] = raid_ch->base_channel[slot];
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     232                 :          0 :                 } else {
     233   [ #  #  #  #  :         66 :                         raid_ch_processed->base_channel[slot] = raid_ch->process.target_ch;
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     234                 :            :                 }
     235                 :          0 :         }
     236                 :            : 
     237   [ #  #  #  #  :         66 :         raid_ch_processed->module_channel = raid_ch->module_channel;
             #  #  #  # ]
     238   [ #  #  #  #  :         66 :         raid_ch_processed->process.offset = RAID_OFFSET_BLOCKS_INVALID;
                   #  # ]
     239                 :            : 
     240                 :         66 :         return 0;
     241                 :          0 : err:
     242                 :          0 :         raid_bdev_ch_process_cleanup(raid_ch);
     243                 :          0 :         return -ENOMEM;
     244                 :          0 : }
     245                 :            : 
     246                 :            : /*
     247                 :            :  * brief:
     248                 :            :  * raid_bdev_create_cb function is a cb function for raid bdev which creates the
     249                 :            :  * hierarchy from raid bdev to base bdev io channels. It will be called per core
     250                 :            :  * params:
     251                 :            :  * io_device - pointer to raid bdev io device represented by raid_bdev
     252                 :            :  * ctx_buf - pointer to context buffer for raid bdev io channel
     253                 :            :  * returns:
     254                 :            :  * 0 - success
     255                 :            :  * non zero - failure
     256                 :            :  */
     257                 :            : static int
     258                 :        607 : raid_bdev_create_cb(void *io_device, void *ctx_buf)
     259                 :            : {
     260                 :        607 :         struct raid_bdev            *raid_bdev = io_device;
     261                 :        607 :         struct raid_bdev_io_channel *raid_ch = ctx_buf;
     262                 :            :         uint8_t i;
     263                 :        607 :         int ret = -ENOMEM;
     264                 :            : 
     265   [ -  +  +  +  :        607 :         SPDK_DEBUGLOG(bdev_raid, "raid_bdev_create_cb, %p\n", raid_ch);
                   #  # ]
     266                 :            : 
     267   [ -  +  #  # ]:        607 :         assert(raid_bdev != NULL);
     268   [ -  +  #  #  :        607 :         assert(raid_bdev->state == RAID_BDEV_STATE_ONLINE);
             #  #  #  # ]
     269                 :            : 
     270   [ #  #  #  #  :        607 :         raid_ch->base_channel = calloc(raid_bdev->num_base_bdevs, sizeof(struct spdk_io_channel *));
             #  #  #  # ]
     271   [ -  +  #  #  :        607 :         if (!raid_ch->base_channel) {
                   #  # ]
     272                 :          0 :                 SPDK_ERRLOG("Unable to allocate base bdevs io channel\n");
     273                 :          0 :                 return -ENOMEM;
     274                 :            :         }
     275                 :            : 
     276   [ +  +  #  #  :       2517 :         for (i = 0; i < raid_bdev->num_base_bdevs; i++) {
                   #  # ]
     277                 :            :                 /*
     278                 :            :                  * Get the spdk_io_channel for all the base bdevs. This is used during
     279                 :            :                  * split logic to send the respective child bdev ios to respective base
     280                 :            :                  * bdev io channel.
     281                 :            :                  * Skip missing base bdevs and the process target, which should also be treated as
     282                 :            :                  * missing until the process completes.
     283                 :            :                  */
     284   [ +  +  +  +  :       1910 :                 if (raid_bdev->base_bdev_info[i].is_configured == false ||
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     285   [ -  +  +  +  :       1884 :                     raid_bdev->base_bdev_info[i].is_process_target == true) {
          #  #  #  #  #  
                #  #  # ]
     286                 :         75 :                         continue;
     287                 :            :                 }
     288   [ #  #  #  #  :       2107 :                 raid_ch->base_channel[i] = spdk_bdev_get_io_channel(
             #  #  #  # ]
     289   [ #  #  #  #  :       1835 :                                                    raid_bdev->base_bdev_info[i].desc);
          #  #  #  #  #  
                      # ]
     290   [ -  +  #  #  :       1835 :                 if (!raid_ch->base_channel[i]) {
          #  #  #  #  #  
                      # ]
     291                 :          0 :                         SPDK_ERRLOG("Unable to create io channel for base bdev\n");
     292                 :          0 :                         goto err;
     293                 :            :                 }
     294                 :          0 :         }
     295                 :            : 
     296   [ +  +  #  #  :        607 :         if (raid_bdev->module->get_io_channel) {
          #  #  #  #  #  
                      # ]
     297   [ #  #  #  #  :        246 :                 raid_ch->module_channel = raid_bdev->module->get_io_channel(raid_bdev);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     298   [ -  +  #  #  :        246 :                 if (!raid_ch->module_channel) {
                   #  # ]
     299                 :          0 :                         SPDK_ERRLOG("Unable to create io channel for raid module\n");
     300                 :          0 :                         goto err;
     301                 :            :                 }
     302                 :          0 :         }
     303                 :            : 
     304   [ +  +  #  #  :        607 :         if (raid_bdev->process != NULL) {
                   #  # ]
     305   [ #  #  #  # ]:         58 :                 ret = raid_bdev_ch_process_setup(raid_ch, raid_bdev->process);
     306         [ -  + ]:         58 :                 if (ret != 0) {
     307                 :          0 :                         SPDK_ERRLOG("Failed to setup process io channel\n");
     308                 :          0 :                         goto err;
     309                 :            :                 }
     310                 :          0 :         } else {
     311   [ #  #  #  #  :        549 :                 raid_ch->process.offset = RAID_OFFSET_BLOCKS_INVALID;
                   #  # ]
     312                 :            :         }
     313                 :            : 
     314                 :        607 :         return 0;
     315                 :          0 : err:
     316   [ #  #  #  #  :          0 :         for (i = 0; i < raid_bdev->num_base_bdevs; i++) {
                   #  # ]
     317   [ #  #  #  #  :          0 :                 if (raid_ch->base_channel[i] != NULL) {
          #  #  #  #  #  
                      # ]
     318   [ #  #  #  #  :          0 :                         spdk_put_io_channel(raid_ch->base_channel[i]);
             #  #  #  # ]
     319                 :          0 :                 }
     320                 :          0 :         }
     321   [ #  #  #  # ]:          0 :         free(raid_ch->base_channel);
     322                 :            : 
     323                 :          0 :         raid_bdev_ch_process_cleanup(raid_ch);
     324                 :            : 
     325                 :          0 :         return ret;
     326                 :          0 : }
     327                 :            : 
     328                 :            : /*
     329                 :            :  * brief:
     330                 :            :  * raid_bdev_destroy_cb function is a cb function for raid bdev which deletes the
     331                 :            :  * hierarchy from raid bdev to base bdev io channels. It will be called per core
     332                 :            :  * params:
     333                 :            :  * io_device - pointer to raid bdev io device represented by raid_bdev
     334                 :            :  * ctx_buf - pointer to context buffer for raid bdev io channel
     335                 :            :  * returns:
     336                 :            :  * none
     337                 :            :  */
     338                 :            : static void
     339                 :        607 : raid_bdev_destroy_cb(void *io_device, void *ctx_buf)
     340                 :            : {
     341                 :        607 :         struct raid_bdev *raid_bdev = io_device;
     342                 :        607 :         struct raid_bdev_io_channel *raid_ch = ctx_buf;
     343                 :            :         uint8_t i;
     344                 :            : 
     345   [ -  +  +  +  :        607 :         SPDK_DEBUGLOG(bdev_raid, "raid_bdev_destroy_cb\n");
                   #  # ]
     346                 :            : 
     347   [ -  +  #  # ]:        607 :         assert(raid_ch != NULL);
     348   [ -  +  #  #  :        607 :         assert(raid_ch->base_channel);
             #  #  #  # ]
     349                 :            : 
     350   [ +  +  #  #  :        607 :         if (raid_ch->module_channel) {
                   #  # ]
     351   [ #  #  #  # ]:        246 :                 spdk_put_io_channel(raid_ch->module_channel);
     352                 :          0 :         }
     353                 :            : 
     354   [ +  +  #  #  :       2517 :         for (i = 0; i < raid_bdev->num_base_bdevs; i++) {
                   #  # ]
     355                 :            :                 /* Free base bdev channels */
     356   [ +  +  #  #  :       1910 :                 if (raid_ch->base_channel[i] != NULL) {
          #  #  #  #  #  
                      # ]
     357   [ #  #  #  #  :       1845 :                         spdk_put_io_channel(raid_ch->base_channel[i]);
             #  #  #  # ]
     358                 :          0 :                 }
     359                 :          0 :         }
     360   [ #  #  #  # ]:        607 :         free(raid_ch->base_channel);
     361   [ #  #  #  # ]:        607 :         raid_ch->base_channel = NULL;
     362                 :            : 
     363                 :        607 :         raid_bdev_ch_process_cleanup(raid_ch);
     364                 :        607 : }
     365                 :            : 
     366                 :            : /*
     367                 :            :  * brief:
     368                 :            :  * raid_bdev_cleanup is used to cleanup raid_bdev related data
     369                 :            :  * structures.
     370                 :            :  * params:
     371                 :            :  * raid_bdev - pointer to raid_bdev
     372                 :            :  * returns:
     373                 :            :  * none
     374                 :            :  */
     375                 :            : static void
     376                 :        410 : raid_bdev_cleanup(struct raid_bdev *raid_bdev)
     377                 :            : {
     378                 :            :         struct raid_base_bdev_info *base_info;
     379                 :            : 
     380   [ -  +  +  +  :        410 :         SPDK_DEBUGLOG(bdev_raid, "raid_bdev_cleanup, %p name %s, state %s\n",
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     381                 :            :                       raid_bdev, raid_bdev->bdev.name, raid_bdev_state_to_str(raid_bdev->state));
     382   [ -  +  #  #  :        410 :         assert(raid_bdev->state != RAID_BDEV_STATE_ONLINE);
             #  #  #  # ]
     383   [ -  +  #  # ]:        410 :         assert(spdk_get_thread() == spdk_thread_get_app_thread());
     384                 :            : 
     385   [ +  +  #  #  :       2964 :         RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) {
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     386   [ -  +  #  #  :       2554 :                 assert(base_info->desc == NULL);
             #  #  #  # ]
     387   [ #  #  #  # ]:       2554 :                 free(base_info->name);
     388                 :          0 :         }
     389                 :            : 
     390   [ +  +  #  #  :        410 :         TAILQ_REMOVE(&g_raid_bdev_list, raid_bdev, global_link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     391                 :        410 : }
     392                 :            : 
     393                 :            : static void
     394                 :        410 : raid_bdev_free(struct raid_bdev *raid_bdev)
     395                 :            : {
     396                 :        410 :         raid_bdev_free_superblock(raid_bdev);
     397   [ #  #  #  # ]:        410 :         free(raid_bdev->base_bdev_info);
     398   [ #  #  #  #  :        410 :         free(raid_bdev->bdev.name);
                   #  # ]
     399                 :        410 :         free(raid_bdev);
     400                 :        410 : }
     401                 :            : 
     402                 :            : static void
     403                 :         97 : raid_bdev_cleanup_and_free(struct raid_bdev *raid_bdev)
     404                 :            : {
     405                 :         97 :         raid_bdev_cleanup(raid_bdev);
     406                 :         97 :         raid_bdev_free(raid_bdev);
     407                 :         97 : }
     408                 :            : 
     409                 :            : static void
     410                 :       2362 : raid_bdev_deconfigure_base_bdev(struct raid_base_bdev_info *base_info)
     411                 :            : {
     412   [ #  #  #  # ]:       2362 :         struct raid_bdev *raid_bdev = base_info->raid_bdev;
     413                 :            : 
     414   [ -  +  -  +  :       2362 :         assert(base_info->is_configured);
          #  #  #  #  #  
                      # ]
     415   [ -  +  #  #  :       2362 :         assert(raid_bdev->num_base_bdevs_discovered);
             #  #  #  # ]
     416         [ #  # ]:       2362 :         raid_bdev->num_base_bdevs_discovered--;
     417   [ #  #  #  # ]:       2362 :         base_info->is_configured = false;
     418   [ #  #  #  # ]:       2362 :         base_info->is_process_target = false;
     419                 :       2362 : }
     420                 :            : 
     421                 :            : /*
     422                 :            :  * brief:
     423                 :            :  * free resource of base bdev for raid bdev
     424                 :            :  * params:
     425                 :            :  * base_info - raid base bdev info
     426                 :            :  * returns:
     427                 :            :  * none
     428                 :            :  */
     429                 :            : static void
     430                 :       2739 : raid_bdev_free_base_bdev_resource(struct raid_base_bdev_info *base_info)
     431                 :            : {
     432   [ #  #  #  # ]:       2739 :         struct raid_bdev *raid_bdev = base_info->raid_bdev;
     433                 :            : 
     434   [ -  +  #  # ]:       2739 :         assert(spdk_get_thread() == spdk_thread_get_app_thread());
     435   [ -  +  #  #  :       2739 :         assert(base_info->configure_cb == NULL);
             #  #  #  # ]
     436                 :            : 
     437   [ #  #  #  # ]:       2739 :         free(base_info->name);
     438   [ #  #  #  # ]:       2739 :         base_info->name = NULL;
     439   [ +  +  #  #  :       2739 :         if (raid_bdev->state != RAID_BDEV_STATE_CONFIGURING) {
                   #  # ]
     440         [ #  # ]:       2148 :                 spdk_uuid_set_null(&base_info->uuid);
     441                 :          0 :         }
     442   [ #  #  #  # ]:       2739 :         base_info->is_failed = false;
     443                 :            : 
     444                 :            :         /* clear `data_offset` to allow it to be recalculated during configuration */
     445   [ #  #  #  # ]:       2739 :         base_info->data_offset = 0;
     446                 :            : 
     447   [ +  +  #  #  :       2739 :         if (base_info->desc == NULL) {
                   #  # ]
     448                 :        319 :                 return;
     449                 :            :         }
     450                 :            : 
     451   [ #  #  #  # ]:       2420 :         spdk_bdev_module_release_bdev(spdk_bdev_desc_get_bdev(base_info->desc));
     452   [ #  #  #  # ]:       2420 :         spdk_bdev_close(base_info->desc);
     453   [ #  #  #  # ]:       2420 :         base_info->desc = NULL;
     454   [ #  #  #  # ]:       2420 :         spdk_put_io_channel(base_info->app_thread_ch);
     455   [ #  #  #  # ]:       2420 :         base_info->app_thread_ch = NULL;
     456                 :            : 
     457   [ +  +  +  +  :       2420 :         if (base_info->is_configured) {
             #  #  #  # ]
     458                 :       2254 :                 raid_bdev_deconfigure_base_bdev(base_info);
     459                 :          0 :         }
     460                 :          0 : }
     461                 :            : 
     462                 :            : static void
     463                 :        329 : raid_bdev_io_device_unregister_cb(void *io_device)
     464                 :            : {
     465                 :        329 :         struct raid_bdev *raid_bdev = io_device;
     466                 :            : 
     467   [ +  +  #  #  :        329 :         if (raid_bdev->num_base_bdevs_discovered == 0) {
                   #  # ]
     468                 :            :                 /* Free raid_bdev when there are no base bdevs left */
     469   [ -  +  +  +  :        313 :                 SPDK_DEBUGLOG(bdev_raid, "raid bdev base bdevs is 0, going to free all in destruct\n");
                   #  # ]
     470                 :        313 :                 raid_bdev_cleanup(raid_bdev);
     471         [ #  # ]:        313 :                 spdk_bdev_destruct_done(&raid_bdev->bdev, 0);
     472                 :        313 :                 raid_bdev_free(raid_bdev);
     473                 :          0 :         } else {
     474         [ #  # ]:         16 :                 spdk_bdev_destruct_done(&raid_bdev->bdev, 0);
     475                 :            :         }
     476                 :        329 : }
     477                 :            : 
     478                 :            : void
     479                 :        329 : raid_bdev_module_stop_done(struct raid_bdev *raid_bdev)
     480                 :            : {
     481   [ +  -  #  #  :        329 :         if (raid_bdev->state != RAID_BDEV_STATE_CONFIGURING) {
                   #  # ]
     482                 :        329 :                 spdk_io_device_unregister(raid_bdev, raid_bdev_io_device_unregister_cb);
     483                 :          0 :         }
     484                 :        329 : }
     485                 :            : 
     486                 :            : static void
     487                 :        329 : _raid_bdev_destruct(void *ctxt)
     488                 :            : {
     489                 :        329 :         struct raid_bdev *raid_bdev = ctxt;
     490                 :            :         struct raid_base_bdev_info *base_info;
     491                 :            : 
     492   [ -  +  +  +  :        329 :         SPDK_DEBUGLOG(bdev_raid, "raid_bdev_destruct\n");
                   #  # ]
     493                 :            : 
     494   [ -  +  #  #  :        329 :         assert(raid_bdev->process == NULL);
             #  #  #  # ]
     495                 :            : 
     496   [ +  +  #  #  :       2385 :         RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) {
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     497                 :            :                 /*
     498                 :            :                  * Close all base bdev descriptors for which call has come from below
     499                 :            :                  * layers.  Also close the descriptors if we have started shutdown.
     500                 :            :                  */
     501   [ +  +  +  +  :       2056 :                 if (g_shutdown_started || base_info->remove_scheduled == true) {
          -  +  +  +  #  
                #  #  # ]
     502                 :       1991 :                         raid_bdev_free_base_bdev_resource(base_info);
     503                 :          0 :                 }
     504                 :          0 :         }
     505                 :            : 
     506   [ +  +  +  + ]:        329 :         if (g_shutdown_started) {
     507   [ #  #  #  # ]:        164 :                 raid_bdev->state = RAID_BDEV_STATE_OFFLINE;
     508                 :          0 :         }
     509                 :            : 
     510   [ +  +  #  #  :        329 :         if (raid_bdev->module->stop != NULL) {
          #  #  #  #  #  
                      # ]
     511   [ +  +  #  #  :        199 :                 if (raid_bdev->module->stop(raid_bdev) == false) {
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     512                 :        131 :                         return;
     513                 :            :                 }
     514                 :          0 :         }
     515                 :            : 
     516                 :        198 :         raid_bdev_module_stop_done(raid_bdev);
     517                 :          0 : }
     518                 :            : 
     519                 :            : static int
     520                 :        329 : raid_bdev_destruct(void *ctx)
     521                 :            : {
     522                 :        329 :         spdk_thread_exec_msg(spdk_thread_get_app_thread(), _raid_bdev_destruct, ctx);
     523                 :            : 
     524                 :        329 :         return 1;
     525                 :            : }
     526                 :            : 
     527                 :            : int
     528                 :          0 : raid_bdev_remap_dix_reftag(void *md_buf, uint64_t num_blocks,
     529                 :            :                            struct spdk_bdev *bdev, uint32_t remapped_offset)
     530                 :            : {
     531                 :          0 :         struct spdk_dif_ctx dif_ctx;
     532                 :          0 :         struct spdk_dif_error err_blk = {};
     533                 :            :         int rc;
     534                 :          0 :         struct spdk_dif_ctx_init_ext_opts dif_opts;
     535                 :          0 :         struct iovec md_iov = {
     536                 :          0 :                 .iov_base       = md_buf,
     537   [ #  #  #  # ]:          0 :                 .iov_len        = num_blocks * bdev->md_len,
     538                 :            :         };
     539                 :            : 
     540         [ #  # ]:          0 :         if (md_buf == NULL) {
     541                 :          0 :                 return 0;
     542                 :            :         }
     543                 :            : 
     544                 :          0 :         dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
     545   [ #  #  #  #  :          0 :         dif_opts.dif_pi_format = bdev->dif_pi_format;
                   #  # ]
     546                 :          0 :         rc = spdk_dif_ctx_init(&dif_ctx,
     547   [ #  #  #  #  :          0 :                                bdev->blocklen, bdev->md_len, bdev->md_interleave,
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     548   [ #  #  #  #  :          0 :                                bdev->dif_is_head_of_md, bdev->dif_type,
          #  #  #  #  #  
                      # ]
     549         [ #  # ]:          0 :                                SPDK_DIF_FLAGS_REFTAG_CHECK,
     550                 :            :                                0, 0, 0, 0, 0, &dif_opts);
     551         [ #  # ]:          0 :         if (rc != 0) {
     552                 :          0 :                 SPDK_ERRLOG("Initialization of DIF context failed\n");
     553                 :          0 :                 return rc;
     554                 :            :         }
     555                 :            : 
     556                 :          0 :         spdk_dif_ctx_set_remapped_init_ref_tag(&dif_ctx, remapped_offset);
     557                 :            : 
     558                 :          0 :         rc = spdk_dix_remap_ref_tag(&md_iov, num_blocks, &dif_ctx, &err_blk, false);
     559         [ #  # ]:          0 :         if (rc != 0) {
     560         [ #  # ]:          0 :                 SPDK_ERRLOG("Remapping reference tag failed. type=%d, offset=%d"
     561                 :            :                             PRIu32 "\n", err_blk.err_type, err_blk.err_offset);
     562                 :          0 :         }
     563                 :            : 
     564                 :          0 :         return rc;
     565                 :          0 : }
     566                 :            : 
     567                 :            : int
     568                 :          0 : raid_bdev_verify_dix_reftag(struct iovec *iovs, int iovcnt, void *md_buf,
     569                 :            :                             uint64_t num_blocks, struct spdk_bdev *bdev, uint32_t offset_blocks)
     570                 :            : {
     571                 :          0 :         struct spdk_dif_ctx dif_ctx;
     572                 :          0 :         struct spdk_dif_error err_blk = {};
     573                 :            :         int rc;
     574                 :          0 :         struct spdk_dif_ctx_init_ext_opts dif_opts;
     575                 :          0 :         struct iovec md_iov = {
     576                 :          0 :                 .iov_base       = md_buf,
     577   [ #  #  #  # ]:          0 :                 .iov_len        = num_blocks * bdev->md_len,
     578                 :            :         };
     579                 :            : 
     580         [ #  # ]:          0 :         if (md_buf == NULL) {
     581                 :          0 :                 return 0;
     582                 :            :         }
     583                 :            : 
     584                 :          0 :         dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
     585   [ #  #  #  #  :          0 :         dif_opts.dif_pi_format = bdev->dif_pi_format;
                   #  # ]
     586                 :          0 :         rc = spdk_dif_ctx_init(&dif_ctx,
     587   [ #  #  #  #  :          0 :                                bdev->blocklen, bdev->md_len, bdev->md_interleave,
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     588   [ #  #  #  #  :          0 :                                bdev->dif_is_head_of_md, bdev->dif_type,
          #  #  #  #  #  
                      # ]
     589         [ #  # ]:          0 :                                SPDK_DIF_FLAGS_REFTAG_CHECK,
     590                 :          0 :                                offset_blocks, 0, 0, 0, 0, &dif_opts);
     591         [ #  # ]:          0 :         if (rc != 0) {
     592                 :          0 :                 SPDK_ERRLOG("Initialization of DIF context failed\n");
     593                 :          0 :                 return rc;
     594                 :            :         }
     595                 :            : 
     596                 :          0 :         rc = spdk_dix_verify(iovs, iovcnt, &md_iov, num_blocks, &dif_ctx, &err_blk);
     597         [ #  # ]:          0 :         if (rc != 0) {
     598         [ #  # ]:          0 :                 SPDK_ERRLOG("Reference tag check failed. type=%d, offset=%d"
     599                 :            :                             PRIu32 "\n", err_blk.err_type, err_blk.err_offset);
     600                 :          0 :         }
     601                 :            : 
     602                 :          0 :         return rc;
     603                 :          0 : }
     604                 :            : 
     605                 :            : void
     606                 :   13754490 : raid_bdev_io_complete(struct raid_bdev_io *raid_io, enum spdk_bdev_io_status status)
     607                 :            : {
     608                 :   13754490 :         struct spdk_bdev_io *bdev_io = spdk_bdev_io_from_ctx(raid_io);
     609                 :            :         int rc;
     610                 :            : 
     611   [ +  +  -  +  :   13754490 :         spdk_trace_record(TRACE_BDEV_RAID_IO_DONE, 0, 0, (uintptr_t)raid_io, (uintptr_t)bdev_io);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     612                 :            : 
     613   [ +  +  #  #  :   13754490 :         if (raid_io->split.offset != RAID_OFFSET_BLOCKS_INVALID) {
             #  #  #  # ]
     614   [ #  #  #  #  :        230 :                 struct iovec *split_iov = raid_io->split.iov;
                   #  # ]
     615   [ #  #  #  # ]:        230 :                 const struct iovec *split_iov_orig = &raid_io->split.iov_copy;
     616                 :            : 
     617                 :            :                 /*
     618                 :            :                  * Non-zero offset here means that this is the completion of the first part of the
     619                 :            :                  * split I/O (the higher LBAs). Then, we submit the second part and set offset to 0.
     620                 :            :                  */
     621   [ +  +  #  #  :        230 :                 if (raid_io->split.offset != 0) {
             #  #  #  # ]
     622   [ #  #  #  #  :        115 :                         raid_io->offset_blocks = bdev_io->u.bdev.offset_blocks;
          #  #  #  #  #  
                #  #  # ]
     623   [ #  #  #  #  :        115 :                         raid_io->md_buf = bdev_io->u.bdev.md_buf;
          #  #  #  #  #  
                #  #  # ]
     624                 :            : 
     625         [ +  - ]:        115 :                         if (status == SPDK_BDEV_IO_STATUS_SUCCESS) {
     626   [ #  #  #  #  :        115 :                                 raid_io->num_blocks = raid_io->split.offset;
          #  #  #  #  #  
                      # ]
     627   [ #  #  #  #  :        115 :                                 raid_io->iovcnt = raid_io->iovs - bdev_io->u.bdev.iovs;
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     628   [ #  #  #  #  :        115 :                                 raid_io->iovs = bdev_io->u.bdev.iovs;
          #  #  #  #  #  
                #  #  # ]
     629         [ +  + ]:        115 :                                 if (split_iov != NULL) {
     630   [ #  #  #  # ]:        112 :                                         raid_io->iovcnt++;
     631   [ #  #  #  #  :        112 :                                         split_iov->iov_len = split_iov->iov_base - split_iov_orig->iov_base;
          #  #  #  #  #  
                #  #  # ]
     632   [ #  #  #  #  :        112 :                                         split_iov->iov_base = split_iov_orig->iov_base;
             #  #  #  # ]
     633                 :          0 :                                 }
     634                 :            : 
     635   [ #  #  #  #  :        115 :                                 raid_io->split.offset = 0;
                   #  # ]
     636   [ #  #  #  # ]:        115 :                                 raid_io->base_bdev_io_submitted = 0;
     637   [ #  #  #  #  :        115 :                                 raid_io->raid_ch = raid_io->raid_ch->process.ch_processed;
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     638                 :            : 
     639   [ #  #  #  #  :        115 :                                 raid_io->raid_bdev->module->submit_rw_request(raid_io);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     640                 :        115 :                                 return;
     641                 :            :                         }
     642                 :          0 :                 }
     643                 :            : 
     644   [ #  #  #  #  :        115 :                 raid_io->num_blocks = bdev_io->u.bdev.num_blocks;
          #  #  #  #  #  
                #  #  # ]
     645   [ #  #  #  #  :        115 :                 raid_io->iovcnt = bdev_io->u.bdev.iovcnt;
          #  #  #  #  #  
                #  #  # ]
     646   [ #  #  #  #  :        115 :                 raid_io->iovs = bdev_io->u.bdev.iovs;
          #  #  #  #  #  
                #  #  # ]
     647         [ +  + ]:        115 :                 if (split_iov != NULL) {
     648                 :        112 :                         *split_iov = *split_iov_orig;
     649                 :          0 :                 }
     650                 :          0 :         }
     651                 :            : 
     652   [ +  +  #  #  :   13754375 :         if (spdk_unlikely(raid_io->completion_cb != NULL)) {
                   #  # ]
     653   [ #  #  #  #  :       3327 :                 raid_io->completion_cb(raid_io, status);
             #  #  #  # ]
     654                 :          0 :         } else {
     655   [ +  +  -  +  :   13751048 :                 if (spdk_unlikely(bdev_io->type == SPDK_BDEV_IO_TYPE_READ &&
          -  +  -  -  -  
          +  -  -  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     656                 :            :                                   spdk_bdev_get_dif_type(bdev_io->bdev) != SPDK_DIF_DISABLE &&
     657                 :            :                                   bdev_io->bdev->dif_check_flags & SPDK_DIF_FLAGS_REFTAG_CHECK &&
     658                 :            :                                   status == SPDK_BDEV_IO_STATUS_SUCCESS)) {
     659                 :            : 
     660   [ #  #  #  #  :          0 :                         rc = raid_bdev_remap_dix_reftag(bdev_io->u.bdev.md_buf,
             #  #  #  # ]
     661   [ #  #  #  #  :          0 :                                                         bdev_io->u.bdev.num_blocks, bdev_io->bdev,
          #  #  #  #  #  
                #  #  # ]
     662   [ #  #  #  #  :          0 :                                                         bdev_io->u.bdev.offset_blocks);
             #  #  #  # ]
     663         [ #  # ]:          0 :                         if (rc != 0) {
     664                 :          0 :                                 status = SPDK_BDEV_IO_STATUS_FAILED;
     665                 :          0 :                         }
     666                 :          0 :                 }
     667                 :   13751048 :                 spdk_bdev_io_complete(bdev_io, status);
     668                 :            :         }
     669                 :          0 : }
     670                 :            : 
     671                 :            : /*
     672                 :            :  * brief:
     673                 :            :  * raid_bdev_io_complete_part - signal the completion of a part of the expected
     674                 :            :  * base bdev IOs and complete the raid_io if this is the final expected IO.
     675                 :            :  * The caller should first set raid_io->base_bdev_io_remaining. This function
     676                 :            :  * will decrement this counter by the value of the 'completed' parameter and
     677                 :            :  * complete the raid_io if the counter reaches 0. The caller is free to
     678                 :            :  * interpret the 'base_bdev_io_remaining' and 'completed' values as needed,
     679                 :            :  * it can represent e.g. blocks or IOs.
     680                 :            :  * params:
     681                 :            :  * raid_io - pointer to raid_bdev_io
     682                 :            :  * completed - the part of the raid_io that has been completed
     683                 :            :  * status - status of the base IO
     684                 :            :  * returns:
     685                 :            :  * true - if the raid_io is completed
     686                 :            :  * false - otherwise
     687                 :            :  */
     688                 :            : bool
     689                 :    3757167 : raid_bdev_io_complete_part(struct raid_bdev_io *raid_io, uint64_t completed,
     690                 :            :                            enum spdk_bdev_io_status status)
     691                 :            : {
     692   [ -  +  #  #  :    3757167 :         assert(raid_io->base_bdev_io_remaining >= completed);
             #  #  #  # ]
     693   [ #  #  #  # ]:    3757167 :         raid_io->base_bdev_io_remaining -= completed;
     694                 :            : 
     695   [ +  +  #  #  :    3757167 :         if (status != raid_io->base_bdev_io_status_default) {
                   #  # ]
     696   [ #  #  #  # ]:    1757565 :                 raid_io->base_bdev_io_status = status;
     697                 :          0 :         }
     698                 :            : 
     699   [ +  +  #  #  :    3757167 :         if (raid_io->base_bdev_io_remaining == 0) {
                   #  # ]
     700   [ #  #  #  # ]:    2132857 :                 raid_bdev_io_complete(raid_io, raid_io->base_bdev_io_status);
     701                 :    2132857 :                 return true;
     702                 :            :         } else {
     703                 :    1624310 :                 return false;
     704                 :            :         }
     705                 :          0 : }
     706                 :            : 
     707                 :            : /*
     708                 :            :  * brief:
     709                 :            :  * raid_bdev_queue_io_wait function processes the IO which failed to submit.
     710                 :            :  * It will try to queue the IOs after storing the context to bdev wait queue logic.
     711                 :            :  * params:
     712                 :            :  * raid_io - pointer to raid_bdev_io
     713                 :            :  * bdev - the block device that the IO is submitted to
     714                 :            :  * ch - io channel
     715                 :            :  * cb_fn - callback when the spdk_bdev_io for bdev becomes available
     716                 :            :  * returns:
     717                 :            :  * none
     718                 :            :  */
     719                 :            : void
     720                 :          0 : raid_bdev_queue_io_wait(struct raid_bdev_io *raid_io, struct spdk_bdev *bdev,
     721                 :            :                         struct spdk_io_channel *ch, spdk_bdev_io_wait_cb cb_fn)
     722                 :            : {
     723   [ #  #  #  #  :          0 :         raid_io->waitq_entry.bdev = bdev;
                   #  # ]
     724   [ #  #  #  #  :          0 :         raid_io->waitq_entry.cb_fn = cb_fn;
                   #  # ]
     725   [ #  #  #  #  :          0 :         raid_io->waitq_entry.cb_arg = raid_io;
                   #  # ]
     726         [ #  # ]:          0 :         spdk_bdev_queue_io_wait(bdev, ch, &raid_io->waitq_entry);
     727                 :          0 : }
     728                 :            : 
     729                 :            : static void
     730                 :        127 : raid_base_bdev_reset_complete(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
     731                 :            : {
     732                 :        127 :         struct raid_bdev_io *raid_io = cb_arg;
     733                 :            : 
     734                 :        127 :         spdk_bdev_free_io(bdev_io);
     735                 :            : 
     736         [ +  - ]:        127 :         raid_bdev_io_complete_part(raid_io, 1, success ?
     737                 :            :                                    SPDK_BDEV_IO_STATUS_SUCCESS :
     738                 :            :                                    SPDK_BDEV_IO_STATUS_FAILED);
     739                 :        127 : }
     740                 :            : 
     741                 :            : static void raid_bdev_submit_reset_request(struct raid_bdev_io *raid_io);
     742                 :            : 
     743                 :            : static void
     744                 :          0 : _raid_bdev_submit_reset_request(void *_raid_io)
     745                 :            : {
     746                 :          0 :         struct raid_bdev_io *raid_io = _raid_io;
     747                 :            : 
     748                 :          0 :         raid_bdev_submit_reset_request(raid_io);
     749                 :          0 : }
     750                 :            : 
     751                 :            : /*
     752                 :            :  * brief:
     753                 :            :  * raid_bdev_submit_reset_request function submits reset requests
     754                 :            :  * to member disks; it will submit as many as possible unless a reset fails with -ENOMEM, in
     755                 :            :  * which case it will queue it for later submission
     756                 :            :  * params:
     757                 :            :  * raid_io
     758                 :            :  * returns:
     759                 :            :  * none
     760                 :            :  */
     761                 :            : static void
     762                 :         18 : raid_bdev_submit_reset_request(struct raid_bdev_io *raid_io)
     763                 :            : {
     764                 :            :         struct raid_bdev                *raid_bdev;
     765                 :            :         int                             ret;
     766                 :            :         uint8_t                         i;
     767                 :            :         struct raid_base_bdev_info      *base_info;
     768                 :            :         struct spdk_io_channel          *base_ch;
     769                 :            : 
     770   [ #  #  #  # ]:         18 :         raid_bdev = raid_io->raid_bdev;
     771                 :            : 
     772   [ +  -  #  #  :         18 :         if (raid_io->base_bdev_io_remaining == 0) {
                   #  # ]
     773   [ #  #  #  #  :         18 :                 raid_io->base_bdev_io_remaining = raid_bdev->num_base_bdevs;
             #  #  #  # ]
     774                 :          0 :         }
     775                 :            : 
     776   [ +  +  #  #  :        145 :         for (i = raid_io->base_bdev_io_submitted; i < raid_bdev->num_base_bdevs; i++) {
          #  #  #  #  #  
                      # ]
     777   [ #  #  #  #  :        127 :                 base_info = &raid_bdev->base_bdev_info[i];
                   #  # ]
     778   [ #  #  #  #  :        127 :                 base_ch = raid_io->raid_ch->base_channel[i];
          #  #  #  #  #  
                #  #  # ]
     779         [ -  + ]:        127 :                 if (base_ch == NULL) {
     780         [ #  # ]:          0 :                         raid_io->base_bdev_io_submitted++;
     781                 :          0 :                         raid_bdev_io_complete_part(raid_io, 1, SPDK_BDEV_IO_STATUS_SUCCESS);
     782                 :          0 :                         continue;
     783                 :            :                 }
     784   [ #  #  #  # ]:        127 :                 ret = spdk_bdev_reset(base_info->desc, base_ch,
     785                 :          0 :                                       raid_base_bdev_reset_complete, raid_io);
     786         [ +  - ]:        127 :                 if (ret == 0) {
     787         [ #  # ]:        127 :                         raid_io->base_bdev_io_submitted++;
     788         [ #  # ]:          0 :                 } else if (ret == -ENOMEM) {
     789   [ #  #  #  # ]:          0 :                         raid_bdev_queue_io_wait(raid_io, spdk_bdev_desc_get_bdev(base_info->desc),
     790                 :          0 :                                                 base_ch, _raid_bdev_submit_reset_request);
     791                 :          0 :                         return;
     792                 :            :                 } else {
     793                 :          0 :                         SPDK_ERRLOG("bdev io submit error not due to ENOMEM, it should not happen\n");
     794         [ #  # ]:          0 :                         assert(false);
     795                 :            :                         raid_bdev_io_complete(raid_io, SPDK_BDEV_IO_STATUS_FAILED);
     796                 :            :                         return;
     797                 :            :                 }
     798                 :          0 :         }
     799                 :          0 : }
     800                 :            : 
     801                 :            : static void
     802                 :        115 : raid_bdev_io_split(struct raid_bdev_io *raid_io, uint64_t split_offset)
     803                 :            : {
     804   [ #  #  #  # ]:        115 :         struct raid_bdev *raid_bdev = raid_io->raid_bdev;
     805   [ #  #  #  #  :        115 :         size_t iov_offset = split_offset * raid_bdev->bdev.blocklen;
                   #  # ]
     806                 :            :         int i;
     807                 :            : 
     808   [ -  +  #  # ]:        115 :         assert(split_offset != 0);
     809   [ -  +  #  #  :        115 :         assert(raid_io->split.offset == RAID_OFFSET_BLOCKS_INVALID);
          #  #  #  #  #  
                      # ]
     810   [ #  #  #  #  :        115 :         raid_io->split.offset = split_offset;
                   #  # ]
     811                 :            : 
     812   [ #  #  #  # ]:        115 :         raid_io->offset_blocks += split_offset;
     813   [ #  #  #  # ]:        115 :         raid_io->num_blocks -= split_offset;
     814   [ +  +  #  #  :        115 :         if (raid_io->md_buf != NULL) {
                   #  # ]
     815   [ #  #  #  #  :         15 :                 raid_io->md_buf += (split_offset * raid_bdev->bdev.md_len);
          #  #  #  #  #  
                      # ]
     816                 :          0 :         }
     817                 :            : 
     818   [ +  -  #  #  :        136 :         for (i = 0; i < raid_io->iovcnt; i++) {
             #  #  #  # ]
     819   [ #  #  #  #  :        136 :                 struct iovec *iov = &raid_io->iovs[i];
                   #  # ]
     820                 :            : 
     821   [ +  +  #  #  :        136 :                 if (iov_offset < iov->iov_len) {
                   #  # ]
     822         [ +  + ]:        115 :                         if (iov_offset == 0) {
     823   [ #  #  #  #  :          3 :                                 raid_io->split.iov = NULL;
                   #  # ]
     824                 :          0 :                         } else {
     825   [ #  #  #  #  :        112 :                                 raid_io->split.iov = iov;
                   #  # ]
     826   [ #  #  #  # ]:        112 :                                 raid_io->split.iov_copy = *iov;
     827   [ #  #  #  # ]:        112 :                                 iov->iov_base += iov_offset;
     828   [ #  #  #  # ]:        112 :                                 iov->iov_len -= iov_offset;
     829                 :            :                         }
     830   [ #  #  #  #  :        115 :                         raid_io->iovs += i;
                   #  # ]
     831   [ #  #  #  #  :        115 :                         raid_io->iovcnt -= i;
                   #  # ]
     832                 :        115 :                         break;
     833                 :            :                 }
     834                 :            : 
     835   [ #  #  #  # ]:         21 :                 iov_offset -= iov->iov_len;
     836                 :          0 :         }
     837                 :        115 : }
     838                 :            : 
     839                 :            : static void
     840                 :   12641370 : raid_bdev_submit_rw_request(struct raid_bdev_io *raid_io)
     841                 :            : {
     842   [ #  #  #  # ]:   12641370 :         struct raid_bdev_io_channel *raid_ch = raid_io->raid_ch;
     843                 :            : 
     844   [ +  +  #  #  :   12641370 :         if (raid_ch->process.offset != RAID_OFFSET_BLOCKS_INVALID) {
             #  #  #  # ]
     845   [ #  #  #  # ]:       1634 :                 uint64_t offset_begin = raid_io->offset_blocks;
     846   [ #  #  #  # ]:       1634 :                 uint64_t offset_end = offset_begin + raid_io->num_blocks;
     847                 :            : 
     848   [ +  +  #  #  :       1634 :                 if (offset_end > raid_ch->process.offset) {
             #  #  #  # ]
     849   [ +  +  #  #  :       1191 :                         if (offset_begin < raid_ch->process.offset) {
             #  #  #  # ]
     850                 :            :                                 /*
     851                 :            :                                  * If the I/O spans both the processed and unprocessed ranges,
     852                 :            :                                  * split it and first handle the unprocessed part. After it
     853                 :            :                                  * completes, the rest will be handled.
     854                 :            :                                  * This situation occurs when the process thread is not active
     855                 :            :                                  * or is waiting for the process window range to be locked
     856                 :            :                                  * (quiesced). When a window is being processed, such I/Os will be
     857                 :            :                                  * deferred by the bdev layer until the window is unlocked.
     858                 :            :                                  */
     859   [ -  +  +  +  :        115 :                                 SPDK_DEBUGLOG(bdev_raid, "split: process_offset: %lu offset_begin: %lu offset_end: %lu\n",
          #  #  #  #  #  
                #  #  # ]
     860                 :            :                                               raid_ch->process.offset, offset_begin, offset_end);
     861   [ #  #  #  #  :        115 :                                 raid_bdev_io_split(raid_io, raid_ch->process.offset - offset_begin);
                   #  # ]
     862                 :          0 :                         }
     863                 :          0 :                 } else {
     864                 :            :                         /* Use the child channel, which corresponds to the already processed range */
     865   [ #  #  #  #  :        443 :                         raid_io->raid_ch = raid_ch->process.ch_processed;
          #  #  #  #  #  
                      # ]
     866                 :            :                 }
     867                 :          0 :         }
     868                 :            : 
     869   [ #  #  #  #  :   12641370 :         raid_io->raid_bdev->module->submit_rw_request(raid_io);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     870                 :   12641370 : }
     871                 :            : 
     872                 :            : /*
     873                 :            :  * brief:
     874                 :            :  * Callback function to spdk_bdev_io_get_buf.
     875                 :            :  * params:
     876                 :            :  * ch - pointer to raid bdev io channel
     877                 :            :  * bdev_io - pointer to parent bdev_io on raid bdev device
     878                 :            :  * success - True if buffer is allocated or false otherwise.
     879                 :            :  * returns:
     880                 :            :  * none
     881                 :            :  */
     882                 :            : static void
     883                 :    4994701 : raid_bdev_get_buf_cb(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io,
     884                 :            :                      bool success)
     885                 :            : {
     886         [ #  # ]:    4994701 :         struct raid_bdev_io *raid_io = (struct raid_bdev_io *)bdev_io->driver_ctx;
     887                 :            : 
     888   [ -  +  #  # ]:    4994701 :         if (!success) {
     889                 :          0 :                 raid_bdev_io_complete(raid_io, SPDK_BDEV_IO_STATUS_FAILED);
     890                 :          0 :                 return;
     891                 :            :         }
     892                 :            : 
     893                 :    4994701 :         raid_bdev_submit_rw_request(raid_io);
     894                 :          0 : }
     895                 :            : 
     896                 :            : void
     897                 :   13754363 : raid_bdev_io_init(struct raid_bdev_io *raid_io, struct raid_bdev_io_channel *raid_ch,
     898                 :            :                   enum spdk_bdev_io_type type, uint64_t offset_blocks,
     899                 :            :                   uint64_t num_blocks, struct iovec *iovs, int iovcnt, void *md_buf,
     900                 :            :                   struct spdk_memory_domain *memory_domain, void *memory_domain_ctx)
     901                 :            : {
     902                 :   13754363 :         struct spdk_io_channel *ch = spdk_io_channel_from_ctx(raid_ch);
     903                 :   13754363 :         struct raid_bdev *raid_bdev = spdk_io_channel_get_io_device(ch);
     904                 :            : 
     905   [ #  #  #  # ]:   13754363 :         raid_io->type = type;
     906   [ #  #  #  # ]:   13754363 :         raid_io->offset_blocks = offset_blocks;
     907   [ #  #  #  # ]:   13754363 :         raid_io->num_blocks = num_blocks;
     908   [ #  #  #  # ]:   13754363 :         raid_io->iovs = iovs;
     909   [ #  #  #  # ]:   13754363 :         raid_io->iovcnt = iovcnt;
     910   [ #  #  #  # ]:   13754363 :         raid_io->memory_domain = memory_domain;
     911   [ #  #  #  # ]:   13754363 :         raid_io->memory_domain_ctx = memory_domain_ctx;
     912   [ #  #  #  # ]:   13754363 :         raid_io->md_buf = md_buf;
     913                 :            : 
     914   [ #  #  #  # ]:   13754363 :         raid_io->raid_bdev = raid_bdev;
     915   [ #  #  #  # ]:   13754363 :         raid_io->raid_ch = raid_ch;
     916   [ #  #  #  # ]:   13754363 :         raid_io->base_bdev_io_remaining = 0;
     917   [ #  #  #  # ]:   13754363 :         raid_io->base_bdev_io_submitted = 0;
     918   [ #  #  #  # ]:   13754363 :         raid_io->completion_cb = NULL;
     919   [ #  #  #  #  :   13754363 :         raid_io->split.offset = RAID_OFFSET_BLOCKS_INVALID;
                   #  # ]
     920                 :            : 
     921                 :   13754363 :         raid_bdev_io_set_default_status(raid_io, SPDK_BDEV_IO_STATUS_SUCCESS);
     922                 :   13754363 : }
     923                 :            : 
     924                 :            : /*
     925                 :            :  * brief:
     926                 :            :  * raid_bdev_submit_request function is the submit_request function pointer of
     927                 :            :  * raid bdev function table. This is used to submit the io on raid_bdev to below
     928                 :            :  * layers.
     929                 :            :  * params:
     930                 :            :  * ch - pointer to raid bdev io channel
     931                 :            :  * bdev_io - pointer to parent bdev_io on raid bdev device
     932                 :            :  * returns:
     933                 :            :  * none
     934                 :            :  */
     935                 :            : static void
     936                 :   13751048 : raid_bdev_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
     937                 :            : {
     938         [ #  # ]:   13751048 :         struct raid_bdev_io *raid_io = (struct raid_bdev_io *)bdev_io->driver_ctx;
     939                 :            : 
     940   [ #  #  #  # ]:   13751048 :         raid_bdev_io_init(raid_io, spdk_io_channel_get_ctx(ch), bdev_io->type,
     941   [ #  #  #  #  :          0 :                           bdev_io->u.bdev.offset_blocks, bdev_io->u.bdev.num_blocks,
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     942   [ #  #  #  #  :          0 :                           bdev_io->u.bdev.iovs, bdev_io->u.bdev.iovcnt, bdev_io->u.bdev.md_buf,
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     943   [ #  #  #  #  :          0 :                           bdev_io->u.bdev.memory_domain, bdev_io->u.bdev.memory_domain_ctx);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     944                 :            : 
     945   [ +  +  -  +  :   13751048 :         spdk_trace_record(TRACE_BDEV_RAID_IO_START, 0, 0, (uintptr_t)raid_io, (uintptr_t)bdev_io);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     946                 :            : 
     947   [ +  +  +  +  :   13751048 :         switch (bdev_io->type) {
             -  #  #  #  
                      # ]
     948                 :    4994701 :         case SPDK_BDEV_IO_TYPE_READ:
     949                 :    4994701 :                 spdk_bdev_io_get_buf(bdev_io, raid_bdev_get_buf_cb,
     950   [ #  #  #  #  :    4994701 :                                      bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     951                 :    4994701 :                 break;
     952                 :    7646669 :         case SPDK_BDEV_IO_TYPE_WRITE:
     953                 :    7646669 :                 raid_bdev_submit_rw_request(raid_io);
     954                 :    7646669 :                 break;
     955                 :            : 
     956                 :         18 :         case SPDK_BDEV_IO_TYPE_RESET:
     957                 :         18 :                 raid_bdev_submit_reset_request(raid_io);
     958                 :         18 :                 break;
     959                 :            : 
     960                 :    1109660 :         case SPDK_BDEV_IO_TYPE_FLUSH:
     961                 :            :         case SPDK_BDEV_IO_TYPE_UNMAP:
     962   [ -  +  #  #  :    1109660 :                 if (raid_io->raid_bdev->process != NULL) {
          #  #  #  #  #  
                      # ]
     963                 :            :                         /* TODO: rebuild support */
     964                 :          0 :                         raid_bdev_io_complete(raid_io, SPDK_BDEV_IO_STATUS_FAILED);
     965                 :          0 :                         return;
     966                 :            :                 }
     967   [ #  #  #  #  :    1109660 :                 raid_io->raid_bdev->module->submit_null_payload_request(raid_io);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     968                 :    1109660 :                 break;
     969                 :            : 
     970                 :          0 :         default:
     971   [ #  #  #  # ]:          0 :                 SPDK_ERRLOG("submit request, invalid io type %u\n", bdev_io->type);
     972                 :          0 :                 raid_bdev_io_complete(raid_io, SPDK_BDEV_IO_STATUS_FAILED);
     973                 :          0 :                 break;
     974                 :            :         }
     975                 :          0 : }
     976                 :            : 
     977                 :            : /*
     978                 :            :  * brief:
     979                 :            :  * _raid_bdev_io_type_supported checks whether io_type is supported in
     980                 :            :  * all base bdev modules of raid bdev module. If anyone among the base_bdevs
     981                 :            :  * doesn't support, the raid device doesn't supports.
     982                 :            :  *
     983                 :            :  * params:
     984                 :            :  * raid_bdev - pointer to raid bdev context
     985                 :            :  * io_type - io type
     986                 :            :  * returns:
     987                 :            :  * true - io_type is supported
     988                 :            :  * false - io_type is not supported
     989                 :            :  */
     990                 :            : inline static bool
     991                 :       1174 : _raid_bdev_io_type_supported(struct raid_bdev *raid_bdev, enum spdk_bdev_io_type io_type)
     992                 :            : {
     993                 :            :         struct raid_base_bdev_info *base_info;
     994                 :            : 
     995   [ +  +  +  + ]:       1174 :         if (io_type == SPDK_BDEV_IO_TYPE_FLUSH ||
     996                 :          0 :             io_type == SPDK_BDEV_IO_TYPE_UNMAP) {
     997   [ +  +  #  #  :        975 :                 if (raid_bdev->module->submit_null_payload_request == NULL) {
          #  #  #  #  #  
                      # ]
     998                 :        212 :                         return false;
     999                 :            :                 }
    1000                 :          0 :         }
    1001                 :            : 
    1002   [ +  +  #  #  :       3187 :         RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) {
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
    1003   [ +  +  #  #  :       2232 :                 if (base_info->desc == NULL) {
                   #  # ]
    1004                 :          8 :                         continue;
    1005                 :            :                 }
    1006                 :            : 
    1007   [ +  +  #  #  :       2224 :                 if (spdk_bdev_io_type_supported(spdk_bdev_desc_get_bdev(base_info->desc), io_type) == false) {
                   #  # ]
    1008                 :          7 :                         return false;
    1009                 :            :                 }
    1010                 :          0 :         }
    1011                 :            : 
    1012                 :        955 :         return true;
    1013                 :          0 : }
    1014                 :            : 
    1015                 :            : /*
    1016                 :            :  * brief:
    1017                 :            :  * raid_bdev_io_type_supported is the io_supported function for bdev function
    1018                 :            :  * table which returns whether the particular io type is supported or not by
    1019                 :            :  * raid bdev module
    1020                 :            :  * params:
    1021                 :            :  * ctx - pointer to raid bdev context
    1022                 :            :  * type - io type
    1023                 :            :  * returns:
    1024                 :            :  * true - io_type is supported
    1025                 :            :  * false - io_type is not supported
    1026                 :            :  */
    1027                 :            : static bool
    1028                 :     450201 : raid_bdev_io_type_supported(void *ctx, enum spdk_bdev_io_type io_type)
    1029                 :            : {
    1030      [ +  +  + ]:     450201 :         switch (io_type) {
    1031                 :     148995 :         case SPDK_BDEV_IO_TYPE_READ:
    1032                 :            :         case SPDK_BDEV_IO_TYPE_WRITE:
    1033                 :     148995 :                 return true;
    1034                 :            : 
    1035                 :       1174 :         case SPDK_BDEV_IO_TYPE_FLUSH:
    1036                 :            :         case SPDK_BDEV_IO_TYPE_RESET:
    1037                 :            :         case SPDK_BDEV_IO_TYPE_UNMAP:
    1038                 :       1174 :                 return _raid_bdev_io_type_supported(ctx, io_type);
    1039                 :            : 
    1040                 :     300032 :         default:
    1041                 :     300032 :                 return false;
    1042                 :            :         }
    1043                 :            : 
    1044                 :            :         return false;
    1045                 :          0 : }
    1046                 :            : 
    1047                 :            : /*
    1048                 :            :  * brief:
    1049                 :            :  * raid_bdev_get_io_channel is the get_io_channel function table pointer for
    1050                 :            :  * raid bdev. This is used to return the io channel for this raid bdev
    1051                 :            :  * params:
    1052                 :            :  * ctxt - pointer to raid_bdev
    1053                 :            :  * returns:
    1054                 :            :  * pointer to io channel for raid bdev
    1055                 :            :  */
    1056                 :            : static struct spdk_io_channel *
    1057                 :        543 : raid_bdev_get_io_channel(void *ctxt)
    1058                 :            : {
    1059                 :        543 :         struct raid_bdev *raid_bdev = ctxt;
    1060                 :            : 
    1061                 :        543 :         return spdk_get_io_channel(raid_bdev);
    1062                 :            : }
    1063                 :            : 
    1064                 :            : void
    1065                 :       1613 : raid_bdev_write_info_json(struct raid_bdev *raid_bdev, struct spdk_json_write_ctx *w)
    1066                 :            : {
    1067                 :            :         struct raid_base_bdev_info *base_info;
    1068                 :            : 
    1069   [ -  +  #  # ]:       1613 :         assert(raid_bdev != NULL);
    1070   [ -  +  #  # ]:       1613 :         assert(spdk_get_thread() == spdk_thread_get_app_thread());
    1071                 :            : 
    1072   [ #  #  #  # ]:       1613 :         spdk_json_write_named_uuid(w, "uuid", &raid_bdev->bdev.uuid);
    1073   [ #  #  #  # ]:       1613 :         spdk_json_write_named_uint32(w, "strip_size_kb", raid_bdev->strip_size_kb);
    1074   [ #  #  #  # ]:       1613 :         spdk_json_write_named_string(w, "state", raid_bdev_state_to_str(raid_bdev->state));
    1075   [ #  #  #  # ]:       1613 :         spdk_json_write_named_string(w, "raid_level", raid_bdev_level_to_str(raid_bdev->level));
    1076   [ -  +  #  #  :       1613 :         spdk_json_write_named_bool(w, "superblock", raid_bdev->superblock_enabled);
                   #  # ]
    1077   [ #  #  #  # ]:       1613 :         spdk_json_write_named_uint32(w, "num_base_bdevs", raid_bdev->num_base_bdevs);
    1078   [ #  #  #  # ]:       1613 :         spdk_json_write_named_uint32(w, "num_base_bdevs_discovered", raid_bdev->num_base_bdevs_discovered);
    1079                 :       1613 :         spdk_json_write_named_uint32(w, "num_base_bdevs_operational",
    1080   [ #  #  #  # ]:       1613 :                                      raid_bdev->num_base_bdevs_operational);
    1081   [ +  +  #  #  :       1613 :         if (raid_bdev->process) {
                   #  # ]
    1082   [ #  #  #  # ]:        106 :                 struct raid_bdev_process *process = raid_bdev->process;
    1083   [ #  #  #  # ]:        106 :                 uint64_t offset = process->window_offset;
    1084                 :            : 
    1085                 :        106 :                 spdk_json_write_named_object_begin(w, "process");
    1086                 :        106 :                 spdk_json_write_name(w, "type");
    1087   [ #  #  #  # ]:        106 :                 spdk_json_write_string(w, raid_bdev_process_to_str(process->type));
    1088   [ #  #  #  #  :        106 :                 spdk_json_write_named_string(w, "target", process->target->name);
             #  #  #  # ]
    1089                 :        106 :                 spdk_json_write_named_object_begin(w, "progress");
    1090                 :        106 :                 spdk_json_write_named_uint64(w, "blocks", offset);
    1091   [ #  #  #  #  :        106 :                 spdk_json_write_named_uint32(w, "percent", offset * 100.0 / raid_bdev->bdev.blockcnt);
             #  #  #  # ]
    1092                 :        106 :                 spdk_json_write_object_end(w);
    1093                 :        106 :                 spdk_json_write_object_end(w);
    1094                 :          0 :         }
    1095                 :       1613 :         spdk_json_write_name(w, "base_bdevs_list");
    1096                 :       1613 :         spdk_json_write_array_begin(w);
    1097   [ +  +  #  #  :       7173 :         RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) {
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
    1098                 :       5560 :                 spdk_json_write_object_begin(w);
    1099                 :       5560 :                 spdk_json_write_name(w, "name");
    1100   [ +  +  #  #  :       5560 :                 if (base_info->name) {
                   #  # ]
    1101   [ #  #  #  # ]:       4555 :                         spdk_json_write_string(w, base_info->name);
    1102                 :          0 :                 } else {
    1103                 :       1005 :                         spdk_json_write_null(w);
    1104                 :            :                 }
    1105         [ #  # ]:       5560 :                 spdk_json_write_named_uuid(w, "uuid", &base_info->uuid);
    1106   [ -  +  #  #  :       5560 :                 spdk_json_write_named_bool(w, "is_configured", base_info->is_configured);
                   #  # ]
    1107   [ #  #  #  # ]:       5560 :                 spdk_json_write_named_uint64(w, "data_offset", base_info->data_offset);
    1108   [ #  #  #  # ]:       5560 :                 spdk_json_write_named_uint64(w, "data_size", base_info->data_size);
    1109                 :       5560 :                 spdk_json_write_object_end(w);
    1110                 :          0 :         }
    1111                 :       1613 :         spdk_json_write_array_end(w);
    1112                 :       1613 : }
    1113                 :            : 
    1114                 :            : /*
    1115                 :            :  * brief:
    1116                 :            :  * raid_bdev_dump_info_json is the function table pointer for raid bdev
    1117                 :            :  * params:
    1118                 :            :  * ctx - pointer to raid_bdev
    1119                 :            :  * w - pointer to json context
    1120                 :            :  * returns:
    1121                 :            :  * 0 - success
    1122                 :            :  * non zero - failure
    1123                 :            :  */
    1124                 :            : static int
    1125                 :        186 : raid_bdev_dump_info_json(void *ctx, struct spdk_json_write_ctx *w)
    1126                 :            : {
    1127                 :        186 :         struct raid_bdev *raid_bdev = ctx;
    1128                 :            : 
    1129   [ -  +  +  +  :        186 :         SPDK_DEBUGLOG(bdev_raid, "raid_bdev_dump_config_json\n");
                   #  # ]
    1130                 :            : 
    1131                 :            :         /* Dump the raid bdev configuration related information */
    1132                 :        186 :         spdk_json_write_named_object_begin(w, "raid");
    1133                 :        186 :         raid_bdev_write_info_json(raid_bdev, w);
    1134                 :        186 :         spdk_json_write_object_end(w);
    1135                 :            : 
    1136                 :        186 :         return 0;
    1137                 :            : }
    1138                 :            : 
    1139                 :            : /*
    1140                 :            :  * brief:
    1141                 :            :  * raid_bdev_write_config_json is the function table pointer for raid bdev
    1142                 :            :  * params:
    1143                 :            :  * bdev - pointer to spdk_bdev
    1144                 :            :  * w - pointer to json context
    1145                 :            :  * returns:
    1146                 :            :  * none
    1147                 :            :  */
    1148                 :            : static void
    1149                 :         13 : raid_bdev_write_config_json(struct spdk_bdev *bdev, struct spdk_json_write_ctx *w)
    1150                 :            : {
    1151   [ #  #  #  # ]:         13 :         struct raid_bdev *raid_bdev = bdev->ctxt;
    1152                 :            :         struct raid_base_bdev_info *base_info;
    1153                 :            : 
    1154   [ -  +  #  # ]:         13 :         assert(spdk_get_thread() == spdk_thread_get_app_thread());
    1155                 :            : 
    1156   [ -  +  -  +  :         13 :         if (raid_bdev->superblock_enabled) {
             #  #  #  # ]
    1157                 :            :                 /* raid bdev configuration is stored in the superblock */
    1158                 :          0 :                 return;
    1159                 :            :         }
    1160                 :            : 
    1161                 :         13 :         spdk_json_write_object_begin(w);
    1162                 :            : 
    1163                 :         13 :         spdk_json_write_named_string(w, "method", "bdev_raid_create");
    1164                 :            : 
    1165                 :         13 :         spdk_json_write_named_object_begin(w, "params");
    1166   [ #  #  #  # ]:         13 :         spdk_json_write_named_string(w, "name", bdev->name);
    1167   [ #  #  #  # ]:         13 :         spdk_json_write_named_uuid(w, "uuid", &raid_bdev->bdev.uuid);
    1168   [ +  +  #  #  :         13 :         if (raid_bdev->strip_size_kb != 0) {
                   #  # ]
    1169   [ #  #  #  # ]:          9 :                 spdk_json_write_named_uint32(w, "strip_size_kb", raid_bdev->strip_size_kb);
    1170                 :          0 :         }
    1171   [ #  #  #  # ]:         13 :         spdk_json_write_named_string(w, "raid_level", raid_bdev_level_to_str(raid_bdev->level));
    1172                 :            : 
    1173                 :         13 :         spdk_json_write_named_array_begin(w, "base_bdevs");
    1174   [ +  +  #  #  :         40 :         RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) {
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
    1175   [ +  -  #  #  :         27 :                 if (base_info->name) {
                   #  # ]
    1176   [ #  #  #  # ]:         27 :                         spdk_json_write_string(w, base_info->name);
    1177                 :          0 :                 } else {
    1178                 :          0 :                         char str[32];
    1179                 :            : 
    1180         [ #  # ]:          0 :                         snprintf(str, sizeof(str), "removed_base_bdev_%u", raid_bdev_base_bdev_slot(base_info));
    1181                 :          0 :                         spdk_json_write_string(w, str);
    1182                 :            :                 }
    1183                 :          0 :         }
    1184                 :         13 :         spdk_json_write_array_end(w);
    1185                 :         13 :         spdk_json_write_object_end(w);
    1186                 :            : 
    1187                 :         13 :         spdk_json_write_object_end(w);
    1188                 :          0 : }
    1189                 :            : 
    1190                 :            : static int
    1191                 :       2445 : raid_bdev_get_memory_domains(void *ctx, struct spdk_memory_domain **domains, int array_size)
    1192                 :            : {
    1193                 :       2445 :         struct raid_bdev *raid_bdev = ctx;
    1194                 :            :         struct raid_base_bdev_info *base_info;
    1195                 :       2445 :         int domains_count = 0, rc = 0;
    1196                 :            : 
    1197   [ -  +  +  +  :       2445 :         if (raid_bdev->module->memory_domains_supported == false) {
          #  #  #  #  #  
                #  #  # ]
    1198                 :        217 :                 return 0;
    1199                 :            :         }
    1200                 :            : 
    1201                 :            :         /* First loop to get the number of memory domains */
    1202   [ +  +  #  #  :       7456 :         RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) {
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
    1203   [ -  +  +  +  :       5228 :                 if (base_info->is_configured == false) {
             #  #  #  # ]
    1204                 :         86 :                         continue;
    1205                 :            :                 }
    1206   [ #  #  #  # ]:       5142 :                 rc = spdk_bdev_get_memory_domains(spdk_bdev_desc_get_bdev(base_info->desc), NULL, 0);
    1207         [ -  + ]:       5142 :                 if (rc < 0) {
    1208                 :          0 :                         return rc;
    1209                 :            :                 }
    1210         [ #  # ]:       5142 :                 domains_count += rc;
    1211                 :          0 :         }
    1212                 :            : 
    1213   [ +  +  -  + ]:       2228 :         if (!domains || array_size < domains_count) {
    1214                 :       2071 :                 return domains_count;
    1215                 :            :         }
    1216                 :            : 
    1217   [ +  +  #  #  :        555 :         RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) {
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
    1218   [ -  +  +  +  :        398 :                 if (base_info->is_configured == false) {
             #  #  #  # ]
    1219                 :          6 :                         continue;
    1220                 :            :                 }
    1221   [ #  #  #  # ]:        392 :                 rc = spdk_bdev_get_memory_domains(spdk_bdev_desc_get_bdev(base_info->desc), domains, array_size);
    1222         [ -  + ]:        392 :                 if (rc < 0) {
    1223                 :          0 :                         return rc;
    1224                 :            :                 }
    1225         [ #  # ]:        392 :                 domains += rc;
    1226         [ #  # ]:        392 :                 array_size -= rc;
    1227                 :          0 :         }
    1228                 :            : 
    1229                 :        157 :         return domains_count;
    1230                 :          0 : }
    1231                 :            : 
    1232                 :            : /* g_raid_bdev_fn_table is the function table for raid bdev */
    1233                 :            : static const struct spdk_bdev_fn_table g_raid_bdev_fn_table = {
    1234                 :            :         .destruct               = raid_bdev_destruct,
    1235                 :            :         .submit_request         = raid_bdev_submit_request,
    1236                 :            :         .io_type_supported      = raid_bdev_io_type_supported,
    1237                 :            :         .get_io_channel         = raid_bdev_get_io_channel,
    1238                 :            :         .dump_info_json         = raid_bdev_dump_info_json,
    1239                 :            :         .write_config_json      = raid_bdev_write_config_json,
    1240                 :            :         .get_memory_domains     = raid_bdev_get_memory_domains,
    1241                 :            : };
    1242                 :            : 
    1243                 :            : struct raid_bdev *
    1244                 :        694 : raid_bdev_find_by_name(const char *name)
    1245                 :            : {
    1246                 :            :         struct raid_bdev *raid_bdev;
    1247                 :            : 
    1248   [ +  +  #  #  :        844 :         TAILQ_FOREACH(raid_bdev, &g_raid_bdev_list, global_link) {
             #  #  #  # ]
    1249   [ +  +  -  +  :        425 :                 if (strcmp(raid_bdev->bdev.name, name) == 0) {
          +  +  #  #  #  
                #  #  # ]
    1250                 :        275 :                         return raid_bdev;
    1251                 :            :                 }
    1252                 :          0 :         }
    1253                 :            : 
    1254                 :        419 :         return NULL;
    1255                 :          0 : }
    1256                 :            : 
    1257                 :            : static struct raid_bdev *
    1258                 :        224 : raid_bdev_find_by_uuid(const struct spdk_uuid *uuid)
    1259                 :            : {
    1260                 :            :         struct raid_bdev *raid_bdev;
    1261                 :            : 
    1262   [ +  +  #  #  :        224 :         TAILQ_FOREACH(raid_bdev, &g_raid_bdev_list, global_link) {
             #  #  #  # ]
    1263   [ +  -  #  #  :        183 :                 if (spdk_uuid_compare(&raid_bdev->bdev.uuid, uuid) == 0) {
                   #  # ]
    1264                 :        183 :                         return raid_bdev;
    1265                 :            :                 }
    1266                 :          0 :         }
    1267                 :            : 
    1268                 :         41 :         return NULL;
    1269                 :          0 : }
    1270                 :            : 
    1271                 :            : static struct {
    1272                 :            :         const char *name;
    1273                 :            :         enum raid_level value;
    1274                 :            : } g_raid_level_names[] = {
    1275                 :            :         { "raid0", RAID0 },
    1276                 :            :         { "0", RAID0 },
    1277                 :            :         { "raid1", RAID1 },
    1278                 :            :         { "1", RAID1 },
    1279                 :            :         { "raid5f", RAID5F },
    1280                 :            :         { "5f", RAID5F },
    1281                 :            :         { "concat", CONCAT },
    1282                 :            :         { }
    1283                 :            : };
    1284                 :            : 
    1285                 :            : const char *g_raid_state_names[] = {
    1286                 :            :         [RAID_BDEV_STATE_ONLINE]        = "online",
    1287                 :            :         [RAID_BDEV_STATE_CONFIGURING]   = "configuring",
    1288                 :            :         [RAID_BDEV_STATE_OFFLINE]       = "offline",
    1289                 :            :         [RAID_BDEV_STATE_MAX]           = NULL
    1290                 :            : };
    1291                 :            : 
    1292                 :            : static const char *g_raid_process_type_names[] = {
    1293                 :            :         [RAID_PROCESS_NONE]     = "none",
    1294                 :            :         [RAID_PROCESS_REBUILD]  = "rebuild",
    1295                 :            :         [RAID_PROCESS_MAX]      = NULL
    1296                 :            : };
    1297                 :            : 
    1298                 :            : /* We have to use the typedef in the function declaration to appease astyle. */
    1299                 :            : typedef enum raid_level raid_level_t;
    1300                 :            : typedef enum raid_bdev_state raid_bdev_state_t;
    1301                 :            : 
    1302                 :            : raid_level_t
    1303                 :        322 : raid_bdev_str_to_level(const char *str)
    1304                 :            : {
    1305                 :            :         unsigned int i;
    1306                 :            : 
    1307   [ -  +  #  # ]:        322 :         assert(str != NULL);
    1308                 :            : 
    1309   [ +  +  #  #  :       1192 :         for (i = 0; g_raid_level_names[i].name != NULL; i++) {
          #  #  #  #  #  
                      # ]
    1310   [ +  +  -  +  :       1189 :                 if (strcasecmp(g_raid_level_names[i].name, str) == 0) {
          +  +  #  #  #  
             #  #  #  #  
                      # ]
    1311   [ #  #  #  #  :        319 :                         return g_raid_level_names[i].value;
             #  #  #  # ]
    1312                 :            :                 }
    1313                 :          0 :         }
    1314                 :            : 
    1315                 :          3 :         return INVALID_RAID_LEVEL;
    1316                 :          0 : }
    1317                 :            : 
    1318                 :            : const char *
    1319                 :       1638 : raid_bdev_level_to_str(enum raid_level level)
    1320                 :            : {
    1321                 :            :         unsigned int i;
    1322                 :            : 
    1323   [ +  +  #  #  :       6156 :         for (i = 0; g_raid_level_names[i].name != NULL; i++) {
          #  #  #  #  #  
                      # ]
    1324   [ +  +  #  #  :       6126 :                 if (g_raid_level_names[i].value == level) {
          #  #  #  #  #  
                      # ]
    1325   [ #  #  #  #  :       1608 :                         return g_raid_level_names[i].name;
             #  #  #  # ]
    1326                 :            :                 }
    1327                 :          0 :         }
    1328                 :            : 
    1329                 :         30 :         return "";
    1330                 :          0 : }
    1331                 :            : 
    1332                 :            : raid_bdev_state_t
    1333                 :       1511 : raid_bdev_str_to_state(const char *str)
    1334                 :            : {
    1335                 :            :         unsigned int i;
    1336                 :            : 
    1337   [ -  +  #  # ]:       1511 :         assert(str != NULL);
    1338                 :            : 
    1339         [ +  + ]:       4722 :         for (i = 0; i < RAID_BDEV_STATE_MAX; i++) {
    1340   [ +  +  -  +  :       3745 :                 if (strcasecmp(g_raid_state_names[i], str) == 0) {
          +  +  #  #  #  
                #  #  # ]
    1341                 :        534 :                         break;
    1342                 :            :                 }
    1343                 :          0 :         }
    1344                 :            : 
    1345                 :       1511 :         return i;
    1346                 :            : }
    1347                 :            : 
    1348                 :            : const char *
    1349                 :       1821 : raid_bdev_state_to_str(enum raid_bdev_state state)
    1350                 :            : {
    1351         [ -  + ]:       1821 :         if (state >= RAID_BDEV_STATE_MAX) {
    1352                 :          0 :                 return "";
    1353                 :            :         }
    1354                 :            : 
    1355   [ #  #  #  #  :       1821 :         return g_raid_state_names[state];
                   #  # ]
    1356                 :          0 : }
    1357                 :            : 
    1358                 :            : const char *
    1359                 :        271 : raid_bdev_process_to_str(enum raid_process_type value)
    1360                 :            : {
    1361         [ -  + ]:        271 :         if (value >= RAID_PROCESS_MAX) {
    1362                 :          0 :                 return "";
    1363                 :            :         }
    1364                 :            : 
    1365   [ #  #  #  #  :        271 :         return g_raid_process_type_names[value];
                   #  # ]
    1366                 :          0 : }
    1367                 :            : 
    1368                 :            : /*
    1369                 :            :  * brief:
    1370                 :            :  * raid_bdev_fini_start is called when bdev layer is starting the
    1371                 :            :  * shutdown process
    1372                 :            :  * params:
    1373                 :            :  * none
    1374                 :            :  * returns:
    1375                 :            :  * none
    1376                 :            :  */
    1377                 :            : static void
    1378                 :       1935 : raid_bdev_fini_start(void)
    1379                 :            : {
    1380                 :            :         struct raid_bdev *raid_bdev;
    1381                 :            :         struct raid_base_bdev_info *base_info;
    1382                 :            : 
    1383   [ +  +  +  +  :       1935 :         SPDK_DEBUGLOG(bdev_raid, "raid_bdev_fini_start\n");
                   +  - ]
    1384                 :            : 
    1385   [ +  +  #  #  :       2099 :         TAILQ_FOREACH(raid_bdev, &g_raid_bdev_list, global_link) {
             #  #  #  # ]
    1386   [ -  +  #  #  :        164 :                 if (raid_bdev->state != RAID_BDEV_STATE_ONLINE) {
                   #  # ]
    1387   [ #  #  #  #  :          0 :                         RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) {
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
    1388                 :          0 :                                 raid_bdev_free_base_bdev_resource(base_info);
    1389                 :          0 :                         }
    1390                 :          0 :                 }
    1391                 :          0 :         }
    1392                 :            : 
    1393                 :       1935 :         g_shutdown_started = true;
    1394                 :       1935 : }
    1395                 :            : 
    1396                 :            : /*
    1397                 :            :  * brief:
    1398                 :            :  * raid_bdev_exit is called on raid bdev module exit time by bdev layer
    1399                 :            :  * params:
    1400                 :            :  * none
    1401                 :            :  * returns:
    1402                 :            :  * none
    1403                 :            :  */
    1404                 :            : static void
    1405                 :       1971 : raid_bdev_exit(void)
    1406                 :            : {
    1407                 :            :         struct raid_bdev *raid_bdev, *tmp;
    1408                 :            : 
    1409   [ +  +  +  +  :       1971 :         SPDK_DEBUGLOG(bdev_raid, "raid_bdev_exit\n");
                   +  - ]
    1410                 :            : 
    1411   [ +  +  #  #  :       1971 :         TAILQ_FOREACH_SAFE(raid_bdev, &g_raid_bdev_list, global_link, tmp) {
          #  #  #  #  -  
                      + ]
    1412                 :          0 :                 raid_bdev_cleanup_and_free(raid_bdev);
    1413                 :          0 :         }
    1414                 :       1971 : }
    1415                 :            : 
    1416                 :            : static void
    1417                 :        165 : raid_bdev_opts_config_json(struct spdk_json_write_ctx *w)
    1418                 :            : {
    1419                 :        165 :         spdk_json_write_object_begin(w);
    1420                 :            : 
    1421                 :        165 :         spdk_json_write_named_string(w, "method", "bdev_raid_set_options");
    1422                 :            : 
    1423                 :        165 :         spdk_json_write_named_object_begin(w, "params");
    1424                 :        165 :         spdk_json_write_named_uint32(w, "process_window_size_kb", g_opts.process_window_size_kb);
    1425                 :        165 :         spdk_json_write_named_uint32(w, "process_max_bandwidth_mb_sec",
    1426         [ +  - ]:          1 :                                      g_opts.process_max_bandwidth_mb_sec);
    1427                 :        165 :         spdk_json_write_object_end(w);
    1428                 :            : 
    1429                 :        165 :         spdk_json_write_object_end(w);
    1430                 :        165 : }
    1431                 :            : 
    1432                 :            : static int
    1433                 :        165 : raid_bdev_config_json(struct spdk_json_write_ctx *w)
    1434                 :            : {
    1435                 :        165 :         raid_bdev_opts_config_json(w);
    1436                 :            : 
    1437                 :        165 :         return 0;
    1438                 :            : }
    1439                 :            : 
    1440                 :            : /*
    1441                 :            :  * brief:
    1442                 :            :  * raid_bdev_get_ctx_size is used to return the context size of bdev_io for raid
    1443                 :            :  * module
    1444                 :            :  * params:
    1445                 :            :  * none
    1446                 :            :  * returns:
    1447                 :            :  * size of spdk_bdev_io context for raid
    1448                 :            :  */
    1449                 :            : static int
    1450                 :       3433 : raid_bdev_get_ctx_size(void)
    1451                 :            : {
    1452   [ +  +  +  +  :       3433 :         SPDK_DEBUGLOG(bdev_raid, "raid_bdev_get_ctx_size\n");
                   +  - ]
    1453                 :       3433 :         return sizeof(struct raid_bdev_io);
    1454                 :            : }
    1455                 :            : 
    1456                 :            : static struct spdk_bdev_module g_raid_if = {
    1457                 :            :         .name = "raid",
    1458                 :            :         .module_init = raid_bdev_init,
    1459                 :            :         .fini_start = raid_bdev_fini_start,
    1460                 :            :         .module_fini = raid_bdev_exit,
    1461                 :            :         .config_json = raid_bdev_config_json,
    1462                 :            :         .get_ctx_size = raid_bdev_get_ctx_size,
    1463                 :            :         .examine_disk = raid_bdev_examine,
    1464                 :            :         .async_init = false,
    1465                 :            :         .async_fini = false,
    1466                 :            : };
    1467                 :       2122 : SPDK_BDEV_MODULE_REGISTER(raid, &g_raid_if)
    1468                 :            : 
    1469                 :            : /*
    1470                 :            :  * brief:
    1471                 :            :  * raid_bdev_init is the initialization function for raid bdev module
    1472                 :            :  * params:
    1473                 :            :  * none
    1474                 :            :  * returns:
    1475                 :            :  * 0 - success
    1476                 :            :  * non zero - failure
    1477                 :            :  */
    1478                 :            : static int
    1479                 :       1971 : raid_bdev_init(void)
    1480                 :            : {
    1481                 :       1971 :         return 0;
    1482                 :            : }
    1483                 :            : 
    1484                 :            : static int
    1485                 :        419 : _raid_bdev_create(const char *name, uint32_t strip_size, uint8_t num_base_bdevs,
    1486                 :            :                   enum raid_level level, bool superblock_enabled, const struct spdk_uuid *uuid,
    1487                 :            :                   struct raid_bdev **raid_bdev_out)
    1488                 :            : {
    1489                 :            :         struct raid_bdev *raid_bdev;
    1490                 :            :         struct spdk_bdev *raid_bdev_gen;
    1491                 :            :         struct raid_bdev_module *module;
    1492                 :            :         struct raid_base_bdev_info *base_info;
    1493                 :            :         uint8_t min_operational;
    1494                 :            : 
    1495   [ -  +  -  + ]:        419 :         if (strnlen(name, RAID_BDEV_SB_NAME_SIZE) == RAID_BDEV_SB_NAME_SIZE) {
    1496                 :          0 :                 SPDK_ERRLOG("Raid bdev name '%s' exceeds %d characters\n", name, RAID_BDEV_SB_NAME_SIZE - 1);
    1497                 :          0 :                 return -EINVAL;
    1498                 :            :         }
    1499                 :            : 
    1500         [ +  + ]:        419 :         if (raid_bdev_find_by_name(name) != NULL) {
    1501                 :          3 :                 SPDK_ERRLOG("Duplicate raid bdev name found: %s\n", name);
    1502                 :          3 :                 return -EEXIST;
    1503                 :            :         }
    1504                 :            : 
    1505         [ +  + ]:        416 :         if (level == RAID1) {
    1506         [ -  + ]:        131 :                 if (strip_size != 0) {
    1507                 :          0 :                         SPDK_ERRLOG("Strip size is not supported by raid1\n");
    1508                 :          0 :                         return -EINVAL;
    1509                 :            :                 }
    1510         [ +  + ]:        285 :         } else if (spdk_u32_is_pow2(strip_size) == false) {
    1511                 :          3 :                 SPDK_ERRLOG("Invalid strip size %" PRIu32 "\n", strip_size);
    1512                 :          3 :                 return -EINVAL;
    1513                 :            :         }
    1514                 :            : 
    1515                 :        413 :         module = raid_bdev_module_find(level);
    1516         [ +  + ]:        413 :         if (module == NULL) {
    1517                 :          3 :                 SPDK_ERRLOG("Unsupported raid level '%d'\n", level);
    1518                 :          3 :                 return -EINVAL;
    1519                 :            :         }
    1520                 :            : 
    1521   [ -  +  #  #  :        410 :         assert(module->base_bdevs_min != 0);
             #  #  #  # ]
    1522   [ -  +  #  #  :        410 :         if (num_base_bdevs < module->base_bdevs_min) {
                   #  # ]
    1523   [ #  #  #  # ]:          0 :                 SPDK_ERRLOG("At least %u base devices required for %s\n",
    1524                 :            :                             module->base_bdevs_min,
    1525                 :            :                             raid_bdev_level_to_str(level));
    1526                 :          0 :                 return -EINVAL;
    1527                 :            :         }
    1528                 :            : 
    1529   [ +  +  +  -  :        410 :         switch (module->base_bdevs_constraint.type) {
          #  #  #  #  #  
                      # ]
    1530                 :         42 :         case CONSTRAINT_MAX_BASE_BDEVS_REMOVED:
    1531   [ #  #  #  #  :         42 :                 min_operational = num_base_bdevs - module->base_bdevs_constraint.value;
                   #  # ]
    1532                 :         42 :                 break;
    1533                 :        131 :         case CONSTRAINT_MIN_BASE_BDEVS_OPERATIONAL:
    1534   [ #  #  #  #  :        131 :                 min_operational = module->base_bdevs_constraint.value;
                   #  # ]
    1535                 :        131 :                 break;
    1536                 :        237 :         case CONSTRAINT_UNSET:
    1537   [ -  +  #  #  :        237 :                 if (module->base_bdevs_constraint.value != 0) {
             #  #  #  # ]
    1538   [ #  #  #  #  :          0 :                         SPDK_ERRLOG("Unexpected constraint value '%u' provided for raid bdev '%s'.\n",
                   #  # ]
    1539                 :            :                                     (uint8_t)module->base_bdevs_constraint.value, name);
    1540                 :          0 :                         return -EINVAL;
    1541                 :            :                 }
    1542                 :        237 :                 min_operational = num_base_bdevs;
    1543                 :        237 :                 break;
    1544                 :          0 :         default:
    1545   [ #  #  #  #  :          0 :                 SPDK_ERRLOG("Unrecognised constraint type '%u' in module for raid level '%s'.\n",
          #  #  #  #  #  
                      # ]
    1546                 :            :                             (uint8_t)module->base_bdevs_constraint.type,
    1547                 :            :                             raid_bdev_level_to_str(module->level));
    1548                 :          0 :                 return -EINVAL;
    1549                 :            :         };
    1550                 :            : 
    1551   [ +  -  -  + ]:        410 :         if (min_operational == 0 || min_operational > num_base_bdevs) {
    1552   [ #  #  #  # ]:          0 :                 SPDK_ERRLOG("Wrong constraint value for raid level '%s'.\n",
    1553                 :            :                             raid_bdev_level_to_str(module->level));
    1554                 :          0 :                 return -EINVAL;
    1555                 :            :         }
    1556                 :            : 
    1557                 :        410 :         raid_bdev = calloc(1, sizeof(*raid_bdev));
    1558         [ -  + ]:        410 :         if (!raid_bdev) {
    1559                 :          0 :                 SPDK_ERRLOG("Unable to allocate memory for raid bdev\n");
    1560                 :          0 :                 return -ENOMEM;
    1561                 :            :         }
    1562                 :            : 
    1563   [ #  #  #  # ]:        410 :         raid_bdev->module = module;
    1564   [ #  #  #  # ]:        410 :         raid_bdev->num_base_bdevs = num_base_bdevs;
    1565   [ #  #  #  #  :        410 :         raid_bdev->base_bdev_info = calloc(raid_bdev->num_base_bdevs,
             #  #  #  # ]
    1566                 :            :                                            sizeof(struct raid_base_bdev_info));
    1567   [ -  +  #  #  :        410 :         if (!raid_bdev->base_bdev_info) {
                   #  # ]
    1568                 :          0 :                 SPDK_ERRLOG("Unable able to allocate base bdev info\n");
    1569                 :          0 :                 raid_bdev_free(raid_bdev);
    1570                 :          0 :                 return -ENOMEM;
    1571                 :            :         }
    1572                 :            : 
    1573   [ +  +  #  #  :       2964 :         RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) {
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
    1574   [ #  #  #  # ]:       2554 :                 base_info->raid_bdev = raid_bdev;
    1575                 :          0 :         }
    1576                 :            : 
    1577                 :            :         /* strip_size_kb is from the rpc param.  strip_size is in blocks and used
    1578                 :            :          * internally and set later.
    1579                 :            :          */
    1580   [ #  #  #  # ]:        410 :         raid_bdev->strip_size = 0;
    1581   [ #  #  #  # ]:        410 :         raid_bdev->strip_size_kb = strip_size;
    1582   [ #  #  #  # ]:        410 :         raid_bdev->state = RAID_BDEV_STATE_CONFIGURING;
    1583   [ #  #  #  # ]:        410 :         raid_bdev->level = level;
    1584   [ #  #  #  # ]:        410 :         raid_bdev->min_base_bdevs_operational = min_operational;
    1585   [ #  #  #  #  :        410 :         raid_bdev->superblock_enabled = superblock_enabled;
                   #  # ]
    1586                 :            : 
    1587         [ #  # ]:        410 :         raid_bdev_gen = &raid_bdev->bdev;
    1588                 :            : 
    1589   [ -  +  #  #  :        410 :         raid_bdev_gen->name = strdup(name);
                   #  # ]
    1590   [ -  +  #  #  :        410 :         if (!raid_bdev_gen->name) {
                   #  # ]
    1591                 :          0 :                 SPDK_ERRLOG("Unable to allocate name for raid\n");
    1592                 :          0 :                 raid_bdev_free(raid_bdev);
    1593                 :          0 :                 return -ENOMEM;
    1594                 :            :         }
    1595                 :            : 
    1596   [ #  #  #  # ]:        410 :         raid_bdev_gen->product_name = "Raid Volume";
    1597   [ #  #  #  # ]:        410 :         raid_bdev_gen->ctxt = raid_bdev;
    1598   [ #  #  #  # ]:        410 :         raid_bdev_gen->fn_table = &g_raid_bdev_fn_table;
    1599   [ #  #  #  # ]:        410 :         raid_bdev_gen->module = &g_raid_if;
    1600   [ #  #  #  # ]:        410 :         raid_bdev_gen->write_cache = 0;
    1601         [ #  # ]:        410 :         spdk_uuid_copy(&raid_bdev_gen->uuid, uuid);
    1602                 :            : 
    1603   [ #  #  #  #  :        410 :         TAILQ_INSERT_TAIL(&g_raid_bdev_list, raid_bdev, global_link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1604                 :            : 
    1605         [ #  # ]:        410 :         *raid_bdev_out = raid_bdev;
    1606                 :            : 
    1607                 :        410 :         return 0;
    1608                 :          0 : }
    1609                 :            : 
    1610                 :            : /*
    1611                 :            :  * brief:
    1612                 :            :  * raid_bdev_create allocates raid bdev based on passed configuration
    1613                 :            :  * params:
    1614                 :            :  * name - name for raid bdev
    1615                 :            :  * strip_size - strip size in KB
    1616                 :            :  * num_base_bdevs - number of base bdevs
    1617                 :            :  * level - raid level
    1618                 :            :  * superblock_enabled - true if raid should have superblock
    1619                 :            :  * uuid - uuid to set for the bdev
    1620                 :            :  * raid_bdev_out - the created raid bdev
    1621                 :            :  * returns:
    1622                 :            :  * 0 - success
    1623                 :            :  * non zero - failure
    1624                 :            :  */
    1625                 :            : int
    1626                 :        370 : raid_bdev_create(const char *name, uint32_t strip_size, uint8_t num_base_bdevs,
    1627                 :            :                  enum raid_level level, bool superblock_enabled, const struct spdk_uuid *uuid,
    1628                 :            :                  struct raid_bdev **raid_bdev_out)
    1629                 :            : {
    1630                 :        321 :         struct raid_bdev *raid_bdev;
    1631                 :            :         int rc;
    1632                 :            : 
    1633   [ -  +  #  # ]:        370 :         assert(uuid != NULL);
    1634                 :            : 
    1635         [ #  # ]:        370 :         rc = _raid_bdev_create(name, strip_size, num_base_bdevs, level, superblock_enabled, uuid,
    1636                 :            :                                &raid_bdev);
    1637         [ +  + ]:        370 :         if (rc != 0) {
    1638                 :          9 :                 return rc;
    1639                 :            :         }
    1640                 :            : 
    1641   [ +  +  +  -  :        361 :         if (superblock_enabled && spdk_uuid_is_null(uuid)) {
                   #  # ]
    1642                 :            :                 /* we need to have the uuid to store in the superblock before the bdev is registered */
    1643   [ #  #  #  # ]:         97 :                 spdk_uuid_generate(&raid_bdev->bdev.uuid);
    1644                 :          0 :         }
    1645                 :            : 
    1646   [ #  #  #  # ]:        361 :         raid_bdev->num_base_bdevs_operational = num_base_bdevs;
    1647                 :            : 
    1648         [ #  # ]:        361 :         *raid_bdev_out = raid_bdev;
    1649                 :            : 
    1650                 :        361 :         return 0;
    1651                 :          0 : }
    1652                 :            : 
    1653                 :            : static void
    1654                 :        287 : _raid_bdev_unregistering_cont(void *ctx)
    1655                 :            : {
    1656                 :        287 :         struct raid_bdev *raid_bdev = ctx;
    1657                 :            : 
    1658   [ #  #  #  # ]:        287 :         spdk_bdev_close(raid_bdev->self_desc);
    1659   [ #  #  #  # ]:        287 :         raid_bdev->self_desc = NULL;
    1660                 :        287 : }
    1661                 :            : 
    1662                 :            : static void
    1663                 :        287 : raid_bdev_unregistering_cont(void *ctx)
    1664                 :            : {
    1665                 :        287 :         spdk_thread_exec_msg(spdk_thread_get_app_thread(), _raid_bdev_unregistering_cont, ctx);
    1666                 :        287 : }
    1667                 :            : 
    1668                 :            : static int
    1669                 :         34 : raid_bdev_process_add_finish_action(struct raid_bdev_process *process, spdk_msg_fn cb, void *cb_ctx)
    1670                 :            : {
    1671                 :            :         struct raid_process_finish_action *finish_action;
    1672                 :            : 
    1673   [ -  +  #  #  :         34 :         assert(spdk_get_thread() == process->thread);
             #  #  #  # ]
    1674   [ -  +  #  #  :         34 :         assert(process->state < RAID_PROCESS_STATE_STOPPED);
             #  #  #  # ]
    1675                 :            : 
    1676                 :         34 :         finish_action = calloc(1, sizeof(*finish_action));
    1677         [ -  + ]:         34 :         if (finish_action == NULL) {
    1678                 :          0 :                 return -ENOMEM;
    1679                 :            :         }
    1680                 :            : 
    1681   [ #  #  #  # ]:         34 :         finish_action->cb = cb;
    1682   [ #  #  #  # ]:         34 :         finish_action->cb_ctx = cb_ctx;
    1683                 :            : 
    1684   [ #  #  #  #  :         34 :         TAILQ_INSERT_TAIL(&process->finish_actions, finish_action, link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    1685                 :            : 
    1686                 :         34 :         return 0;
    1687                 :          0 : }
    1688                 :            : 
    1689                 :            : static void
    1690                 :          1 : raid_bdev_unregistering_stop_process(void *ctx)
    1691                 :            : {
    1692                 :          1 :         struct raid_bdev_process *process = ctx;
    1693   [ #  #  #  # ]:          1 :         struct raid_bdev *raid_bdev = process->raid_bdev;
    1694                 :            :         int rc;
    1695                 :            : 
    1696   [ #  #  #  # ]:          1 :         process->state = RAID_PROCESS_STATE_STOPPING;
    1697   [ +  -  #  #  :          1 :         if (process->status == 0) {
                   #  # ]
    1698   [ #  #  #  # ]:          1 :                 process->status = -ECANCELED;
    1699                 :          0 :         }
    1700                 :            : 
    1701                 :          1 :         rc = raid_bdev_process_add_finish_action(process, raid_bdev_unregistering_cont, raid_bdev);
    1702         [ -  + ]:          1 :         if (rc != 0) {
    1703   [ #  #  #  #  :          0 :                 SPDK_ERRLOG("Failed to add raid bdev '%s' process finish action: %s\n",
             #  #  #  # ]
    1704                 :            :                             raid_bdev->bdev.name, spdk_strerror(-rc));
    1705                 :          0 :         }
    1706                 :          1 : }
    1707                 :            : 
    1708                 :            : static void
    1709                 :        291 : raid_bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *event_ctx)
    1710                 :            : {
    1711                 :        291 :         struct raid_bdev *raid_bdev = event_ctx;
    1712                 :            : 
    1713         [ +  + ]:        291 :         if (type == SPDK_BDEV_EVENT_REMOVE) {
    1714   [ +  +  #  #  :        287 :                 if (raid_bdev->process != NULL) {
                   #  # ]
    1715   [ #  #  #  #  :          1 :                         spdk_thread_send_msg(raid_bdev->process->thread, raid_bdev_unregistering_stop_process,
             #  #  #  # ]
    1716   [ #  #  #  # ]:          1 :                                              raid_bdev->process);
    1717                 :          0 :                 } else {
    1718                 :        286 :                         raid_bdev_unregistering_cont(raid_bdev);
    1719                 :            :                 }
    1720                 :          0 :         }
    1721                 :        291 : }
    1722                 :            : 
    1723                 :            : static void
    1724                 :        329 : raid_bdev_configure_cont(struct raid_bdev *raid_bdev)
    1725                 :            : {
    1726         [ #  # ]:        329 :         struct spdk_bdev *raid_bdev_gen = &raid_bdev->bdev;
    1727                 :            :         int rc;
    1728                 :            : 
    1729   [ #  #  #  # ]:        329 :         raid_bdev->state = RAID_BDEV_STATE_ONLINE;
    1730   [ -  +  +  +  :        329 :         SPDK_DEBUGLOG(bdev_raid, "io device register %p\n", raid_bdev);
                   #  # ]
    1731   [ -  +  +  +  :        329 :         SPDK_DEBUGLOG(bdev_raid, "blockcnt %" PRIu64 ", blocklen %u\n",
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1732                 :            :                       raid_bdev_gen->blockcnt, raid_bdev_gen->blocklen);
    1733                 :        329 :         spdk_io_device_register(raid_bdev, raid_bdev_create_cb, raid_bdev_destroy_cb,
    1734                 :            :                                 sizeof(struct raid_bdev_io_channel),
    1735   [ #  #  #  # ]:        329 :                                 raid_bdev_gen->name);
    1736                 :        329 :         rc = spdk_bdev_register(raid_bdev_gen);
    1737         [ -  + ]:        329 :         if (rc != 0) {
    1738   [ #  #  #  #  :          0 :                 SPDK_ERRLOG("Failed to register raid bdev '%s': %s\n",
                   #  # ]
    1739                 :            :                             raid_bdev_gen->name, spdk_strerror(-rc));
    1740                 :          0 :                 goto out;
    1741                 :            :         }
    1742                 :            : 
    1743                 :            :         /*
    1744                 :            :          * Open the bdev internally to delay unregistering if we need to stop a background process
    1745                 :            :          * first. The process may still need to unquiesce a range but it will fail because the
    1746                 :            :          * bdev's internal.spinlock is destroyed by the time the destruct callback is reached.
    1747                 :            :          * During application shutdown, bdevs automatically get unregistered by the bdev layer
    1748                 :            :          * so this is the only way currently to do this correctly.
    1749                 :            :          * TODO: try to handle this correctly in bdev layer instead.
    1750                 :            :          */
    1751   [ #  #  #  # ]:        329 :         rc = spdk_bdev_open_ext(raid_bdev_gen->name, false, raid_bdev_event_cb, raid_bdev,
    1752         [ #  # ]:          0 :                                 &raid_bdev->self_desc);
    1753         [ -  + ]:        329 :         if (rc != 0) {
    1754   [ #  #  #  #  :          0 :                 SPDK_ERRLOG("Failed to open raid bdev '%s': %s\n",
                   #  # ]
    1755                 :            :                             raid_bdev_gen->name, spdk_strerror(-rc));
    1756                 :          0 :                 spdk_bdev_unregister(raid_bdev_gen, NULL, NULL);
    1757                 :          0 :                 goto out;
    1758                 :            :         }
    1759                 :            : 
    1760   [ -  +  +  +  :        329 :         SPDK_DEBUGLOG(bdev_raid, "raid bdev generic %p\n", raid_bdev_gen);
                   #  # ]
    1761   [ +  +  +  +  :        329 :         SPDK_DEBUGLOG(bdev_raid, "raid bdev is created with name %s, raid_bdev %p\n",
          #  #  #  #  #  
                      # ]
    1762                 :            :                       raid_bdev_gen->name, raid_bdev);
    1763                 :        193 : out:
    1764         [ -  + ]:        329 :         if (rc != 0) {
    1765   [ #  #  #  #  :          0 :                 if (raid_bdev->module->stop != NULL) {
          #  #  #  #  #  
                      # ]
    1766   [ #  #  #  #  :          0 :                         raid_bdev->module->stop(raid_bdev);
          #  #  #  #  #  
                #  #  # ]
    1767                 :          0 :                 }
    1768                 :          0 :                 spdk_io_device_unregister(raid_bdev, NULL);
    1769   [ #  #  #  # ]:          0 :                 raid_bdev->state = RAID_BDEV_STATE_CONFIGURING;
    1770                 :          0 :         }
    1771                 :            : 
    1772   [ +  +  #  #  :        329 :         if (raid_bdev->configure_cb != NULL) {
                   #  # ]
    1773   [ #  #  #  #  :        288 :                 raid_bdev->configure_cb(raid_bdev->configure_cb_ctx, rc);
          #  #  #  #  #  
                #  #  # ]
    1774   [ #  #  #  # ]:        288 :                 raid_bdev->configure_cb = NULL;
    1775                 :          0 :         }
    1776                 :        329 : }
    1777                 :            : 
    1778                 :            : static void
    1779                 :        110 : raid_bdev_configure_write_sb_cb(int status, struct raid_bdev *raid_bdev, void *ctx)
    1780                 :            : {
    1781         [ +  - ]:        110 :         if (status == 0) {
    1782                 :        110 :                 raid_bdev_configure_cont(raid_bdev);
    1783                 :          0 :         } else {
    1784   [ #  #  #  #  :          0 :                 SPDK_ERRLOG("Failed to write raid bdev '%s' superblock: %s\n",
             #  #  #  # ]
    1785                 :            :                             raid_bdev->bdev.name, spdk_strerror(-status));
    1786   [ #  #  #  #  :          0 :                 if (raid_bdev->module->stop != NULL) {
          #  #  #  #  #  
                      # ]
    1787   [ #  #  #  #  :          0 :                         raid_bdev->module->stop(raid_bdev);
          #  #  #  #  #  
                #  #  # ]
    1788                 :          0 :                 }
    1789   [ #  #  #  #  :          0 :                 if (raid_bdev->configure_cb != NULL) {
                   #  # ]
    1790   [ #  #  #  #  :          0 :                         raid_bdev->configure_cb(raid_bdev->configure_cb_ctx, status);
          #  #  #  #  #  
                #  #  # ]
    1791   [ #  #  #  # ]:          0 :                         raid_bdev->configure_cb = NULL;
    1792                 :          0 :                 }
    1793                 :            :         }
    1794                 :        110 : }
    1795                 :            : 
    1796                 :            : /*
    1797                 :            :  * brief:
    1798                 :            :  * If raid bdev config is complete, then only register the raid bdev to
    1799                 :            :  * bdev layer and remove this raid bdev from configuring list and
    1800                 :            :  * insert the raid bdev to configured list
    1801                 :            :  * params:
    1802                 :            :  * raid_bdev - pointer to raid bdev
    1803                 :            :  * returns:
    1804                 :            :  * 0 - success
    1805                 :            :  * non zero - failure
    1806                 :            :  */
    1807                 :            : static int
    1808                 :        329 : raid_bdev_configure(struct raid_bdev *raid_bdev, raid_bdev_configure_cb cb, void *cb_ctx)
    1809                 :            : {
    1810         [ #  # ]:        329 :         uint32_t data_block_size = spdk_bdev_get_data_block_size(&raid_bdev->bdev);
    1811                 :            :         int rc;
    1812                 :            : 
    1813   [ -  +  #  #  :        329 :         assert(raid_bdev->state == RAID_BDEV_STATE_CONFIGURING);
             #  #  #  # ]
    1814   [ -  +  #  #  :        329 :         assert(raid_bdev->num_base_bdevs_discovered == raid_bdev->num_base_bdevs_operational);
          #  #  #  #  #  
                #  #  # ]
    1815   [ -  +  #  #  :        329 :         assert(raid_bdev->bdev.blocklen > 0);
          #  #  #  #  #  
                      # ]
    1816                 :            : 
    1817                 :            :         /* The strip_size_kb is read in from user in KB. Convert to blocks here for
    1818                 :            :          * internal use.
    1819                 :            :          */
    1820   [ -  +  #  #  :        329 :         raid_bdev->strip_size = (raid_bdev->strip_size_kb * 1024) / data_block_size;
          #  #  #  #  #  
                      # ]
    1821   [ +  +  -  +  :        329 :         if (raid_bdev->strip_size == 0 && raid_bdev->level != RAID1) {
          #  #  #  #  #  
                #  #  # ]
    1822                 :          0 :                 SPDK_ERRLOG("Strip size cannot be smaller than the device block size\n");
    1823                 :          0 :                 return -EINVAL;
    1824                 :            :         }
    1825   [ #  #  #  #  :        329 :         raid_bdev->strip_size_shift = spdk_u32log2(raid_bdev->strip_size);
             #  #  #  # ]
    1826                 :            : 
    1827   [ #  #  #  #  :        329 :         rc = raid_bdev->module->start(raid_bdev);
          #  #  #  #  #  
                #  #  # ]
    1828         [ -  + ]:        329 :         if (rc != 0) {
    1829                 :          0 :                 SPDK_ERRLOG("raid module startup callback failed\n");
    1830                 :          0 :                 return rc;
    1831                 :            :         }
    1832                 :            : 
    1833   [ -  +  #  #  :        329 :         assert(raid_bdev->configure_cb == NULL);
             #  #  #  # ]
    1834   [ #  #  #  # ]:        329 :         raid_bdev->configure_cb = cb;
    1835   [ #  #  #  # ]:        329 :         raid_bdev->configure_cb_ctx = cb_ctx;
    1836                 :            : 
    1837   [ +  +  +  +  :        329 :         if (raid_bdev->superblock_enabled) {
             #  #  #  # ]
    1838   [ +  +  #  #  :        110 :                 if (raid_bdev->sb == NULL) {
                   #  # ]
    1839                 :         69 :                         rc = raid_bdev_alloc_superblock(raid_bdev, data_block_size);
    1840         [ +  - ]:         69 :                         if (rc == 0) {
    1841                 :         69 :                                 raid_bdev_init_superblock(raid_bdev);
    1842                 :          0 :                         }
    1843                 :          0 :                 } else {
    1844   [ -  +  #  #  :         41 :                         assert(spdk_uuid_compare(&raid_bdev->sb->uuid, &raid_bdev->bdev.uuid) == 0);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1845   [ -  +  #  #  :         41 :                         if (raid_bdev->sb->block_size != data_block_size) {
          #  #  #  #  #  
                      # ]
    1846                 :          0 :                                 SPDK_ERRLOG("blocklen does not match value in superblock\n");
    1847                 :          0 :                                 rc = -EINVAL;
    1848                 :          0 :                         }
    1849   [ -  +  #  #  :         41 :                         if (raid_bdev->sb->raid_size != raid_bdev->bdev.blockcnt) {
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    1850                 :          0 :                                 SPDK_ERRLOG("blockcnt does not match value in superblock\n");
    1851                 :          0 :                                 rc = -EINVAL;
    1852                 :          0 :                         }
    1853                 :            :                 }
    1854                 :            : 
    1855         [ -  + ]:        110 :                 if (rc != 0) {
    1856   [ #  #  #  # ]:          0 :                         raid_bdev->configure_cb = NULL;
    1857   [ #  #  #  #  :          0 :                         if (raid_bdev->module->stop != NULL) {
          #  #  #  #  #  
                      # ]
    1858   [ #  #  #  #  :          0 :                                 raid_bdev->module->stop(raid_bdev);
          #  #  #  #  #  
                #  #  # ]
    1859                 :          0 :                         }
    1860                 :          0 :                         return rc;
    1861                 :            :                 }
    1862                 :            : 
    1863                 :        110 :                 raid_bdev_write_superblock(raid_bdev, raid_bdev_configure_write_sb_cb, NULL);
    1864                 :          0 :         } else {
    1865                 :        219 :                 raid_bdev_configure_cont(raid_bdev);
    1866                 :            :         }
    1867                 :            : 
    1868                 :        329 :         return 0;
    1869                 :          0 : }
    1870                 :            : 
    1871                 :            : /*
    1872                 :            :  * brief:
    1873                 :            :  * If raid bdev is online and registered, change the bdev state to
    1874                 :            :  * configuring and unregister this raid device. Queue this raid device
    1875                 :            :  * in configuring list
    1876                 :            :  * params:
    1877                 :            :  * raid_bdev - pointer to raid bdev
    1878                 :            :  * cb_fn - callback function
    1879                 :            :  * cb_arg - argument to callback function
    1880                 :            :  * returns:
    1881                 :            :  * none
    1882                 :            :  */
    1883                 :            : static void
    1884                 :        165 : raid_bdev_deconfigure(struct raid_bdev *raid_bdev, raid_bdev_destruct_cb cb_fn,
    1885                 :            :                       void *cb_arg)
    1886                 :            : {
    1887   [ -  +  #  #  :        165 :         if (raid_bdev->state != RAID_BDEV_STATE_ONLINE) {
                   #  # ]
    1888         [ #  # ]:          0 :                 if (cb_fn) {
    1889   [ #  #  #  # ]:          0 :                         cb_fn(cb_arg, 0);
    1890                 :          0 :                 }
    1891                 :          0 :                 return;
    1892                 :            :         }
    1893                 :            : 
    1894   [ #  #  #  # ]:        165 :         raid_bdev->state = RAID_BDEV_STATE_OFFLINE;
    1895   [ -  +  +  +  :        165 :         SPDK_DEBUGLOG(bdev_raid, "raid bdev state changing from online to offline\n");
                   #  # ]
    1896                 :            : 
    1897         [ #  # ]:        165 :         spdk_bdev_unregister(&raid_bdev->bdev, cb_fn, cb_arg);
    1898                 :          0 : }
    1899                 :            : 
    1900                 :            : /*
    1901                 :            :  * brief:
    1902                 :            :  * raid_bdev_find_base_info_by_bdev function finds the base bdev info by bdev.
    1903                 :            :  * params:
    1904                 :            :  * base_bdev - pointer to base bdev
    1905                 :            :  * returns:
    1906                 :            :  * base bdev info if found, otherwise NULL.
    1907                 :            :  */
    1908                 :            : static struct raid_base_bdev_info *
    1909                 :       5696 : raid_bdev_find_base_info_by_bdev(struct spdk_bdev *base_bdev)
    1910                 :            : {
    1911                 :            :         struct raid_bdev *raid_bdev;
    1912                 :            :         struct raid_base_bdev_info *base_info;
    1913                 :            : 
    1914   [ +  +  #  #  :       6673 :         TAILQ_FOREACH(raid_bdev, &g_raid_bdev_list, global_link) {
             #  #  #  # ]
    1915   [ +  +  #  #  :       3644 :                 RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) {
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
    1916   [ +  +  +  +  :       4893 :                         if (base_info->desc != NULL &&
             #  #  #  # ]
    1917   [ #  #  #  # ]:       2226 :                             spdk_bdev_desc_get_bdev(base_info->desc) == base_bdev) {
    1918                 :        212 :                                 return base_info;
    1919                 :            :                         }
    1920                 :          0 :                 }
    1921                 :          0 :         }
    1922                 :            : 
    1923                 :       5484 :         return NULL;
    1924                 :         47 : }
    1925                 :            : 
    1926                 :            : static void
    1927                 :        108 : raid_bdev_remove_base_bdev_done(struct raid_base_bdev_info *base_info, int status)
    1928                 :            : {
    1929   [ #  #  #  # ]:        108 :         struct raid_bdev *raid_bdev = base_info->raid_bdev;
    1930                 :            : 
    1931   [ -  +  -  +  :        108 :         assert(base_info->remove_scheduled);
          #  #  #  #  #  
                      # ]
    1932   [ #  #  #  # ]:        108 :         base_info->remove_scheduled = false;
    1933                 :            : 
    1934         [ +  - ]:        108 :         if (status == 0) {
    1935         [ #  # ]:        108 :                 raid_bdev->num_base_bdevs_operational--;
    1936   [ +  +  #  #  :        108 :                 if (raid_bdev->num_base_bdevs_operational < raid_bdev->min_base_bdevs_operational) {
          #  #  #  #  #  
                      # ]
    1937                 :            :                         /* There is not enough base bdevs to keep the raid bdev operational. */
    1938   [ #  #  #  #  :         14 :                         raid_bdev_deconfigure(raid_bdev, base_info->remove_cb, base_info->remove_cb_ctx);
             #  #  #  # ]
    1939                 :         14 :                         return;
    1940                 :            :                 }
    1941                 :          0 :         }
    1942                 :            : 
    1943   [ +  +  #  #  :         94 :         if (base_info->remove_cb != NULL) {
                   #  # ]
    1944   [ #  #  #  #  :         47 :                 base_info->remove_cb(base_info->remove_cb_ctx, status);
          #  #  #  #  #  
                #  #  # ]
    1945                 :          0 :         }
    1946                 :          0 : }
    1947                 :            : 
    1948                 :            : static void
    1949                 :        108 : raid_bdev_remove_base_bdev_on_unquiesced(void *ctx, int status)
    1950                 :            : {
    1951                 :        108 :         struct raid_base_bdev_info *base_info = ctx;
    1952   [ #  #  #  # ]:        108 :         struct raid_bdev *raid_bdev = base_info->raid_bdev;
    1953                 :            : 
    1954         [ -  + ]:        108 :         if (status != 0) {
    1955   [ #  #  #  #  :          0 :                 SPDK_ERRLOG("Failed to unquiesce raid bdev %s: %s\n",
             #  #  #  # ]
    1956                 :            :                             raid_bdev->bdev.name, spdk_strerror(-status));
    1957                 :          0 :         }
    1958                 :            : 
    1959                 :        108 :         raid_bdev_remove_base_bdev_done(base_info, status);
    1960                 :        108 : }
    1961                 :            : 
    1962                 :            : static void
    1963                 :         13 : raid_bdev_channel_remove_base_bdev(struct spdk_io_channel_iter *i)
    1964                 :            : {
    1965                 :         13 :         struct raid_base_bdev_info *base_info = spdk_io_channel_iter_get_ctx(i);
    1966                 :         13 :         struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(i);
    1967                 :         13 :         struct raid_bdev_io_channel *raid_ch = spdk_io_channel_get_ctx(ch);
    1968                 :         13 :         uint8_t idx = raid_bdev_base_bdev_slot(base_info);
    1969                 :            : 
    1970   [ -  +  +  -  :         13 :         SPDK_DEBUGLOG(bdev_raid, "slot: %u raid_ch: %p\n", idx, raid_ch);
                   #  # ]
    1971                 :            : 
    1972   [ +  +  #  #  :         13 :         if (raid_ch->base_channel[idx] != NULL) {
          #  #  #  #  #  
                      # ]
    1973   [ #  #  #  #  :          9 :                 spdk_put_io_channel(raid_ch->base_channel[idx]);
             #  #  #  # ]
    1974   [ #  #  #  #  :          9 :                 raid_ch->base_channel[idx] = NULL;
             #  #  #  # ]
    1975                 :          0 :         }
    1976                 :            : 
    1977   [ +  +  #  #  :         13 :         if (raid_ch->process.ch_processed != NULL) {
             #  #  #  # ]
    1978   [ #  #  #  #  :          6 :                 raid_ch->process.ch_processed->base_channel[idx] = NULL;
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1979                 :          0 :         }
    1980                 :            : 
    1981                 :         13 :         spdk_for_each_channel_continue(i, 0);
    1982                 :         13 : }
    1983                 :            : 
    1984                 :            : static void
    1985                 :        108 : raid_bdev_channels_remove_base_bdev_done(struct spdk_io_channel_iter *i, int status)
    1986                 :            : {
    1987                 :        108 :         struct raid_base_bdev_info *base_info = spdk_io_channel_iter_get_ctx(i);
    1988   [ #  #  #  # ]:        108 :         struct raid_bdev *raid_bdev = base_info->raid_bdev;
    1989                 :            : 
    1990                 :        108 :         raid_bdev_free_base_bdev_resource(base_info);
    1991                 :            : 
    1992         [ #  # ]:        108 :         spdk_bdev_unquiesce(&raid_bdev->bdev, &g_raid_if, raid_bdev_remove_base_bdev_on_unquiesced,
    1993                 :          0 :                             base_info);
    1994                 :        108 : }
    1995                 :            : 
    1996                 :            : static void
    1997                 :        108 : raid_bdev_remove_base_bdev_cont(struct raid_base_bdev_info *base_info)
    1998                 :            : {
    1999                 :        108 :         raid_bdev_deconfigure_base_bdev(base_info);
    2000                 :            : 
    2001   [ #  #  #  # ]:        108 :         spdk_for_each_channel(base_info->raid_bdev, raid_bdev_channel_remove_base_bdev, base_info,
    2002                 :            :                               raid_bdev_channels_remove_base_bdev_done);
    2003                 :        108 : }
    2004                 :            : 
    2005                 :            : static void
    2006                 :         53 : raid_bdev_remove_base_bdev_write_sb_cb(int status, struct raid_bdev *raid_bdev, void *ctx)
    2007                 :            : {
    2008                 :         53 :         struct raid_base_bdev_info *base_info = ctx;
    2009                 :            : 
    2010         [ -  + ]:         53 :         if (status != 0) {
    2011   [ #  #  #  #  :          0 :                 SPDK_ERRLOG("Failed to write raid bdev '%s' superblock: %s\n",
             #  #  #  # ]
    2012                 :            :                             raid_bdev->bdev.name, spdk_strerror(-status));
    2013                 :          0 :                 raid_bdev_remove_base_bdev_done(base_info, status);
    2014                 :          0 :                 return;
    2015                 :            :         }
    2016                 :            : 
    2017                 :         53 :         raid_bdev_remove_base_bdev_cont(base_info);
    2018                 :          0 : }
    2019                 :            : 
    2020                 :            : static void
    2021                 :        108 : raid_bdev_remove_base_bdev_on_quiesced(void *ctx, int status)
    2022                 :            : {
    2023                 :        108 :         struct raid_base_bdev_info *base_info = ctx;
    2024   [ #  #  #  # ]:        108 :         struct raid_bdev *raid_bdev = base_info->raid_bdev;
    2025                 :            : 
    2026         [ -  + ]:        108 :         if (status != 0) {
    2027   [ #  #  #  #  :          0 :                 SPDK_ERRLOG("Failed to quiesce raid bdev %s: %s\n",
             #  #  #  # ]
    2028                 :            :                             raid_bdev->bdev.name, spdk_strerror(-status));
    2029                 :          0 :                 raid_bdev_remove_base_bdev_done(base_info, status);
    2030                 :          0 :                 return;
    2031                 :            :         }
    2032                 :            : 
    2033   [ +  +  #  #  :        108 :         if (raid_bdev->sb) {
                   #  # ]
    2034   [ #  #  #  # ]:         81 :                 struct raid_bdev_superblock *sb = raid_bdev->sb;
    2035                 :         81 :                 uint8_t slot = raid_bdev_base_bdev_slot(base_info);
    2036                 :            :                 uint8_t i;
    2037                 :            : 
    2038   [ +  +  #  #  :        179 :                 for (i = 0; i < sb->base_bdevs_size; i++) {
                   #  # ]
    2039   [ #  #  #  # ]:        151 :                         struct raid_bdev_sb_base_bdev *sb_base_bdev = &sb->base_bdevs[i];
    2040                 :            : 
    2041   [ +  +  #  #  :        151 :                         if (sb_base_bdev->state == RAID_SB_BASE_BDEV_CONFIGURED &&
             #  #  #  # ]
    2042   [ +  +  #  # ]:        101 :                             sb_base_bdev->slot == slot) {
    2043   [ -  +  +  +  :         53 :                                 if (base_info->is_failed) {
             #  #  #  # ]
    2044   [ #  #  #  # ]:          3 :                                         sb_base_bdev->state = RAID_SB_BASE_BDEV_FAILED;
    2045                 :          0 :                                 } else {
    2046   [ #  #  #  # ]:         50 :                                         sb_base_bdev->state = RAID_SB_BASE_BDEV_MISSING;
    2047                 :            :                                 }
    2048                 :            : 
    2049                 :         53 :                                 raid_bdev_write_superblock(raid_bdev, raid_bdev_remove_base_bdev_write_sb_cb, base_info);
    2050                 :         53 :                                 return;
    2051                 :            :                         }
    2052                 :          0 :                 }
    2053                 :          0 :         }
    2054                 :            : 
    2055                 :         55 :         raid_bdev_remove_base_bdev_cont(base_info);
    2056                 :          0 : }
    2057                 :            : 
    2058                 :            : static int
    2059                 :        108 : raid_bdev_remove_base_bdev_quiesce(struct raid_base_bdev_info *base_info)
    2060                 :            : {
    2061   [ -  +  #  # ]:        108 :         assert(spdk_get_thread() == spdk_thread_get_app_thread());
    2062                 :            : 
    2063   [ #  #  #  #  :        108 :         return spdk_bdev_quiesce(&base_info->raid_bdev->bdev, &g_raid_if,
                   #  # ]
    2064                 :          0 :                                  raid_bdev_remove_base_bdev_on_quiesced, base_info);
    2065                 :            : }
    2066                 :            : 
    2067                 :            : struct raid_bdev_process_base_bdev_remove_ctx {
    2068                 :            :         struct raid_bdev_process *process;
    2069                 :            :         struct raid_base_bdev_info *base_info;
    2070                 :            :         uint8_t num_base_bdevs_operational;
    2071                 :            : };
    2072                 :            : 
    2073                 :            : static void
    2074                 :         37 : _raid_bdev_process_base_bdev_remove_cont(void *ctx)
    2075                 :            : {
    2076                 :         37 :         struct raid_base_bdev_info *base_info = ctx;
    2077                 :            :         int ret;
    2078                 :            : 
    2079                 :         37 :         ret = raid_bdev_remove_base_bdev_quiesce(base_info);
    2080         [ -  + ]:         37 :         if (ret != 0) {
    2081                 :          0 :                 raid_bdev_remove_base_bdev_done(base_info, ret);
    2082                 :          0 :         }
    2083                 :         37 : }
    2084                 :            : 
    2085                 :            : static void
    2086                 :         37 : raid_bdev_process_base_bdev_remove_cont(void *_ctx)
    2087                 :            : {
    2088                 :         37 :         struct raid_bdev_process_base_bdev_remove_ctx *ctx = _ctx;
    2089   [ #  #  #  # ]:         37 :         struct raid_base_bdev_info *base_info = ctx->base_info;
    2090                 :            : 
    2091                 :         37 :         free(ctx);
    2092                 :            : 
    2093                 :         37 :         spdk_thread_send_msg(spdk_thread_get_app_thread(), _raid_bdev_process_base_bdev_remove_cont,
    2094                 :          0 :                              base_info);
    2095                 :         37 : }
    2096                 :            : 
    2097                 :            : static void
    2098                 :         37 : _raid_bdev_process_base_bdev_remove(void *_ctx)
    2099                 :            : {
    2100                 :         37 :         struct raid_bdev_process_base_bdev_remove_ctx *ctx = _ctx;
    2101   [ #  #  #  # ]:         37 :         struct raid_bdev_process *process = ctx->process;
    2102                 :            :         int ret;
    2103                 :            : 
    2104   [ +  +  #  #  :         37 :         if (ctx->base_info != process->target &&
          #  #  #  #  #  
                #  #  # ]
    2105   [ +  -  #  #  :          4 :             ctx->num_base_bdevs_operational > process->raid_bdev->min_base_bdevs_operational) {
          #  #  #  #  #  
                #  #  # ]
    2106                 :            :                 /* process doesn't need to be stopped */
    2107                 :          4 :                 raid_bdev_process_base_bdev_remove_cont(ctx);
    2108                 :          4 :                 return;
    2109                 :            :         }
    2110                 :            : 
    2111   [ +  -  +  -  :         33 :         assert(process->state > RAID_PROCESS_STATE_INIT &&
          #  #  #  #  #  
                #  #  # ]
    2112                 :            :                process->state < RAID_PROCESS_STATE_STOPPED);
    2113                 :            : 
    2114                 :         33 :         ret = raid_bdev_process_add_finish_action(process, raid_bdev_process_base_bdev_remove_cont, ctx);
    2115         [ -  + ]:         33 :         if (ret != 0) {
    2116   [ #  #  #  # ]:          0 :                 raid_bdev_remove_base_bdev_done(ctx->base_info, ret);
    2117                 :          0 :                 free(ctx);
    2118                 :          0 :                 return;
    2119                 :            :         }
    2120                 :            : 
    2121   [ #  #  #  # ]:         33 :         process->state = RAID_PROCESS_STATE_STOPPING;
    2122                 :            : 
    2123   [ +  -  #  #  :         33 :         if (process->status == 0) {
                   #  # ]
    2124   [ #  #  #  # ]:         33 :                 process->status = -ENODEV;
    2125                 :          0 :         }
    2126                 :          0 : }
    2127                 :            : 
    2128                 :            : static int
    2129                 :         37 : raid_bdev_process_base_bdev_remove(struct raid_bdev_process *process,
    2130                 :            :                                    struct raid_base_bdev_info *base_info)
    2131                 :            : {
    2132                 :            :         struct raid_bdev_process_base_bdev_remove_ctx *ctx;
    2133                 :            : 
    2134   [ -  +  #  # ]:         37 :         assert(spdk_get_thread() == spdk_thread_get_app_thread());
    2135                 :            : 
    2136                 :         37 :         ctx = calloc(1, sizeof(*ctx));
    2137         [ -  + ]:         37 :         if (ctx == NULL) {
    2138                 :          0 :                 return -ENOMEM;
    2139                 :            :         }
    2140                 :            : 
    2141                 :            :         /*
    2142                 :            :          * We have to send the process and num_base_bdevs_operational in the message ctx
    2143                 :            :          * because the process thread should not access raid_bdev's properties. Particularly,
    2144                 :            :          * raid_bdev->process may be cleared by the time the message is handled, but ctx->process
    2145                 :            :          * will still be valid until the process is fully stopped.
    2146                 :            :          */
    2147   [ #  #  #  # ]:         37 :         ctx->base_info = base_info;
    2148   [ #  #  #  # ]:         37 :         ctx->process = process;
    2149                 :            :         /*
    2150                 :            :          * raid_bdev->num_base_bdevs_operational can't be used here because it is decremented
    2151                 :            :          * after the removal and more than one base bdev may be removed at the same time
    2152                 :            :          */
    2153   [ +  +  #  #  :        147 :         RAID_FOR_EACH_BASE_BDEV(process->raid_bdev, base_info) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
    2154   [ -  +  +  +  :        110 :                 if (base_info->is_configured && !base_info->remove_scheduled) {
          -  +  +  +  #  
          #  #  #  #  #  
                   #  # ]
    2155         [ #  # ]:         69 :                         ctx->num_base_bdevs_operational++;
    2156                 :          0 :                 }
    2157                 :          0 :         }
    2158                 :            : 
    2159   [ #  #  #  # ]:         37 :         spdk_thread_send_msg(process->thread, _raid_bdev_process_base_bdev_remove, ctx);
    2160                 :            : 
    2161                 :         37 :         return 0;
    2162                 :          0 : }
    2163                 :            : 
    2164                 :            : static int
    2165                 :        241 : _raid_bdev_remove_base_bdev(struct raid_base_bdev_info *base_info,
    2166                 :            :                             raid_base_bdev_cb cb_fn, void *cb_ctx)
    2167                 :            : {
    2168   [ #  #  #  # ]:        241 :         struct raid_bdev *raid_bdev = base_info->raid_bdev;
    2169                 :        241 :         int ret = 0;
    2170                 :            : 
    2171   [ -  +  +  -  :        241 :         SPDK_DEBUGLOG(bdev_raid, "%s\n", base_info->name);
          #  #  #  #  #  
                      # ]
    2172                 :            : 
    2173   [ -  +  #  # ]:        241 :         assert(spdk_get_thread() == spdk_thread_get_app_thread());
    2174                 :            : 
    2175   [ -  +  +  +  :        241 :         if (base_info->remove_scheduled || !base_info->is_configured) {
          -  +  -  +  #  
          #  #  #  #  #  
                   #  # ]
    2176                 :         33 :                 return -ENODEV;
    2177                 :            :         }
    2178                 :            : 
    2179   [ -  +  #  #  :        208 :         assert(base_info->desc);
             #  #  #  # ]
    2180   [ #  #  #  # ]:        208 :         base_info->remove_scheduled = true;
    2181                 :            : 
    2182   [ +  +  #  #  :        208 :         if (raid_bdev->state != RAID_BDEV_STATE_ONLINE) {
                   #  # ]
    2183                 :            :                 /*
    2184                 :            :                  * As raid bdev is not registered yet or already unregistered,
    2185                 :            :                  * so cleanup should be done here itself.
    2186                 :            :                  *
    2187                 :            :                  * Removing a base bdev at this stage does not change the number of operational
    2188                 :            :                  * base bdevs, only the number of discovered base bdevs.
    2189                 :            :                  */
    2190                 :         87 :                 raid_bdev_free_base_bdev_resource(base_info);
    2191   [ #  #  #  # ]:         87 :                 base_info->remove_scheduled = false;
    2192   [ +  +  #  #  :         87 :                 if (raid_bdev->num_base_bdevs_discovered == 0 &&
             #  #  #  # ]
    2193   [ +  -  #  # ]:         16 :                     raid_bdev->state == RAID_BDEV_STATE_OFFLINE) {
    2194                 :            :                         /* There is no base bdev for this raid, so free the raid device. */
    2195                 :         16 :                         raid_bdev_cleanup_and_free(raid_bdev);
    2196                 :          0 :                 }
    2197         [ +  + ]:         87 :                 if (cb_fn != NULL) {
    2198   [ #  #  #  # ]:         32 :                         cb_fn(cb_ctx, 0);
    2199                 :          0 :                 }
    2200   [ +  +  #  #  :        121 :         } else if (raid_bdev->min_base_bdevs_operational == raid_bdev->num_base_bdevs) {
          #  #  #  #  #  
                      # ]
    2201                 :            :                 /* This raid bdev does not tolerate removing a base bdev. */
    2202         [ #  # ]:         13 :                 raid_bdev->num_base_bdevs_operational--;
    2203                 :         13 :                 raid_bdev_deconfigure(raid_bdev, cb_fn, cb_ctx);
    2204                 :          0 :         } else {
    2205   [ #  #  #  # ]:        108 :                 base_info->remove_cb = cb_fn;
    2206   [ #  #  #  # ]:        108 :                 base_info->remove_cb_ctx = cb_ctx;
    2207                 :            : 
    2208   [ +  +  #  #  :        108 :                 if (raid_bdev->process != NULL) {
                   #  # ]
    2209   [ #  #  #  # ]:         37 :                         ret = raid_bdev_process_base_bdev_remove(raid_bdev->process, base_info);
    2210                 :          0 :                 } else {
    2211                 :         71 :                         ret = raid_bdev_remove_base_bdev_quiesce(base_info);
    2212                 :            :                 }
    2213                 :            : 
    2214         [ -  + ]:        108 :                 if (ret != 0) {
    2215   [ #  #  #  # ]:          0 :                         base_info->remove_scheduled = false;
    2216                 :          0 :                 }
    2217                 :            :         }
    2218                 :            : 
    2219                 :        208 :         return ret;
    2220                 :          0 : }
    2221                 :            : 
    2222                 :            : /*
    2223                 :            :  * brief:
    2224                 :            :  * raid_bdev_remove_base_bdev function is called by below layers when base_bdev
    2225                 :            :  * is removed. This function checks if this base bdev is part of any raid bdev
    2226                 :            :  * or not. If yes, it takes necessary action on that particular raid bdev.
    2227                 :            :  * params:
    2228                 :            :  * base_bdev - pointer to base bdev which got removed
    2229                 :            :  * cb_fn - callback function
    2230                 :            :  * cb_arg - argument to callback function
    2231                 :            :  * returns:
    2232                 :            :  * 0 - success
    2233                 :            :  * non zero - failure
    2234                 :            :  */
    2235                 :            : int
    2236                 :        204 : raid_bdev_remove_base_bdev(struct spdk_bdev *base_bdev, raid_base_bdev_cb cb_fn, void *cb_ctx)
    2237                 :            : {
    2238                 :            :         struct raid_base_bdev_info *base_info;
    2239                 :            : 
    2240                 :            :         /* Find the raid_bdev which has claimed this base_bdev */
    2241                 :        204 :         base_info = raid_bdev_find_base_info_by_bdev(base_bdev);
    2242         [ -  + ]:        204 :         if (!base_info) {
    2243   [ #  #  #  # ]:          0 :                 SPDK_ERRLOG("bdev to remove '%s' not found\n", base_bdev->name);
    2244                 :          0 :                 return -ENODEV;
    2245                 :            :         }
    2246                 :            : 
    2247                 :        204 :         return _raid_bdev_remove_base_bdev(base_info, cb_fn, cb_ctx);
    2248                 :          0 : }
    2249                 :            : 
    2250                 :            : static void
    2251                 :          3 : raid_bdev_fail_base_remove_cb(void *ctx, int status)
    2252                 :            : {
    2253                 :          3 :         struct raid_base_bdev_info *base_info = ctx;
    2254                 :            : 
    2255         [ -  + ]:          3 :         if (status != 0) {
    2256   [ #  #  #  # ]:          0 :                 SPDK_WARNLOG("Failed to remove base bdev %s\n", base_info->name);
    2257   [ #  #  #  # ]:          0 :                 base_info->is_failed = false;
    2258                 :          0 :         }
    2259                 :          3 : }
    2260                 :            : 
    2261                 :            : static void
    2262                 :          3 : _raid_bdev_fail_base_bdev(void *ctx)
    2263                 :            : {
    2264                 :          3 :         struct raid_base_bdev_info *base_info = ctx;
    2265                 :            :         int rc;
    2266                 :            : 
    2267   [ -  +  -  +  :          3 :         if (base_info->is_failed) {
             #  #  #  # ]
    2268                 :          0 :                 return;
    2269                 :            :         }
    2270   [ #  #  #  # ]:          3 :         base_info->is_failed = true;
    2271                 :            : 
    2272   [ #  #  #  #  :          3 :         SPDK_NOTICELOG("Failing base bdev in slot %d ('%s') of raid bdev '%s'\n",
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    2273                 :            :                        raid_bdev_base_bdev_slot(base_info), base_info->name, base_info->raid_bdev->bdev.name);
    2274                 :            : 
    2275                 :          3 :         rc = _raid_bdev_remove_base_bdev(base_info, raid_bdev_fail_base_remove_cb, base_info);
    2276         [ -  + ]:          3 :         if (rc != 0) {
    2277                 :          0 :                 raid_bdev_fail_base_remove_cb(base_info, rc);
    2278                 :          0 :         }
    2279                 :          0 : }
    2280                 :            : 
    2281                 :            : void
    2282                 :          3 : raid_bdev_fail_base_bdev(struct raid_base_bdev_info *base_info)
    2283                 :            : {
    2284                 :          3 :         spdk_thread_exec_msg(spdk_thread_get_app_thread(), _raid_bdev_fail_base_bdev, base_info);
    2285                 :          3 : }
    2286                 :            : 
    2287                 :            : static void
    2288                 :          2 : raid_bdev_resize_write_sb_cb(int status, struct raid_bdev *raid_bdev, void *ctx)
    2289                 :            : {
    2290         [ -  + ]:          2 :         if (status != 0) {
    2291   [ #  #  #  #  :          0 :                 SPDK_ERRLOG("Failed to write raid bdev '%s' superblock after resizing the bdev: %s\n",
             #  #  #  # ]
    2292                 :            :                             raid_bdev->bdev.name, spdk_strerror(-status));
    2293                 :          0 :         }
    2294                 :          2 : }
    2295                 :            : 
    2296                 :            : /*
    2297                 :            :  * brief:
    2298                 :            :  * raid_bdev_resize_base_bdev function is called by below layers when base_bdev
    2299                 :            :  * is resized. This function checks if the smallest size of the base_bdevs is changed.
    2300                 :            :  * If yes, call module handler to resize the raid_bdev if implemented.
    2301                 :            :  * params:
    2302                 :            :  * base_bdev - pointer to base bdev which got resized.
    2303                 :            :  * returns:
    2304                 :            :  * none
    2305                 :            :  */
    2306                 :            : static void
    2307                 :          8 : raid_bdev_resize_base_bdev(struct spdk_bdev *base_bdev)
    2308                 :            : {
    2309                 :            :         struct raid_bdev *raid_bdev;
    2310                 :            :         struct raid_base_bdev_info *base_info;
    2311                 :            :         uint64_t blockcnt_old;
    2312                 :            : 
    2313   [ -  +  +  -  :          8 :         SPDK_DEBUGLOG(bdev_raid, "raid_bdev_resize_base_bdev\n");
                   #  # ]
    2314                 :            : 
    2315                 :          8 :         base_info = raid_bdev_find_base_info_by_bdev(base_bdev);
    2316                 :            : 
    2317                 :            :         /* Find the raid_bdev which has claimed this base_bdev */
    2318         [ -  + ]:          8 :         if (!base_info) {
    2319   [ #  #  #  # ]:          0 :                 SPDK_ERRLOG("raid_bdev whose base_bdev '%s' not found\n", base_bdev->name);
    2320                 :          0 :                 return;
    2321                 :            :         }
    2322   [ #  #  #  # ]:          8 :         raid_bdev = base_info->raid_bdev;
    2323                 :            : 
    2324   [ -  +  #  # ]:          8 :         assert(spdk_get_thread() == spdk_thread_get_app_thread());
    2325                 :            : 
    2326   [ #  #  #  #  :          8 :         SPDK_NOTICELOG("base_bdev '%s' was resized: old size %" PRIu64 ", new size %" PRIu64 "\n",
          #  #  #  #  #  
                #  #  # ]
    2327                 :            :                        base_bdev->name, base_info->blockcnt, base_bdev->blockcnt);
    2328                 :            : 
    2329   [ #  #  #  #  :          8 :         base_info->blockcnt = base_bdev->blockcnt;
             #  #  #  # ]
    2330                 :            : 
    2331   [ -  +  #  #  :          8 :         if (!raid_bdev->module->resize) {
          #  #  #  #  #  
                      # ]
    2332                 :          0 :                 return;
    2333                 :            :         }
    2334                 :            : 
    2335   [ #  #  #  #  :          8 :         blockcnt_old = raid_bdev->bdev.blockcnt;
                   #  # ]
    2336   [ +  +  #  #  :          8 :         if (raid_bdev->module->resize(raid_bdev) == false) {
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    2337                 :          4 :                 return;
    2338                 :            :         }
    2339                 :            : 
    2340   [ #  #  #  #  :          4 :         SPDK_NOTICELOG("raid bdev '%s': block count was changed from %" PRIu64 " to %" PRIu64 "\n",
          #  #  #  #  #  
                #  #  # ]
    2341                 :            :                        raid_bdev->bdev.name, blockcnt_old, raid_bdev->bdev.blockcnt);
    2342                 :            : 
    2343   [ -  +  +  +  :          4 :         if (raid_bdev->superblock_enabled) {
             #  #  #  # ]
    2344   [ #  #  #  # ]:          2 :                 struct raid_bdev_superblock *sb = raid_bdev->sb;
    2345                 :            :                 uint8_t i;
    2346                 :            : 
    2347   [ +  +  #  #  :          6 :                 for (i = 0; i < sb->base_bdevs_size; i++) {
                   #  # ]
    2348   [ #  #  #  # ]:          4 :                         struct raid_bdev_sb_base_bdev *sb_base_bdev = &sb->base_bdevs[i];
    2349                 :            : 
    2350   [ +  -  #  #  :          4 :                         if (sb_base_bdev->slot < raid_bdev->num_base_bdevs) {
          #  #  #  #  #  
                      # ]
    2351   [ #  #  #  #  :          4 :                                 base_info = &raid_bdev->base_bdev_info[sb_base_bdev->slot];
          #  #  #  #  #  
                      # ]
    2352   [ #  #  #  #  :          4 :                                 sb_base_bdev->data_size = base_info->data_size;
             #  #  #  # ]
    2353                 :          0 :                         }
    2354                 :          0 :                 }
    2355   [ #  #  #  #  :          2 :                 sb->raid_size = raid_bdev->bdev.blockcnt;
          #  #  #  #  #  
                      # ]
    2356                 :          2 :                 raid_bdev_write_superblock(raid_bdev, raid_bdev_resize_write_sb_cb, NULL);
    2357                 :          0 :         }
    2358                 :          0 : }
    2359                 :            : 
    2360                 :            : /*
    2361                 :            :  * brief:
    2362                 :            :  * raid_bdev_event_base_bdev function is called by below layers when base_bdev
    2363                 :            :  * triggers asynchronous event.
    2364                 :            :  * params:
    2365                 :            :  * type - event details.
    2366                 :            :  * bdev - bdev that triggered event.
    2367                 :            :  * event_ctx - context for event.
    2368                 :            :  * returns:
    2369                 :            :  * none
    2370                 :            :  */
    2371                 :            : static void
    2372                 :        137 : raid_bdev_event_base_bdev(enum spdk_bdev_event_type type, struct spdk_bdev *bdev,
    2373                 :            :                           void *event_ctx)
    2374                 :            : {
    2375                 :            :         int rc;
    2376                 :            : 
    2377      [ +  +  - ]:        137 :         switch (type) {
    2378                 :        129 :         case SPDK_BDEV_EVENT_REMOVE:
    2379                 :        129 :                 rc = raid_bdev_remove_base_bdev(bdev, NULL, NULL);
    2380         [ -  + ]:        129 :                 if (rc != 0) {
    2381         [ #  # ]:          0 :                         SPDK_ERRLOG("Failed to remove base bdev %s: %s\n",
    2382                 :            :                                     spdk_bdev_get_name(bdev), spdk_strerror(-rc));
    2383                 :          0 :                 }
    2384                 :        129 :                 break;
    2385                 :          8 :         case SPDK_BDEV_EVENT_RESIZE:
    2386                 :          8 :                 raid_bdev_resize_base_bdev(bdev);
    2387                 :          8 :                 break;
    2388                 :          0 :         default:
    2389                 :          0 :                 SPDK_NOTICELOG("Unsupported bdev event: type %d\n", type);
    2390                 :          0 :                 break;
    2391                 :            :         }
    2392                 :        137 : }
    2393                 :            : 
    2394                 :            : /*
    2395                 :            :  * brief:
    2396                 :            :  * Deletes the specified raid bdev
    2397                 :            :  * params:
    2398                 :            :  * raid_bdev - pointer to raid bdev
    2399                 :            :  * cb_fn - callback function
    2400                 :            :  * cb_arg - argument to callback function
    2401                 :            :  */
    2402                 :            : void
    2403                 :        216 : raid_bdev_delete(struct raid_bdev *raid_bdev, raid_bdev_destruct_cb cb_fn, void *cb_arg)
    2404                 :            : {
    2405                 :            :         struct raid_base_bdev_info *base_info;
    2406                 :            : 
    2407   [ -  +  +  +  :        216 :         SPDK_DEBUGLOG(bdev_raid, "delete raid bdev: %s\n", raid_bdev->bdev.name);
          #  #  #  #  #  
                #  #  # ]
    2408                 :            : 
    2409   [ -  +  -  +  :        216 :         if (raid_bdev->destroy_started) {
             #  #  #  # ]
    2410   [ #  #  #  #  :          0 :                 SPDK_DEBUGLOG(bdev_raid, "destroying raid bdev %s is already started\n",
          #  #  #  #  #  
                #  #  # ]
    2411                 :            :                               raid_bdev->bdev.name);
    2412         [ #  # ]:          0 :                 if (cb_fn) {
    2413   [ #  #  #  # ]:          0 :                         cb_fn(cb_arg, -EALREADY);
    2414                 :          0 :                 }
    2415                 :          0 :                 return;
    2416                 :            :         }
    2417                 :            : 
    2418   [ #  #  #  # ]:        216 :         raid_bdev->destroy_started = true;
    2419                 :            : 
    2420   [ +  +  #  #  :       2239 :         RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) {
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
    2421   [ #  #  #  # ]:       2023 :                 base_info->remove_scheduled = true;
    2422                 :            : 
    2423   [ +  +  #  #  :       2023 :                 if (raid_bdev->state != RAID_BDEV_STATE_ONLINE) {
                   #  # ]
    2424                 :            :                         /*
    2425                 :            :                          * As raid bdev is not registered yet or already unregistered,
    2426                 :            :                          * so cleanup should be done here itself.
    2427                 :            :                          */
    2428                 :        402 :                         raid_bdev_free_base_bdev_resource(base_info);
    2429                 :          0 :                 }
    2430                 :          0 :         }
    2431                 :            : 
    2432   [ +  +  #  #  :        216 :         if (raid_bdev->num_base_bdevs_discovered == 0) {
                   #  # ]
    2433                 :            :                 /* There is no base bdev for this raid, so free the raid device. */
    2434                 :         78 :                 raid_bdev_cleanup_and_free(raid_bdev);
    2435         [ +  + ]:         78 :                 if (cb_fn) {
    2436   [ #  #  #  # ]:         50 :                         cb_fn(cb_arg, 0);
    2437                 :          0 :                 }
    2438                 :          0 :         } else {
    2439                 :        138 :                 raid_bdev_deconfigure(raid_bdev, cb_fn, cb_arg);
    2440                 :            :         }
    2441                 :          0 : }
    2442                 :            : 
    2443                 :            : static void
    2444                 :          9 : raid_bdev_process_finish_write_sb_cb(int status, struct raid_bdev *raid_bdev, void *ctx)
    2445                 :            : {
    2446         [ -  + ]:          9 :         if (status != 0) {
    2447   [ #  #  #  #  :          0 :                 SPDK_ERRLOG("Failed to write raid bdev '%s' superblock after background process finished: %s\n",
             #  #  #  # ]
    2448                 :            :                             raid_bdev->bdev.name, spdk_strerror(-status));
    2449                 :          0 :         }
    2450                 :          9 : }
    2451                 :            : 
    2452                 :            : static void
    2453                 :          9 : raid_bdev_process_finish_write_sb(void *ctx)
    2454                 :            : {
    2455                 :          9 :         struct raid_bdev *raid_bdev = ctx;
    2456   [ #  #  #  # ]:          9 :         struct raid_bdev_superblock *sb = raid_bdev->sb;
    2457                 :            :         struct raid_bdev_sb_base_bdev *sb_base_bdev;
    2458                 :            :         struct raid_base_bdev_info *base_info;
    2459                 :            :         uint8_t i;
    2460                 :            : 
    2461   [ +  +  #  #  :         34 :         for (i = 0; i < sb->base_bdevs_size; i++) {
                   #  # ]
    2462   [ #  #  #  # ]:         25 :                 sb_base_bdev = &sb->base_bdevs[i];
    2463                 :            : 
    2464   [ +  +  #  #  :         25 :                 if (sb_base_bdev->state != RAID_SB_BASE_BDEV_CONFIGURED &&
             #  #  #  # ]
    2465   [ +  -  #  #  :         11 :                     sb_base_bdev->slot < raid_bdev->num_base_bdevs) {
             #  #  #  # ]
    2466   [ #  #  #  #  :         11 :                         base_info = &raid_bdev->base_bdev_info[sb_base_bdev->slot];
          #  #  #  #  #  
                      # ]
    2467   [ -  +  +  +  :         11 :                         if (base_info->is_configured) {
             #  #  #  # ]
    2468   [ #  #  #  # ]:          9 :                                 sb_base_bdev->state = RAID_SB_BASE_BDEV_CONFIGURED;
    2469   [ #  #  #  #  :          9 :                                 sb_base_bdev->data_offset = base_info->data_offset;
             #  #  #  # ]
    2470   [ #  #  #  # ]:          9 :                                 spdk_uuid_copy(&sb_base_bdev->uuid, &base_info->uuid);
    2471                 :          0 :                         }
    2472                 :          0 :                 }
    2473                 :          0 :         }
    2474                 :            : 
    2475                 :          9 :         raid_bdev_write_superblock(raid_bdev, raid_bdev_process_finish_write_sb_cb, NULL);
    2476                 :          9 : }
    2477                 :            : 
    2478                 :            : static void raid_bdev_process_free(struct raid_bdev_process *process);
    2479                 :            : 
    2480                 :            : static void
    2481                 :         55 : _raid_bdev_process_finish_done(void *ctx)
    2482                 :            : {
    2483                 :         55 :         struct raid_bdev_process *process = ctx;
    2484                 :            :         struct raid_process_finish_action *finish_action;
    2485                 :            : 
    2486   [ +  +  #  #  :         89 :         while ((finish_action = TAILQ_FIRST(&process->finish_actions)) != NULL) {
             #  #  #  # ]
    2487   [ -  +  #  #  :         34 :                 TAILQ_REMOVE(&process->finish_actions, finish_action, link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
    2488   [ #  #  #  #  :         34 :                 finish_action->cb(finish_action->cb_ctx);
          #  #  #  #  #  
                #  #  # ]
    2489                 :         34 :                 free(finish_action);
    2490                 :            :         }
    2491                 :            : 
    2492   [ #  #  #  # ]:         55 :         spdk_poller_unregister(&process->qos.process_continue_poller);
    2493                 :            : 
    2494                 :         55 :         raid_bdev_process_free(process);
    2495                 :            : 
    2496                 :         55 :         spdk_thread_exit(spdk_get_thread());
    2497                 :         55 : }
    2498                 :            : 
    2499                 :            : static void
    2500                 :         34 : raid_bdev_process_finish_target_removed(void *ctx, int status)
    2501                 :            : {
    2502                 :         34 :         struct raid_bdev_process *process = ctx;
    2503                 :            : 
    2504         [ +  + ]:         34 :         if (status != 0) {
    2505         [ #  # ]:         33 :                 SPDK_ERRLOG("Failed to remove target bdev: %s\n", spdk_strerror(-status));
    2506                 :          0 :         }
    2507                 :            : 
    2508   [ #  #  #  # ]:         34 :         spdk_thread_send_msg(process->thread, _raid_bdev_process_finish_done, process);
    2509                 :         34 : }
    2510                 :            : 
    2511                 :            : static void
    2512                 :         55 : raid_bdev_process_finish_unquiesced(void *ctx, int status)
    2513                 :            : {
    2514                 :         55 :         struct raid_bdev_process *process = ctx;
    2515                 :            : 
    2516         [ -  + ]:         55 :         if (status != 0) {
    2517         [ #  # ]:          0 :                 SPDK_ERRLOG("Failed to unquiesce bdev: %s\n", spdk_strerror(-status));
    2518                 :          0 :         }
    2519                 :            : 
    2520   [ +  +  #  #  :         55 :         if (process->status != 0) {
                   #  # ]
    2521   [ #  #  #  # ]:         34 :                 status = _raid_bdev_remove_base_bdev(process->target, raid_bdev_process_finish_target_removed,
    2522                 :          0 :                                                      process);
    2523         [ +  + ]:         34 :                 if (status != 0) {
    2524                 :         33 :                         raid_bdev_process_finish_target_removed(process, status);
    2525                 :          0 :                 }
    2526                 :         34 :                 return;
    2527                 :            :         }
    2528                 :            : 
    2529   [ #  #  #  # ]:         21 :         spdk_thread_send_msg(process->thread, _raid_bdev_process_finish_done, process);
    2530                 :          0 : }
    2531                 :            : 
    2532                 :            : static void
    2533                 :         55 : raid_bdev_process_finish_unquiesce(void *ctx)
    2534                 :            : {
    2535                 :         55 :         struct raid_bdev_process *process = ctx;
    2536                 :            :         int rc;
    2537                 :            : 
    2538   [ #  #  #  #  :         55 :         rc = spdk_bdev_unquiesce(&process->raid_bdev->bdev, &g_raid_if,
                   #  # ]
    2539                 :          0 :                                  raid_bdev_process_finish_unquiesced, process);
    2540         [ -  + ]:         55 :         if (rc != 0) {
    2541                 :          0 :                 raid_bdev_process_finish_unquiesced(process, rc);
    2542                 :          0 :         }
    2543                 :         55 : }
    2544                 :            : 
    2545                 :            : static void
    2546                 :         55 : raid_bdev_process_finish_done(void *ctx)
    2547                 :            : {
    2548                 :         55 :         struct raid_bdev_process *process = ctx;
    2549   [ #  #  #  # ]:         55 :         struct raid_bdev *raid_bdev = process->raid_bdev;
    2550                 :            : 
    2551   [ +  -  #  #  :         55 :         if (process->raid_ch != NULL) {
                   #  # ]
    2552   [ #  #  #  # ]:         55 :                 spdk_put_io_channel(spdk_io_channel_from_ctx(process->raid_ch));
    2553                 :          0 :         }
    2554                 :            : 
    2555   [ #  #  #  # ]:         55 :         process->state = RAID_PROCESS_STATE_STOPPED;
    2556                 :            : 
    2557   [ +  +  #  #  :         55 :         if (process->status == 0) {
                   #  # ]
    2558   [ #  #  #  #  :         21 :                 SPDK_NOTICELOG("Finished %s on raid bdev %s\n",
          #  #  #  #  #  
                      # ]
    2559                 :            :                                raid_bdev_process_to_str(process->type),
    2560                 :            :                                raid_bdev->bdev.name);
    2561   [ -  +  +  +  :         21 :                 if (raid_bdev->superblock_enabled) {
             #  #  #  # ]
    2562                 :          9 :                         spdk_thread_send_msg(spdk_thread_get_app_thread(),
    2563                 :            :                                              raid_bdev_process_finish_write_sb,
    2564                 :          0 :                                              raid_bdev);
    2565                 :          0 :                 }
    2566                 :          0 :         } else {
    2567   [ #  #  #  #  :         34 :                 SPDK_WARNLOG("Finished %s on raid bdev %s: %s\n",
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    2568                 :            :                              raid_bdev_process_to_str(process->type),
    2569                 :            :                              raid_bdev->bdev.name,
    2570                 :            :                              spdk_strerror(-process->status));
    2571                 :            :         }
    2572                 :            : 
    2573                 :         55 :         spdk_thread_send_msg(spdk_thread_get_app_thread(), raid_bdev_process_finish_unquiesce,
    2574                 :          0 :                              process);
    2575                 :         55 : }
    2576                 :            : 
    2577                 :            : static void
    2578                 :         55 : __raid_bdev_process_finish(struct spdk_io_channel_iter *i, int status)
    2579                 :            : {
    2580                 :         55 :         struct raid_bdev_process *process = spdk_io_channel_iter_get_ctx(i);
    2581                 :            : 
    2582   [ #  #  #  # ]:         55 :         spdk_thread_send_msg(process->thread, raid_bdev_process_finish_done, process);
    2583                 :         55 : }
    2584                 :            : 
    2585                 :            : static void
    2586                 :         63 : raid_bdev_channel_process_finish(struct spdk_io_channel_iter *i)
    2587                 :            : {
    2588                 :         63 :         struct raid_bdev_process *process = spdk_io_channel_iter_get_ctx(i);
    2589                 :         63 :         struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(i);
    2590                 :         63 :         struct raid_bdev_io_channel *raid_ch = spdk_io_channel_get_ctx(ch);
    2591                 :            : 
    2592   [ +  +  #  #  :         63 :         if (process->status == 0) {
                   #  # ]
    2593   [ #  #  #  # ]:         25 :                 uint8_t slot = raid_bdev_base_bdev_slot(process->target);
    2594                 :            : 
    2595   [ #  #  #  #  :         25 :                 raid_ch->base_channel[slot] = raid_ch->process.target_ch;
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    2596   [ #  #  #  #  :         25 :                 raid_ch->process.target_ch = NULL;
                   #  # ]
    2597                 :          0 :         }
    2598                 :            : 
    2599                 :         63 :         raid_bdev_ch_process_cleanup(raid_ch);
    2600                 :            : 
    2601                 :         63 :         spdk_for_each_channel_continue(i, 0);
    2602                 :         63 : }
    2603                 :            : 
    2604                 :            : static void
    2605                 :         55 : raid_bdev_process_finish_quiesced(void *ctx, int status)
    2606                 :            : {
    2607                 :         55 :         struct raid_bdev_process *process = ctx;
    2608   [ #  #  #  # ]:         55 :         struct raid_bdev *raid_bdev = process->raid_bdev;
    2609                 :            : 
    2610         [ -  + ]:         55 :         if (status != 0) {
    2611         [ #  # ]:          0 :                 SPDK_ERRLOG("Failed to quiesce bdev: %s\n", spdk_strerror(-status));
    2612                 :          0 :                 return;
    2613                 :            :         }
    2614                 :            : 
    2615   [ #  #  #  # ]:         55 :         raid_bdev->process = NULL;
    2616   [ #  #  #  #  :         55 :         process->target->is_process_target = false;
             #  #  #  # ]
    2617                 :            : 
    2618   [ #  #  #  # ]:         55 :         spdk_for_each_channel(process->raid_bdev, raid_bdev_channel_process_finish, process,
    2619                 :            :                               __raid_bdev_process_finish);
    2620                 :          0 : }
    2621                 :            : 
    2622                 :            : static void
    2623                 :         55 : _raid_bdev_process_finish(void *ctx)
    2624                 :            : {
    2625                 :         55 :         struct raid_bdev_process *process = ctx;
    2626                 :            :         int rc;
    2627                 :            : 
    2628   [ #  #  #  #  :         55 :         rc = spdk_bdev_quiesce(&process->raid_bdev->bdev, &g_raid_if,
                   #  # ]
    2629                 :          0 :                                raid_bdev_process_finish_quiesced, process);
    2630         [ -  + ]:         55 :         if (rc != 0) {
    2631                 :          0 :                 raid_bdev_process_finish_quiesced(ctx, rc);
    2632                 :          0 :         }
    2633                 :         55 : }
    2634                 :            : 
    2635                 :            : static void
    2636                 :         55 : raid_bdev_process_do_finish(struct raid_bdev_process *process)
    2637                 :            : {
    2638                 :         55 :         spdk_thread_send_msg(spdk_thread_get_app_thread(), _raid_bdev_process_finish, process);
    2639                 :         55 : }
    2640                 :            : 
    2641                 :            : static void raid_bdev_process_unlock_window_range(struct raid_bdev_process *process);
    2642                 :            : static void raid_bdev_process_thread_run(struct raid_bdev_process *process);
    2643                 :            : 
    2644                 :            : static void
    2645                 :         21 : raid_bdev_process_finish(struct raid_bdev_process *process, int status)
    2646                 :            : {
    2647   [ -  +  #  #  :         21 :         assert(spdk_get_thread() == process->thread);
             #  #  #  # ]
    2648                 :            : 
    2649   [ +  -  #  #  :         21 :         if (process->status == 0) {
                   #  # ]
    2650   [ #  #  #  # ]:         21 :                 process->status = status;
    2651                 :          0 :         }
    2652                 :            : 
    2653   [ -  +  #  #  :         21 :         if (process->state >= RAID_PROCESS_STATE_STOPPING) {
                   #  # ]
    2654                 :          0 :                 return;
    2655                 :            :         }
    2656                 :            : 
    2657   [ -  +  #  #  :         21 :         assert(process->state == RAID_PROCESS_STATE_RUNNING);
             #  #  #  # ]
    2658   [ #  #  #  # ]:         21 :         process->state = RAID_PROCESS_STATE_STOPPING;
    2659                 :            : 
    2660   [ -  +  -  +  :         21 :         if (process->window_range_locked) {
             #  #  #  # ]
    2661                 :          0 :                 raid_bdev_process_unlock_window_range(process);
    2662                 :          0 :         } else {
    2663                 :         21 :                 raid_bdev_process_thread_run(process);
    2664                 :            :         }
    2665                 :          0 : }
    2666                 :            : 
    2667                 :            : static void
    2668                 :       1106 : raid_bdev_process_window_range_unlocked(void *ctx, int status)
    2669                 :            : {
    2670                 :       1106 :         struct raid_bdev_process *process = ctx;
    2671                 :            : 
    2672         [ -  + ]:       1106 :         if (status != 0) {
    2673         [ #  # ]:          0 :                 SPDK_ERRLOG("Failed to unlock LBA range: %s\n", spdk_strerror(-status));
    2674                 :          0 :                 raid_bdev_process_finish(process, status);
    2675                 :          0 :                 return;
    2676                 :            :         }
    2677                 :            : 
    2678   [ #  #  #  # ]:       1106 :         process->window_range_locked = false;
    2679   [ #  #  #  #  :       1106 :         process->window_offset += process->window_size;
             #  #  #  # ]
    2680                 :            : 
    2681                 :       1106 :         raid_bdev_process_thread_run(process);
    2682                 :          0 : }
    2683                 :            : 
    2684                 :            : static void
    2685                 :       1106 : raid_bdev_process_unlock_window_range(struct raid_bdev_process *process)
    2686                 :            : {
    2687                 :            :         int rc;
    2688                 :            : 
    2689   [ -  +  -  +  :       1106 :         assert(process->window_range_locked == true);
          #  #  #  #  #  
                      # ]
    2690                 :            : 
    2691   [ #  #  #  #  :       1106 :         rc = spdk_bdev_unquiesce_range(&process->raid_bdev->bdev, &g_raid_if,
                   #  # ]
    2692   [ #  #  #  #  :          0 :                                        process->window_offset, process->max_window_size,
             #  #  #  # ]
    2693                 :          0 :                                        raid_bdev_process_window_range_unlocked, process);
    2694         [ -  + ]:       1106 :         if (rc != 0) {
    2695                 :          0 :                 raid_bdev_process_window_range_unlocked(process, rc);
    2696                 :          0 :         }
    2697                 :       1106 : }
    2698                 :            : 
    2699                 :            : static void
    2700                 :       1106 : raid_bdev_process_channels_update_done(struct spdk_io_channel_iter *i, int status)
    2701                 :            : {
    2702                 :       1106 :         struct raid_bdev_process *process = spdk_io_channel_iter_get_ctx(i);
    2703                 :            : 
    2704                 :       1106 :         raid_bdev_process_unlock_window_range(process);
    2705                 :       1106 : }
    2706                 :            : 
    2707                 :            : static void
    2708                 :       1264 : raid_bdev_process_channel_update(struct spdk_io_channel_iter *i)
    2709                 :            : {
    2710                 :       1264 :         struct raid_bdev_process *process = spdk_io_channel_iter_get_ctx(i);
    2711                 :       1264 :         struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(i);
    2712                 :       1264 :         struct raid_bdev_io_channel *raid_ch = spdk_io_channel_get_ctx(ch);
    2713                 :            : 
    2714   [ #  #  #  #  :       1264 :         raid_ch->process.offset = process->window_offset + process->window_size;
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    2715                 :            : 
    2716                 :       1264 :         spdk_for_each_channel_continue(i, 0);
    2717                 :       1264 : }
    2718                 :            : 
    2719                 :            : void
    2720                 :       3321 : raid_bdev_process_request_complete(struct raid_bdev_process_request *process_req, int status)
    2721                 :            : {
    2722   [ #  #  #  # ]:       3321 :         struct raid_bdev_process *process = process_req->process;
    2723                 :            : 
    2724   [ #  #  #  #  :       3321 :         TAILQ_INSERT_TAIL(&process->requests, process_req, link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    2725                 :            : 
    2726   [ -  +  #  #  :       3321 :         assert(spdk_get_thread() == process->thread);
             #  #  #  # ]
    2727   [ -  +  #  #  :       3321 :         assert(process->window_remaining >= process_req->num_blocks);
          #  #  #  #  #  
                #  #  # ]
    2728                 :            : 
    2729         [ -  + ]:       3321 :         if (status != 0) {
    2730   [ #  #  #  # ]:          0 :                 process->window_status = status;
    2731                 :          0 :         }
    2732                 :            : 
    2733   [ #  #  #  #  :       3321 :         process->window_remaining -= process_req->num_blocks;
             #  #  #  # ]
    2734   [ +  +  #  #  :       3321 :         if (process->window_remaining == 0) {
                   #  # ]
    2735   [ -  +  #  #  :       1106 :                 if (process->window_status != 0) {
                   #  # ]
    2736   [ #  #  #  # ]:          0 :                         raid_bdev_process_finish(process, process->window_status);
    2737                 :          0 :                         return;
    2738                 :            :                 }
    2739                 :            : 
    2740   [ #  #  #  # ]:       1106 :                 spdk_for_each_channel(process->raid_bdev, raid_bdev_process_channel_update, process,
    2741                 :            :                                       raid_bdev_process_channels_update_done);
    2742                 :          0 :         }
    2743                 :          0 : }
    2744                 :            : 
    2745                 :            : static int
    2746                 :       3570 : raid_bdev_submit_process_request(struct raid_bdev_process *process, uint64_t offset_blocks,
    2747                 :            :                                  uint32_t num_blocks)
    2748                 :            : {
    2749   [ #  #  #  # ]:       3570 :         struct raid_bdev *raid_bdev = process->raid_bdev;
    2750                 :            :         struct raid_bdev_process_request *process_req;
    2751                 :            :         int ret;
    2752                 :            : 
    2753   [ #  #  #  #  :       3570 :         process_req = TAILQ_FIRST(&process->requests);
                   #  # ]
    2754         [ -  + ]:       3570 :         if (process_req == NULL) {
    2755   [ #  #  #  #  :          0 :                 assert(process->window_remaining > 0);
             #  #  #  # ]
    2756                 :          0 :                 return 0;
    2757                 :            :         }
    2758                 :            : 
    2759   [ #  #  #  #  :       3570 :         process_req->target = process->target;
             #  #  #  # ]
    2760   [ #  #  #  #  :       3570 :         process_req->target_ch = process->raid_ch->process.target_ch;
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    2761   [ #  #  #  # ]:       3570 :         process_req->offset_blocks = offset_blocks;
    2762   [ #  #  #  # ]:       3570 :         process_req->num_blocks = num_blocks;
    2763   [ #  #  #  #  :       3570 :         process_req->iov.iov_len = num_blocks * raid_bdev->bdev.blocklen;
          #  #  #  #  #  
                #  #  # ]
    2764                 :            : 
    2765   [ #  #  #  #  :       3570 :         ret = raid_bdev->module->submit_process_request(process_req, process->raid_ch);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    2766         [ +  + ]:       3570 :         if (ret <= 0) {
    2767         [ -  + ]:        249 :                 if (ret < 0) {
    2768   [ #  #  #  #  :          0 :                         SPDK_ERRLOG("Failed to submit process request on %s: %s\n",
             #  #  #  # ]
    2769                 :            :                                     raid_bdev->bdev.name, spdk_strerror(-ret));
    2770   [ #  #  #  # ]:          0 :                         process->window_status = ret;
    2771                 :          0 :                 }
    2772                 :        249 :                 return ret;
    2773                 :            :         }
    2774                 :            : 
    2775   [ #  #  #  # ]:       3321 :         process_req->num_blocks = ret;
    2776   [ +  -  #  #  :       3321 :         TAILQ_REMOVE(&process->requests, process_req, link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
    2777                 :            : 
    2778                 :       3321 :         return ret;
    2779                 :          0 : }
    2780                 :            : 
    2781                 :            : static void
    2782                 :       1106 : _raid_bdev_process_thread_run(struct raid_bdev_process *process)
    2783                 :            : {
    2784   [ #  #  #  # ]:       1106 :         struct raid_bdev *raid_bdev = process->raid_bdev;
    2785   [ #  #  #  # ]:       1106 :         uint64_t offset = process->window_offset;
    2786   [ #  #  #  #  :       1106 :         const uint64_t offset_end = spdk_min(offset + process->max_window_size, raid_bdev->bdev.blockcnt);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
    2787                 :            :         int ret;
    2788                 :            : 
    2789         [ +  + ]:       4427 :         while (offset < offset_end) {
    2790                 :       3570 :                 ret = raid_bdev_submit_process_request(process, offset, offset_end - offset);
    2791         [ +  + ]:       3570 :                 if (ret <= 0) {
    2792                 :        249 :                         break;
    2793                 :            :                 }
    2794                 :            : 
    2795   [ #  #  #  # ]:       3321 :                 process->window_remaining += ret;
    2796                 :       3321 :                 offset += ret;
    2797                 :            :         }
    2798                 :            : 
    2799   [ +  -  #  #  :       1106 :         if (process->window_remaining > 0) {
                   #  # ]
    2800   [ #  #  #  #  :       1106 :                 process->window_size = process->window_remaining;
             #  #  #  # ]
    2801                 :          0 :         } else {
    2802   [ #  #  #  # ]:          0 :                 raid_bdev_process_finish(process, process->window_status);
    2803                 :            :         }
    2804                 :       1106 : }
    2805                 :            : 
    2806                 :            : static void
    2807                 :       1106 : raid_bdev_process_window_range_locked(void *ctx, int status)
    2808                 :            : {
    2809                 :       1106 :         struct raid_bdev_process *process = ctx;
    2810                 :            : 
    2811         [ -  + ]:       1106 :         if (status != 0) {
    2812         [ #  # ]:          0 :                 SPDK_ERRLOG("Failed to lock LBA range: %s\n", spdk_strerror(-status));
    2813                 :          0 :                 raid_bdev_process_finish(process, status);
    2814                 :          0 :                 return;
    2815                 :            :         }
    2816                 :            : 
    2817   [ #  #  #  # ]:       1106 :         process->window_range_locked = true;
    2818                 :            : 
    2819   [ -  +  #  #  :       1106 :         if (process->state == RAID_PROCESS_STATE_STOPPING) {
                   #  # ]
    2820                 :          0 :                 raid_bdev_process_unlock_window_range(process);
    2821                 :          0 :                 return;
    2822                 :            :         }
    2823                 :            : 
    2824                 :       1106 :         _raid_bdev_process_thread_run(process);
    2825                 :          0 : }
    2826                 :            : 
    2827                 :            : static bool
    2828                 :         36 : raid_bdev_process_consume_token(struct raid_bdev_process *process)
    2829                 :            : {
    2830   [ #  #  #  # ]:         36 :         struct raid_bdev *raid_bdev = process->raid_bdev;
    2831                 :         36 :         uint64_t now = spdk_get_ticks();
    2832                 :            : 
    2833   [ +  +  #  #  :         36 :         process->qos.bytes_available = spdk_min(process->qos.bytes_max,
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    2834                 :            :                                                 process->qos.bytes_available +
    2835                 :            :                                                 (now - process->qos.last_tsc) * process->qos.bytes_per_tsc);
    2836   [ #  #  #  #  :         36 :         process->qos.last_tsc = now;
                   #  # ]
    2837   [ +  +  #  #  :         36 :         if (process->qos.bytes_available > 0.0) {
             #  #  #  # ]
    2838   [ #  #  #  #  :          3 :                 process->qos.bytes_available -= process->window_size * raid_bdev->bdev.blocklen;
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    2839                 :          3 :                 return true;
    2840                 :            :         }
    2841                 :         33 :         return false;
    2842                 :          0 : }
    2843                 :            : 
    2844                 :            : static bool
    2845                 :       1139 : raid_bdev_process_lock_window_range(struct raid_bdev_process *process)
    2846                 :            : {
    2847   [ #  #  #  # ]:       1139 :         struct raid_bdev *raid_bdev = process->raid_bdev;
    2848                 :            :         int rc;
    2849                 :            : 
    2850   [ -  +  -  +  :       1139 :         assert(process->window_range_locked == false);
          #  #  #  #  #  
                      # ]
    2851                 :            : 
    2852   [ +  +  +  +  :       1139 :         if (process->qos.enable_qos) {
          #  #  #  #  #  
                      # ]
    2853         [ +  + ]:         36 :                 if (raid_bdev_process_consume_token(process)) {
    2854   [ #  #  #  #  :          3 :                         spdk_poller_pause(process->qos.process_continue_poller);
                   #  # ]
    2855                 :          0 :                 } else {
    2856   [ #  #  #  #  :         33 :                         spdk_poller_resume(process->qos.process_continue_poller);
                   #  # ]
    2857                 :         33 :                         return false;
    2858                 :            :                 }
    2859                 :          0 :         }
    2860                 :            : 
    2861         [ #  # ]:       1106 :         rc = spdk_bdev_quiesce_range(&raid_bdev->bdev, &g_raid_if,
    2862   [ #  #  #  #  :          0 :                                      process->window_offset, process->max_window_size,
             #  #  #  # ]
    2863                 :          0 :                                      raid_bdev_process_window_range_locked, process);
    2864         [ -  + ]:       1106 :         if (rc != 0) {
    2865                 :          0 :                 raid_bdev_process_window_range_locked(process, rc);
    2866                 :          0 :         }
    2867                 :       1106 :         return true;
    2868                 :          0 : }
    2869                 :            : 
    2870                 :            : static int
    2871                 :         33 : raid_bdev_process_continue_poll(void *arg)
    2872                 :            : {
    2873                 :         33 :         struct raid_bdev_process *process = arg;
    2874                 :            : 
    2875         [ +  + ]:         33 :         if (raid_bdev_process_lock_window_range(process)) {
    2876                 :          3 :                 return SPDK_POLLER_BUSY;
    2877                 :            :         }
    2878                 :         30 :         return SPDK_POLLER_IDLE;
    2879                 :          0 : }
    2880                 :            : 
    2881                 :            : static void
    2882                 :       1182 : raid_bdev_process_thread_run(struct raid_bdev_process *process)
    2883                 :            : {
    2884   [ #  #  #  # ]:       1182 :         struct raid_bdev *raid_bdev = process->raid_bdev;
    2885                 :            : 
    2886   [ -  +  #  #  :       1182 :         assert(spdk_get_thread() == process->thread);
             #  #  #  # ]
    2887   [ -  +  #  #  :       1182 :         assert(process->window_remaining == 0);
             #  #  #  # ]
    2888   [ -  +  -  +  :       1182 :         assert(process->window_range_locked == false);
          #  #  #  #  #  
                      # ]
    2889                 :            : 
    2890   [ +  +  #  #  :       1182 :         if (process->state == RAID_PROCESS_STATE_STOPPING) {
                   #  # ]
    2891                 :         55 :                 raid_bdev_process_do_finish(process);
    2892                 :         55 :                 return;
    2893                 :            :         }
    2894                 :            : 
    2895   [ +  +  #  #  :       1127 :         if (process->window_offset == raid_bdev->bdev.blockcnt) {
          #  #  #  #  #  
                #  #  # ]
    2896   [ -  +  +  +  :         21 :                 SPDK_DEBUGLOG(bdev_raid, "process completed on %s\n", raid_bdev->bdev.name);
          #  #  #  #  #  
                #  #  # ]
    2897                 :         21 :                 raid_bdev_process_finish(process, 0);
    2898                 :         21 :                 return;
    2899                 :            :         }
    2900                 :            : 
    2901   [ #  #  #  #  :       1106 :         process->max_window_size = spdk_min(raid_bdev->bdev.blockcnt - process->window_offset,
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    2902                 :            :                                             process->max_window_size);
    2903                 :       1106 :         raid_bdev_process_lock_window_range(process);
    2904                 :          0 : }
    2905                 :            : 
    2906                 :            : static void
    2907                 :         55 : raid_bdev_process_thread_init(void *ctx)
    2908                 :            : {
    2909                 :         55 :         struct raid_bdev_process *process = ctx;
    2910   [ #  #  #  # ]:         55 :         struct raid_bdev *raid_bdev = process->raid_bdev;
    2911                 :            :         struct spdk_io_channel *ch;
    2912                 :            : 
    2913   [ #  #  #  # ]:         55 :         process->thread = spdk_get_thread();
    2914                 :            : 
    2915                 :         55 :         ch = spdk_get_io_channel(raid_bdev);
    2916         [ -  + ]:         55 :         if (ch == NULL) {
    2917   [ #  #  #  # ]:          0 :                 process->status = -ENOMEM;
    2918                 :          0 :                 raid_bdev_process_do_finish(process);
    2919                 :          0 :                 return;
    2920                 :            :         }
    2921                 :            : 
    2922   [ #  #  #  # ]:         55 :         process->raid_ch = spdk_io_channel_get_ctx(ch);
    2923   [ #  #  #  # ]:         55 :         process->state = RAID_PROCESS_STATE_RUNNING;
    2924                 :            : 
    2925   [ +  +  +  +  :         55 :         if (process->qos.enable_qos) {
          #  #  #  #  #  
                      # ]
    2926   [ #  #  #  #  :          3 :                 process->qos.process_continue_poller = SPDK_POLLER_REGISTER(raid_bdev_process_continue_poll,
                   #  # ]
    2927                 :            :                                                        process, 0);
    2928   [ #  #  #  #  :          3 :                 spdk_poller_pause(process->qos.process_continue_poller);
                   #  # ]
    2929                 :          0 :         }
    2930                 :            : 
    2931   [ #  #  #  #  :         55 :         SPDK_NOTICELOG("Started %s on raid bdev %s\n",
          #  #  #  #  #  
                      # ]
    2932                 :            :                        raid_bdev_process_to_str(process->type), raid_bdev->bdev.name);
    2933                 :            : 
    2934                 :         55 :         raid_bdev_process_thread_run(process);
    2935                 :          0 : }
    2936                 :            : 
    2937                 :            : static void
    2938                 :          0 : raid_bdev_channels_abort_start_process_done(struct spdk_io_channel_iter *i, int status)
    2939                 :            : {
    2940                 :          0 :         struct raid_bdev_process *process = spdk_io_channel_iter_get_ctx(i);
    2941                 :            : 
    2942   [ #  #  #  # ]:          0 :         _raid_bdev_remove_base_bdev(process->target, NULL, NULL);
    2943                 :          0 :         raid_bdev_process_free(process);
    2944                 :            : 
    2945                 :            :         /* TODO: update sb */
    2946                 :          0 : }
    2947                 :            : 
    2948                 :            : static void
    2949                 :          0 : raid_bdev_channel_abort_start_process(struct spdk_io_channel_iter *i)
    2950                 :            : {
    2951                 :          0 :         struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(i);
    2952                 :          0 :         struct raid_bdev_io_channel *raid_ch = spdk_io_channel_get_ctx(ch);
    2953                 :            : 
    2954                 :          0 :         raid_bdev_ch_process_cleanup(raid_ch);
    2955                 :            : 
    2956                 :          0 :         spdk_for_each_channel_continue(i, 0);
    2957                 :          0 : }
    2958                 :            : 
    2959                 :            : static void
    2960                 :         55 : raid_bdev_channels_start_process_done(struct spdk_io_channel_iter *i, int status)
    2961                 :            : {
    2962                 :         55 :         struct raid_bdev_process *process = spdk_io_channel_iter_get_ctx(i);
    2963   [ #  #  #  # ]:         55 :         struct raid_bdev *raid_bdev = process->raid_bdev;
    2964                 :            :         struct spdk_thread *thread;
    2965                 :         55 :         char thread_name[RAID_BDEV_SB_NAME_SIZE + 16];
    2966                 :            : 
    2967   [ +  -  #  # ]:         55 :         if (status == 0 &&
    2968   [ +  +  +  -  :         55 :             (process->target->remove_scheduled || !process->target->is_configured ||
          -  +  +  -  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    2969   [ -  +  #  #  :         55 :              raid_bdev->num_base_bdevs_operational <= raid_bdev->min_base_bdevs_operational)) {
             #  #  #  # ]
    2970                 :            :                 /* a base bdev was removed before we got here */
    2971                 :          0 :                 status = -ENODEV;
    2972                 :          0 :         }
    2973                 :            : 
    2974         [ -  + ]:         55 :         if (status != 0) {
    2975   [ #  #  #  #  :          0 :                 SPDK_ERRLOG("Failed to start %s on %s: %s\n",
          #  #  #  #  #  
                #  #  # ]
    2976                 :            :                             raid_bdev_process_to_str(process->type), raid_bdev->bdev.name,
    2977                 :            :                             spdk_strerror(-status));
    2978                 :          0 :                 goto err;
    2979                 :            :         }
    2980                 :            : 
    2981         [ -  + ]:         55 :         snprintf(thread_name, sizeof(thread_name), "%s_%s",
    2982   [ #  #  #  #  :          0 :                  raid_bdev->bdev.name, raid_bdev_process_to_str(process->type));
          #  #  #  #  #  
                      # ]
    2983                 :            : 
    2984                 :         55 :         thread = spdk_thread_create(thread_name, NULL);
    2985         [ -  + ]:         55 :         if (thread == NULL) {
    2986   [ #  #  #  #  :          0 :                 SPDK_ERRLOG("Failed to create %s thread for %s\n",
          #  #  #  #  #  
                      # ]
    2987                 :            :                             raid_bdev_process_to_str(process->type), raid_bdev->bdev.name);
    2988                 :          0 :                 goto err;
    2989                 :            :         }
    2990                 :            : 
    2991   [ #  #  #  # ]:         55 :         raid_bdev->process = process;
    2992                 :            : 
    2993                 :         55 :         spdk_thread_send_msg(thread, raid_bdev_process_thread_init, process);
    2994                 :            : 
    2995                 :         55 :         return;
    2996                 :          0 : err:
    2997   [ #  #  #  # ]:          0 :         spdk_for_each_channel(process->raid_bdev, raid_bdev_channel_abort_start_process, process,
    2998                 :            :                               raid_bdev_channels_abort_start_process_done);
    2999                 :          0 : }
    3000                 :            : 
    3001                 :            : static void
    3002                 :          8 : raid_bdev_channel_start_process(struct spdk_io_channel_iter *i)
    3003                 :            : {
    3004                 :          8 :         struct raid_bdev_process *process = spdk_io_channel_iter_get_ctx(i);
    3005                 :          8 :         struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(i);
    3006                 :          8 :         struct raid_bdev_io_channel *raid_ch = spdk_io_channel_get_ctx(ch);
    3007                 :            :         int rc;
    3008                 :            : 
    3009                 :          8 :         rc = raid_bdev_ch_process_setup(raid_ch, process);
    3010                 :            : 
    3011                 :          8 :         spdk_for_each_channel_continue(i, rc);
    3012                 :          8 : }
    3013                 :            : 
    3014                 :            : static void
    3015                 :         55 : raid_bdev_process_start(struct raid_bdev_process *process)
    3016                 :            : {
    3017   [ #  #  #  # ]:         55 :         struct raid_bdev *raid_bdev = process->raid_bdev;
    3018                 :            : 
    3019   [ -  +  #  #  :         55 :         assert(raid_bdev->module->submit_process_request != NULL);
          #  #  #  #  #  
                #  #  # ]
    3020                 :            : 
    3021                 :         55 :         spdk_for_each_channel(raid_bdev, raid_bdev_channel_start_process, process,
    3022                 :            :                               raid_bdev_channels_start_process_done);
    3023                 :         55 : }
    3024                 :            : 
    3025                 :            : static void
    3026                 :        880 : raid_bdev_process_request_free(struct raid_bdev_process_request *process_req)
    3027                 :            : {
    3028   [ #  #  #  #  :        880 :         spdk_dma_free(process_req->iov.iov_base);
                   #  # ]
    3029   [ #  #  #  # ]:        880 :         spdk_dma_free(process_req->md_buf);
    3030                 :        880 :         free(process_req);
    3031                 :        880 : }
    3032                 :            : 
    3033                 :            : static struct raid_bdev_process_request *
    3034                 :        880 : raid_bdev_process_alloc_request(struct raid_bdev_process *process)
    3035                 :            : {
    3036   [ #  #  #  # ]:        880 :         struct raid_bdev *raid_bdev = process->raid_bdev;
    3037                 :            :         struct raid_bdev_process_request *process_req;
    3038                 :            : 
    3039                 :        880 :         process_req = calloc(1, sizeof(*process_req));
    3040         [ -  + ]:        880 :         if (process_req == NULL) {
    3041                 :          0 :                 return NULL;
    3042                 :            :         }
    3043                 :            : 
    3044   [ #  #  #  # ]:        880 :         process_req->process = process;
    3045   [ #  #  #  #  :        880 :         process_req->iov.iov_len = process->max_window_size * raid_bdev->bdev.blocklen;
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    3046   [ #  #  #  #  :        880 :         process_req->iov.iov_base = spdk_dma_malloc(process_req->iov.iov_len, 4096, 0);
          #  #  #  #  #  
                #  #  # ]
    3047   [ -  +  #  #  :        880 :         if (process_req->iov.iov_base == NULL) {
             #  #  #  # ]
    3048                 :          0 :                 free(process_req);
    3049                 :          0 :                 return NULL;
    3050                 :            :         }
    3051   [ +  +  #  # ]:        880 :         if (spdk_bdev_is_md_separate(&raid_bdev->bdev)) {
    3052   [ #  #  #  #  :        160 :                 process_req->md_buf = spdk_dma_malloc(process->max_window_size * raid_bdev->bdev.md_len, 4096, 0);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    3053   [ -  +  #  #  :        160 :                 if (process_req->md_buf == NULL) {
                   #  # ]
    3054                 :          0 :                         raid_bdev_process_request_free(process_req);
    3055                 :          0 :                         return NULL;
    3056                 :            :                 }
    3057                 :          0 :         }
    3058                 :            : 
    3059                 :        880 :         return process_req;
    3060                 :          0 : }
    3061                 :            : 
    3062                 :            : static void
    3063                 :         55 : raid_bdev_process_free(struct raid_bdev_process *process)
    3064                 :            : {
    3065                 :            :         struct raid_bdev_process_request *process_req;
    3066                 :            : 
    3067   [ +  +  #  #  :        935 :         while ((process_req = TAILQ_FIRST(&process->requests)) != NULL) {
             #  #  #  # ]
    3068   [ +  +  #  #  :        880 :                 TAILQ_REMOVE(&process->requests, process_req, link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
    3069                 :        880 :                 raid_bdev_process_request_free(process_req);
    3070                 :            :         }
    3071                 :            : 
    3072                 :         55 :         free(process);
    3073                 :         55 : }
    3074                 :            : 
    3075                 :            : static struct raid_bdev_process *
    3076                 :         55 : raid_bdev_process_alloc(struct raid_bdev *raid_bdev, enum raid_process_type type,
    3077                 :            :                         struct raid_base_bdev_info *target)
    3078                 :            : {
    3079                 :            :         struct raid_bdev_process *process;
    3080                 :            :         struct raid_bdev_process_request *process_req;
    3081                 :            :         int i;
    3082                 :            : 
    3083                 :         55 :         process = calloc(1, sizeof(*process));
    3084         [ -  + ]:         55 :         if (process == NULL) {
    3085                 :          0 :                 return NULL;
    3086                 :            :         }
    3087                 :            : 
    3088   [ #  #  #  # ]:         55 :         process->raid_bdev = raid_bdev;
    3089   [ #  #  #  # ]:         55 :         process->type = type;
    3090   [ #  #  #  # ]:         55 :         process->target = target;
    3091   [ +  -  #  #  :         55 :         process->max_window_size = spdk_max(spdk_divide_round_up(g_opts.process_window_size_kb * 1024UL,
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
    3092                 :            :                                             spdk_bdev_get_data_block_size(&raid_bdev->bdev)),
    3093                 :            :                                             raid_bdev->bdev.write_unit_size);
    3094   [ #  #  #  #  :         55 :         TAILQ_INIT(&process->requests);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    3095   [ #  #  #  #  :         55 :         TAILQ_INIT(&process->finish_actions);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    3096                 :            : 
    3097   [ +  +  #  # ]:         55 :         if (g_opts.process_max_bandwidth_mb_sec != 0) {
    3098   [ #  #  #  #  :          3 :                 process->qos.enable_qos = true;
                   #  # ]
    3099   [ #  #  #  #  :          3 :                 process->qos.last_tsc = spdk_get_ticks();
                   #  # ]
    3100   [ #  #  #  #  :          4 :                 process->qos.bytes_per_tsc = g_opts.process_max_bandwidth_mb_sec * 1024 * 1024.0 /
          #  #  #  #  #  
                      # ]
    3101                 :          3 :                                              spdk_get_ticks_hz();
    3102   [ #  #  #  #  :          3 :                 process->qos.bytes_max = g_opts.process_max_bandwidth_mb_sec * 1024 * 1024.0 / SPDK_SEC_TO_MSEC;
             #  #  #  # ]
    3103   [ #  #  #  #  :          3 :                 process->qos.bytes_available = 0.0;
                   #  # ]
    3104                 :          0 :         }
    3105                 :            : 
    3106   [ +  +  #  # ]:        935 :         for (i = 0; i < RAID_BDEV_PROCESS_MAX_QD; i++) {
    3107                 :        880 :                 process_req = raid_bdev_process_alloc_request(process);
    3108         [ -  + ]:        880 :                 if (process_req == NULL) {
    3109                 :          0 :                         raid_bdev_process_free(process);
    3110                 :          0 :                         return NULL;
    3111                 :            :                 }
    3112                 :            : 
    3113   [ #  #  #  #  :        880 :                 TAILQ_INSERT_TAIL(&process->requests, process_req, link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    3114                 :          0 :         }
    3115                 :            : 
    3116                 :         55 :         return process;
    3117                 :          0 : }
    3118                 :            : 
    3119                 :            : static int
    3120                 :         55 : raid_bdev_start_rebuild(struct raid_base_bdev_info *target)
    3121                 :            : {
    3122                 :            :         struct raid_bdev_process *process;
    3123                 :            : 
    3124   [ -  +  #  # ]:         55 :         assert(spdk_get_thread() == spdk_thread_get_app_thread());
    3125                 :            : 
    3126   [ #  #  #  # ]:         55 :         process = raid_bdev_process_alloc(target->raid_bdev, RAID_PROCESS_REBUILD, target);
    3127         [ -  + ]:         55 :         if (process == NULL) {
    3128                 :          0 :                 return -ENOMEM;
    3129                 :            :         }
    3130                 :            : 
    3131                 :         55 :         raid_bdev_process_start(process);
    3132                 :            : 
    3133                 :         55 :         return 0;
    3134                 :          0 : }
    3135                 :            : 
    3136                 :            : static void raid_bdev_configure_base_bdev_cont(struct raid_base_bdev_info *base_info);
    3137                 :            : 
    3138                 :            : static void
    3139                 :         49 : _raid_bdev_configure_base_bdev_cont(struct spdk_io_channel_iter *i, int status)
    3140                 :            : {
    3141                 :         49 :         struct raid_base_bdev_info *base_info = spdk_io_channel_iter_get_ctx(i);
    3142                 :            : 
    3143                 :         49 :         raid_bdev_configure_base_bdev_cont(base_info);
    3144                 :         49 : }
    3145                 :            : 
    3146                 :            : static void
    3147                 :          8 : raid_bdev_ch_sync(struct spdk_io_channel_iter *i)
    3148                 :            : {
    3149                 :          8 :         spdk_for_each_channel_continue(i, 0);
    3150                 :          8 : }
    3151                 :            : 
    3152                 :            : static void
    3153                 :       2411 : raid_bdev_configure_base_bdev_cont(struct raid_base_bdev_info *base_info)
    3154                 :            : {
    3155   [ #  #  #  # ]:       2411 :         struct raid_bdev *raid_bdev = base_info->raid_bdev;
    3156                 :            :         raid_base_bdev_cb configure_cb;
    3157                 :            :         int rc;
    3158                 :            : 
    3159   [ +  +  #  #  :       2411 :         if (raid_bdev->num_base_bdevs_discovered == raid_bdev->num_base_bdevs_operational &&
          #  #  #  #  #  
                #  #  # ]
    3160   [ -  +  +  +  :         98 :             base_info->is_process_target == false) {
                   #  # ]
    3161                 :            :                 /* TODO: defer if rebuild in progress on another base bdev */
    3162   [ -  +  #  #  :         49 :                 assert(raid_bdev->process == NULL);
             #  #  #  # ]
    3163   [ -  +  #  #  :         49 :                 assert(raid_bdev->state == RAID_BDEV_STATE_ONLINE);
             #  #  #  # ]
    3164   [ #  #  #  # ]:         49 :                 base_info->is_process_target = true;
    3165                 :            :                 /* To assure is_process_target is set before is_configured when checked in raid_bdev_create_cb() */
    3166                 :         49 :                 spdk_for_each_channel(raid_bdev, raid_bdev_ch_sync, base_info, _raid_bdev_configure_base_bdev_cont);
    3167                 :         49 :                 return;
    3168                 :            :         }
    3169                 :            : 
    3170   [ #  #  #  # ]:       2362 :         base_info->is_configured = true;
    3171                 :            : 
    3172         [ #  # ]:       2362 :         raid_bdev->num_base_bdevs_discovered++;
    3173   [ -  +  #  #  :       2362 :         assert(raid_bdev->num_base_bdevs_discovered <= raid_bdev->num_base_bdevs);
          #  #  #  #  #  
                #  #  # ]
    3174   [ -  +  #  #  :       2362 :         assert(raid_bdev->num_base_bdevs_operational <= raid_bdev->num_base_bdevs);
          #  #  #  #  #  
                #  #  # ]
    3175   [ -  +  #  #  :       2362 :         assert(raid_bdev->num_base_bdevs_operational >= raid_bdev->min_base_bdevs_operational);
          #  #  #  #  #  
                #  #  # ]
    3176                 :            : 
    3177   [ #  #  #  # ]:       2362 :         configure_cb = base_info->configure_cb;
    3178   [ #  #  #  # ]:       2362 :         base_info->configure_cb = NULL;
    3179                 :            :         /*
    3180                 :            :          * Configure the raid bdev when the number of discovered base bdevs reaches the number
    3181                 :            :          * of base bdevs we know to be operational members of the array. Usually this is equal
    3182                 :            :          * to the total number of base bdevs (num_base_bdevs) but can be less - when the array is
    3183                 :            :          * degraded.
    3184                 :            :          */
    3185   [ +  +  #  #  :       2362 :         if (raid_bdev->num_base_bdevs_discovered == raid_bdev->num_base_bdevs_operational) {
          #  #  #  #  #  
                      # ]
    3186   [ #  #  #  # ]:        329 :                 rc = raid_bdev_configure(raid_bdev, configure_cb, base_info->configure_cb_ctx);
    3187         [ -  + ]:        329 :                 if (rc != 0) {
    3188         [ #  # ]:          0 :                         SPDK_ERRLOG("Failed to configure raid bdev: %s\n", spdk_strerror(-rc));
    3189                 :          0 :                 } else {
    3190                 :        329 :                         configure_cb = NULL;
    3191                 :            :                 }
    3192   [ -  +  +  +  :       2033 :         } else if (base_info->is_process_target) {
             #  #  #  # ]
    3193         [ #  # ]:         49 :                 raid_bdev->num_base_bdevs_operational++;
    3194                 :         49 :                 rc = raid_bdev_start_rebuild(base_info);
    3195         [ -  + ]:         49 :                 if (rc != 0) {
    3196         [ #  # ]:          0 :                         SPDK_ERRLOG("Failed to start rebuild: %s\n", spdk_strerror(-rc));
    3197                 :          0 :                         _raid_bdev_remove_base_bdev(base_info, NULL, NULL);
    3198                 :          0 :                 }
    3199                 :          0 :         } else {
    3200                 :       1984 :                 rc = 0;
    3201                 :            :         }
    3202                 :            : 
    3203         [ +  + ]:       2362 :         if (configure_cb != NULL) {
    3204   [ #  #  #  #  :       1968 :                 configure_cb(base_info->configure_cb_ctx, rc);
             #  #  #  # ]
    3205                 :          0 :         }
    3206                 :          0 : }
    3207                 :            : 
    3208                 :            : static void raid_bdev_examine_sb(const struct raid_bdev_superblock *sb, struct spdk_bdev *bdev,
    3209                 :            :                                  raid_base_bdev_cb cb_fn, void *cb_ctx);
    3210                 :            : 
    3211                 :            : static void
    3212                 :       2185 : raid_bdev_configure_base_bdev_check_sb_cb(const struct raid_bdev_superblock *sb, int status,
    3213                 :            :                 void *ctx)
    3214                 :            : {
    3215                 :       2185 :         struct raid_base_bdev_info *base_info = ctx;
    3216   [ #  #  #  # ]:       2185 :         raid_base_bdev_cb configure_cb = base_info->configure_cb;
    3217                 :            : 
    3218      [ +  +  - ]:       2185 :         switch (status) {
    3219                 :         58 :         case 0:
    3220                 :            :                 /* valid superblock found */
    3221   [ #  #  #  # ]:         58 :                 base_info->configure_cb = NULL;
    3222   [ +  +  #  #  :         58 :                 if (spdk_uuid_compare(&base_info->raid_bdev->bdev.uuid, &sb->uuid) == 0) {
          #  #  #  #  #  
                #  #  # ]
    3223   [ #  #  #  # ]:         18 :                         struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(base_info->desc);
    3224                 :            : 
    3225                 :         18 :                         raid_bdev_free_base_bdev_resource(base_info);
    3226   [ #  #  #  # ]:         18 :                         raid_bdev_examine_sb(sb, bdev, configure_cb, base_info->configure_cb_ctx);
    3227                 :         18 :                         return;
    3228                 :            :                 }
    3229   [ #  #  #  # ]:         40 :                 SPDK_ERRLOG("Superblock of a different raid bdev found on bdev %s\n", base_info->name);
    3230                 :         40 :                 status = -EEXIST;
    3231                 :         40 :                 raid_bdev_free_base_bdev_resource(base_info);
    3232                 :         40 :                 break;
    3233                 :       2127 :         case -EINVAL:
    3234                 :            :                 /* no valid superblock */
    3235                 :       2127 :                 raid_bdev_configure_base_bdev_cont(base_info);
    3236                 :       2127 :                 return;
    3237                 :          0 :         default:
    3238   [ #  #  #  #  :          0 :                 SPDK_ERRLOG("Failed to examine bdev %s: %s\n",
                   #  # ]
    3239                 :            :                             base_info->name, spdk_strerror(-status));
    3240                 :          0 :                 break;
    3241                 :            :         }
    3242                 :            : 
    3243         [ +  - ]:         40 :         if (configure_cb != NULL) {
    3244   [ #  #  #  # ]:         40 :                 base_info->configure_cb = NULL;
    3245   [ #  #  #  #  :         40 :                 configure_cb(base_info->configure_cb_ctx, status);
             #  #  #  # ]
    3246                 :          0 :         }
    3247                 :          0 : }
    3248                 :            : 
    3249                 :            : static int
    3250                 :       2642 : raid_bdev_configure_base_bdev(struct raid_base_bdev_info *base_info, bool existing,
    3251                 :            :                               raid_base_bdev_cb cb_fn, void *cb_ctx)
    3252                 :            : {
    3253   [ #  #  #  # ]:       2642 :         struct raid_bdev *raid_bdev = base_info->raid_bdev;
    3254                 :       2538 :         struct spdk_bdev_desc *desc;
    3255                 :            :         struct spdk_bdev *bdev;
    3256                 :            :         const struct spdk_uuid *bdev_uuid;
    3257                 :            :         int rc;
    3258                 :            : 
    3259   [ -  +  #  # ]:       2642 :         assert(spdk_get_thread() == spdk_thread_get_app_thread());
    3260   [ -  +  #  #  :       2642 :         assert(base_info->desc == NULL);
             #  #  #  # ]
    3261                 :            : 
    3262                 :            :         /*
    3263                 :            :          * Base bdev can be added by name or uuid. Here we assure both properties are set and valid
    3264                 :            :          * before claiming the bdev.
    3265                 :            :          */
    3266                 :            : 
    3267   [ +  +  #  # ]:       2642 :         if (!spdk_uuid_is_null(&base_info->uuid)) {
    3268                 :        177 :                 char uuid_str[SPDK_UUID_STRING_LEN];
    3269                 :            :                 const char *bdev_name;
    3270                 :            : 
    3271         [ #  # ]:        177 :                 spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &base_info->uuid);
    3272                 :            : 
    3273                 :            :                 /* UUID of a bdev is registered as its alias */
    3274                 :        177 :                 bdev = spdk_bdev_get_by_name(uuid_str);
    3275         [ -  + ]:        177 :                 if (bdev == NULL) {
    3276                 :          0 :                         return -ENODEV;
    3277                 :            :                 }
    3278                 :            : 
    3279                 :        177 :                 bdev_name = spdk_bdev_get_name(bdev);
    3280                 :            : 
    3281   [ +  +  #  #  :        177 :                 if (base_info->name == NULL) {
                   #  # ]
    3282   [ -  +  #  #  :        145 :                         assert(existing == true);
                   #  # ]
    3283   [ -  +  #  #  :        145 :                         base_info->name = strdup(bdev_name);
                   #  # ]
    3284   [ -  +  #  #  :        145 :                         if (base_info->name == NULL) {
                   #  # ]
    3285                 :          0 :                                 return -ENOMEM;
    3286                 :            :                         }
    3287   [ -  +  -  +  :         32 :                 } else if (strcmp(base_info->name, bdev_name) != 0) {
          -  +  #  #  #  
                      # ]
    3288   [ #  #  #  # ]:          0 :                         SPDK_ERRLOG("Name mismatch for base bdev '%s' - expected '%s'\n",
    3289                 :            :                                     bdev_name, base_info->name);
    3290                 :          0 :                         return -EINVAL;
    3291                 :            :                 }
    3292                 :          0 :         }
    3293                 :            : 
    3294   [ -  +  #  #  :       2642 :         assert(base_info->name != NULL);
             #  #  #  # ]
    3295                 :            : 
    3296   [ #  #  #  # ]:       2642 :         rc = spdk_bdev_open_ext(base_info->name, true, raid_bdev_event_base_bdev, NULL, &desc);
    3297         [ +  + ]:       2642 :         if (rc != 0) {
    3298         [ -  + ]:        216 :                 if (rc != -ENODEV) {
    3299   [ #  #  #  # ]:          0 :                         SPDK_ERRLOG("Unable to create desc on bdev '%s'\n", base_info->name);
    3300                 :          0 :                 }
    3301                 :        216 :                 return rc;
    3302                 :            :         }
    3303                 :            : 
    3304                 :       2426 :         bdev = spdk_bdev_desc_get_bdev(desc);
    3305                 :       2426 :         bdev_uuid = spdk_bdev_get_uuid(bdev);
    3306                 :            : 
    3307   [ +  +  #  # ]:       2426 :         if (spdk_uuid_is_null(&base_info->uuid)) {
    3308         [ #  # ]:       2249 :                 spdk_uuid_copy(&base_info->uuid, bdev_uuid);
    3309   [ -  +  #  # ]:        177 :         } else if (spdk_uuid_compare(&base_info->uuid, bdev_uuid) != 0) {
    3310   [ #  #  #  # ]:          0 :                 SPDK_ERRLOG("UUID mismatch for base bdev '%s'\n", base_info->name);
    3311                 :          0 :                 spdk_bdev_close(desc);
    3312                 :          0 :                 return -EINVAL;
    3313                 :            :         }
    3314                 :            : 
    3315                 :       2426 :         rc = spdk_bdev_module_claim_bdev(bdev, NULL, &g_raid_if);
    3316         [ +  + ]:       2426 :         if (rc != 0) {
    3317                 :          6 :                 SPDK_ERRLOG("Unable to claim this bdev as it is already claimed\n");
    3318                 :          6 :                 spdk_bdev_close(desc);
    3319                 :          6 :                 return rc;
    3320                 :            :         }
    3321                 :            : 
    3322   [ -  +  +  +  :       2420 :         SPDK_DEBUGLOG(bdev_raid, "bdev %s is claimed\n", bdev->name);
          #  #  #  #  #  
                      # ]
    3323                 :            : 
    3324   [ #  #  #  # ]:       2420 :         base_info->app_thread_ch = spdk_bdev_get_io_channel(desc);
    3325   [ -  +  #  #  :       2420 :         if (base_info->app_thread_ch == NULL) {
                   #  # ]
    3326                 :          0 :                 SPDK_ERRLOG("Failed to get io channel\n");
    3327                 :          0 :                 spdk_bdev_module_release_bdev(bdev);
    3328                 :          0 :                 spdk_bdev_close(desc);
    3329                 :          0 :                 return -ENOMEM;
    3330                 :            :         }
    3331                 :            : 
    3332   [ #  #  #  # ]:       2420 :         base_info->desc = desc;
    3333   [ #  #  #  #  :       2420 :         base_info->blockcnt = bdev->blockcnt;
             #  #  #  # ]
    3334                 :            : 
    3335   [ +  +  +  +  :       2420 :         if (raid_bdev->superblock_enabled) {
             #  #  #  # ]
    3336                 :            :                 uint64_t data_offset;
    3337                 :            : 
    3338   [ +  +  #  #  :        494 :                 if (base_info->data_offset == 0) {
                   #  # ]
    3339   [ -  +  -  +  :        391 :                         assert((RAID_BDEV_MIN_DATA_OFFSET_SIZE % spdk_bdev_get_data_block_size(bdev)) == 0);
                   #  # ]
    3340         [ -  + ]:        391 :                         data_offset = RAID_BDEV_MIN_DATA_OFFSET_SIZE / spdk_bdev_get_data_block_size(bdev);
    3341                 :          0 :                 } else {
    3342   [ #  #  #  # ]:        103 :                         data_offset = base_info->data_offset;
    3343                 :            :                 }
    3344                 :            : 
    3345   [ +  +  #  #  :        494 :                 if (bdev->optimal_io_boundary != 0) {
                   #  # ]
    3346                 :         22 :                         data_offset = spdk_divide_round_up(data_offset,
    3347   [ #  #  #  #  :         11 :                                                            bdev->optimal_io_boundary) * bdev->optimal_io_boundary;
          #  #  #  #  #  
                      # ]
    3348   [ +  +  -  +  :         11 :                         if (base_info->data_offset != 0 && base_info->data_offset != data_offset) {
          #  #  #  #  #  
                #  #  # ]
    3349   [ #  #  #  #  :          0 :                                 SPDK_WARNLOG("Data offset %lu on bdev '%s' is different than optimal value %lu\n",
             #  #  #  # ]
    3350                 :            :                                              base_info->data_offset, base_info->name, data_offset);
    3351   [ #  #  #  # ]:          0 :                                 data_offset = base_info->data_offset;
    3352                 :          0 :                         }
    3353                 :          0 :                 }
    3354                 :            : 
    3355   [ #  #  #  # ]:        494 :                 base_info->data_offset = data_offset;
    3356                 :          0 :         }
    3357                 :            : 
    3358   [ -  +  #  #  :       2420 :         if (base_info->data_offset >= bdev->blockcnt) {
          #  #  #  #  #  
                      # ]
    3359   [ #  #  #  #  :          0 :                 SPDK_ERRLOG("Data offset %lu exceeds base bdev capacity %lu on bdev '%s'\n",
          #  #  #  #  #  
                #  #  # ]
    3360                 :            :                             base_info->data_offset, bdev->blockcnt, base_info->name);
    3361                 :          0 :                 rc = -EINVAL;
    3362                 :          0 :                 goto out;
    3363                 :            :         }
    3364                 :            : 
    3365   [ +  +  #  #  :       2420 :         if (base_info->data_size == 0) {
                   #  # ]
    3366   [ #  #  #  #  :       2194 :                 base_info->data_size = bdev->blockcnt - base_info->data_offset;
          #  #  #  #  #  
                #  #  # ]
    3367   [ -  +  #  #  :        226 :         } else if (base_info->data_offset + base_info->data_size > bdev->blockcnt) {
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    3368   [ #  #  #  #  :          0 :                 SPDK_ERRLOG("Data offset and size exceeds base bdev capacity %lu on bdev '%s'\n",
             #  #  #  # ]
    3369                 :            :                             bdev->blockcnt, base_info->name);
    3370                 :          0 :                 rc = -EINVAL;
    3371                 :          0 :                 goto out;
    3372                 :            :         }
    3373                 :            : 
    3374   [ +  +  +  +  :       2420 :         if (!raid_bdev->module->dif_supported && spdk_bdev_get_dif_type(bdev) != SPDK_DIF_DISABLE) {
          -  +  #  #  #  
             #  #  #  #  
                      # ]
    3375   [ #  #  #  # ]:          0 :                 SPDK_ERRLOG("Base bdev '%s' has DIF or DIX enabled - unsupported RAID configuration\n",
    3376                 :            :                             bdev->name);
    3377                 :          0 :                 rc = -EINVAL;
    3378                 :          0 :                 goto out;
    3379                 :            :         }
    3380                 :            : 
    3381                 :            :         /*
    3382                 :            :          * Set the raid bdev properties if this is the first base bdev configured,
    3383                 :            :          * otherwise - verify. Assumption is that all the base bdevs for any raid bdev should
    3384                 :            :          * have the same blocklen and metadata format.
    3385                 :            :          */
    3386   [ +  +  #  #  :       2420 :         if (raid_bdev->bdev.blocklen == 0) {
             #  #  #  # ]
    3387   [ #  #  #  #  :        382 :                 raid_bdev->bdev.blocklen = bdev->blocklen;
          #  #  #  #  #  
                      # ]
    3388   [ #  #  #  #  :        382 :                 raid_bdev->bdev.md_len = spdk_bdev_get_md_size(bdev);
                   #  # ]
    3389   [ #  #  #  #  :        382 :                 raid_bdev->bdev.md_interleave = spdk_bdev_is_md_interleaved(bdev);
                   #  # ]
    3390   [ #  #  #  #  :        382 :                 raid_bdev->bdev.dif_type = spdk_bdev_get_dif_type(bdev);
                   #  # ]
    3391   [ #  #  #  #  :        382 :                 raid_bdev->bdev.dif_check_flags = bdev->dif_check_flags;
          #  #  #  #  #  
                      # ]
    3392   [ #  #  #  #  :        382 :                 raid_bdev->bdev.dif_is_head_of_md = spdk_bdev_is_dif_head_of_md(bdev);
                   #  # ]
    3393   [ #  #  #  #  :        382 :                 raid_bdev->bdev.dif_pi_format = bdev->dif_pi_format;
          #  #  #  #  #  
                      # ]
    3394                 :          0 :         } else {
    3395   [ -  +  #  #  :       2038 :                 if (raid_bdev->bdev.blocklen != bdev->blocklen) {
          #  #  #  #  #  
                #  #  # ]
    3396   [ #  #  #  #  :          0 :                         SPDK_ERRLOG("Raid bdev '%s' blocklen %u differs from base bdev '%s' blocklen %u\n",
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
    3397                 :            :                                     raid_bdev->bdev.name, raid_bdev->bdev.blocklen, bdev->name, bdev->blocklen);
    3398                 :          0 :                         rc = -EINVAL;
    3399                 :          0 :                         goto out;
    3400                 :            :                 }
    3401                 :            : 
    3402   [ +  -  +  -  :       4076 :                 if (raid_bdev->bdev.md_len != spdk_bdev_get_md_size(bdev) ||
          #  #  #  #  #  
                      # ]
    3403   [ +  +  +  -  :       4076 :                     raid_bdev->bdev.md_interleave != spdk_bdev_is_md_interleaved(bdev) ||
          #  #  #  #  #  
                      # ]
    3404   [ #  #  #  #  :       2038 :                     raid_bdev->bdev.dif_type != spdk_bdev_get_dif_type(bdev) ||
             #  #  #  # ]
    3405   [ +  -  +  -  :       4076 :                     raid_bdev->bdev.dif_check_flags != bdev->dif_check_flags ||
          #  #  #  #  #  
                #  #  # ]
    3406   [ -  +  #  #  :       2038 :                     raid_bdev->bdev.dif_is_head_of_md != spdk_bdev_is_dif_head_of_md(bdev) ||
          #  #  #  #  #  
                      # ]
    3407   [ -  +  #  #  :       2038 :                     raid_bdev->bdev.dif_pi_format != bdev->dif_pi_format) {
          #  #  #  #  #  
                      # ]
    3408   [ #  #  #  #  :          0 :                         SPDK_ERRLOG("Raid bdev '%s' has different metadata format than base bdev '%s'\n",
          #  #  #  #  #  
                      # ]
    3409                 :            :                                     raid_bdev->bdev.name, bdev->name);
    3410                 :          0 :                         rc = -EINVAL;
    3411                 :          0 :                         goto out;
    3412                 :            :                 }
    3413                 :            :         }
    3414                 :            : 
    3415   [ -  +  #  #  :       2420 :         assert(base_info->configure_cb == NULL);
             #  #  #  # ]
    3416   [ #  #  #  # ]:       2420 :         base_info->configure_cb = cb_fn;
    3417   [ #  #  #  # ]:       2420 :         base_info->configure_cb_ctx = cb_ctx;
    3418                 :            : 
    3419   [ +  +  #  # ]:       2420 :         if (existing) {
    3420                 :        235 :                 raid_bdev_configure_base_bdev_cont(base_info);
    3421                 :          0 :         } else {
    3422                 :            :                 /* check for existing superblock when using a new bdev */
    3423   [ #  #  #  # ]:       2185 :                 rc = raid_bdev_load_base_bdev_superblock(desc, base_info->app_thread_ch,
    3424                 :          0 :                                 raid_bdev_configure_base_bdev_check_sb_cb, base_info);
    3425         [ +  - ]:       2185 :                 if (rc) {
    3426   [ #  #  #  #  :          0 :                         SPDK_ERRLOG("Failed to read bdev %s superblock: %s\n",
                   #  # ]
    3427                 :            :                                     bdev->name, spdk_strerror(-rc));
    3428                 :          0 :                 }
    3429                 :            :         }
    3430                 :       2420 : out:
    3431         [ -  + ]:       2420 :         if (rc != 0) {
    3432   [ #  #  #  # ]:          0 :                 base_info->configure_cb = NULL;
    3433                 :          0 :                 raid_bdev_free_base_bdev_resource(base_info);
    3434                 :          0 :         }
    3435                 :       2420 :         return rc;
    3436                 :          0 : }
    3437                 :            : 
    3438                 :            : int
    3439                 :       2407 : raid_bdev_add_base_bdev(struct raid_bdev *raid_bdev, const char *name,
    3440                 :            :                         raid_base_bdev_cb cb_fn, void *cb_ctx)
    3441                 :            : {
    3442                 :       2407 :         struct raid_base_bdev_info *base_info = NULL, *iter;
    3443                 :            :         int rc;
    3444                 :            : 
    3445   [ -  +  #  # ]:       2407 :         assert(name != NULL);
    3446   [ -  +  #  # ]:       2407 :         assert(spdk_get_thread() == spdk_thread_get_app_thread());
    3447                 :            : 
    3448   [ -  +  #  #  :       2407 :         if (raid_bdev->process != NULL) {
                   #  # ]
    3449   [ #  #  #  #  :          0 :                 SPDK_ERRLOG("raid bdev '%s' is in process\n",
                   #  # ]
    3450                 :            :                             raid_bdev->bdev.name);
    3451                 :          0 :                 return -EPERM;
    3452                 :            :         }
    3453                 :            : 
    3454   [ +  +  #  #  :       2407 :         if (raid_bdev->state == RAID_BDEV_STATE_CONFIGURING) {
                   #  # ]
    3455                 :       2358 :                 struct spdk_bdev *bdev = spdk_bdev_get_by_name(name);
    3456                 :            : 
    3457         [ +  + ]:       2358 :                 if (bdev != NULL) {
    3458   [ +  +  #  #  :      52833 :                         RAID_FOR_EACH_BASE_BDEV(raid_bdev, iter) {
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
    3459   [ +  +  +  +  :      77261 :                                 if (iter->name == NULL &&
             #  #  #  # ]
    3460   [ #  #  #  # ]:      26538 :                                     spdk_uuid_compare(&bdev->uuid, &iter->uuid) == 0) {
    3461                 :         32 :                                         base_info = iter;
    3462                 :         32 :                                         break;
    3463                 :            :                                 }
    3464                 :          0 :                         }
    3465                 :          0 :                 }
    3466                 :          0 :         }
    3467                 :            : 
    3468   [ +  +  -  +  :       2407 :         if (base_info == NULL || raid_bdev->state == RAID_BDEV_STATE_ONLINE) {
             #  #  #  # ]
    3469   [ +  -  #  #  :      26882 :                 RAID_FOR_EACH_BASE_BDEV(raid_bdev, iter) {
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
    3470   [ +  +  +  -  :      26882 :                         if (iter->name == NULL && spdk_uuid_is_null(&iter->uuid)) {
          #  #  #  #  #  
                      # ]
    3471                 :       2375 :                                 base_info = iter;
    3472                 :       2375 :                                 break;
    3473                 :            :                         }
    3474                 :          0 :                 }
    3475                 :          0 :         }
    3476                 :            : 
    3477         [ -  + ]:       2407 :         if (base_info == NULL) {
    3478   [ #  #  #  #  :          0 :                 SPDK_ERRLOG("no empty slot found in raid bdev '%s' for new base bdev '%s'\n",
                   #  # ]
    3479                 :            :                             raid_bdev->bdev.name, name);
    3480                 :          0 :                 return -EINVAL;
    3481                 :            :         }
    3482                 :            : 
    3483   [ -  +  -  +  :       2407 :         assert(base_info->is_configured == false);
          #  #  #  #  #  
                      # ]
    3484                 :            : 
    3485   [ +  +  #  #  :       2407 :         if (raid_bdev->state == RAID_BDEV_STATE_ONLINE) {
                   #  # ]
    3486   [ -  +  #  #  :         49 :                 assert(base_info->data_size != 0);
             #  #  #  # ]
    3487   [ -  +  #  #  :         49 :                 assert(base_info->desc == NULL);
             #  #  #  # ]
    3488                 :          0 :         }
    3489                 :            : 
    3490   [ -  +  #  #  :       2407 :         base_info->name = strdup(name);
                   #  # ]
    3491   [ -  +  #  #  :       2407 :         if (base_info->name == NULL) {
                   #  # ]
    3492                 :          0 :                 return -ENOMEM;
    3493                 :            :         }
    3494                 :            : 
    3495                 :       2407 :         rc = raid_bdev_configure_base_bdev(base_info, false, cb_fn, cb_ctx);
    3496   [ +  +  +  +  :       2407 :         if (rc != 0 && (rc != -ENODEV || raid_bdev->state != RAID_BDEV_STATE_CONFIGURING)) {
          -  +  #  #  #  
                      # ]
    3497         [ #  # ]:          6 :                 SPDK_ERRLOG("base bdev '%s' configure failed: %s\n", name, spdk_strerror(-rc));
    3498   [ #  #  #  # ]:          6 :                 free(base_info->name);
    3499   [ #  #  #  # ]:          6 :                 base_info->name = NULL;
    3500                 :          0 :         }
    3501                 :            : 
    3502                 :       2407 :         return rc;
    3503                 :          0 : }
    3504                 :            : 
    3505                 :            : static int
    3506                 :         49 : raid_bdev_create_from_sb(const struct raid_bdev_superblock *sb, struct raid_bdev **raid_bdev_out)
    3507                 :            : {
    3508                 :         49 :         struct raid_bdev *raid_bdev;
    3509                 :            :         uint8_t i;
    3510                 :            :         int rc;
    3511                 :            : 
    3512   [ #  #  #  #  :         98 :         rc = _raid_bdev_create(sb->name, (sb->strip_size * sb->block_size) / 1024, sb->num_base_bdevs,
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    3513   [ #  #  #  #  :         49 :                                sb->level, true, &sb->uuid, &raid_bdev);
                   #  # ]
    3514         [ -  + ]:         49 :         if (rc != 0) {
    3515                 :          0 :                 return rc;
    3516                 :            :         }
    3517                 :            : 
    3518   [ #  #  #  # ]:         49 :         rc = raid_bdev_alloc_superblock(raid_bdev, sb->block_size);
    3519         [ -  + ]:         49 :         if (rc != 0) {
    3520                 :          0 :                 raid_bdev_free(raid_bdev);
    3521                 :          0 :                 return rc;
    3522                 :            :         }
    3523                 :            : 
    3524   [ -  +  #  #  :         49 :         assert(sb->length <= RAID_BDEV_SB_MAX_LENGTH);
             #  #  #  # ]
    3525   [ -  +  -  +  :         49 :         memcpy(raid_bdev->sb, sb, sb->length);
          #  #  #  #  #  
                #  #  # ]
    3526                 :            : 
    3527   [ +  +  #  #  :        184 :         for (i = 0; i < sb->base_bdevs_size; i++) {
                   #  # ]
    3528   [ #  #  #  # ]:        135 :                 const struct raid_bdev_sb_base_bdev *sb_base_bdev = &sb->base_bdevs[i];
    3529   [ #  #  #  #  :        135 :                 struct raid_base_bdev_info *base_info = &raid_bdev->base_bdev_info[sb_base_bdev->slot];
          #  #  #  #  #  
                      # ]
    3530                 :            : 
    3531   [ +  +  #  #  :        135 :                 if (sb_base_bdev->state == RAID_SB_BASE_BDEV_CONFIGURED) {
                   #  # ]
    3532   [ #  #  #  # ]:        117 :                         spdk_uuid_copy(&base_info->uuid, &sb_base_bdev->uuid);
    3533         [ #  # ]:        117 :                         raid_bdev->num_base_bdevs_operational++;
    3534                 :          0 :                 }
    3535                 :            : 
    3536   [ #  #  #  #  :        135 :                 base_info->data_offset = sb_base_bdev->data_offset;
             #  #  #  # ]
    3537   [ #  #  #  #  :        135 :                 base_info->data_size = sb_base_bdev->data_size;
             #  #  #  # ]
    3538                 :          0 :         }
    3539                 :            : 
    3540         [ #  # ]:         49 :         *raid_bdev_out = raid_bdev;
    3541                 :         49 :         return 0;
    3542                 :          0 : }
    3543                 :            : 
    3544                 :            : static void
    3545                 :       5379 : raid_bdev_examine_no_sb(struct spdk_bdev *bdev)
    3546                 :            : {
    3547                 :            :         struct raid_bdev *raid_bdev;
    3548                 :            :         struct raid_base_bdev_info *base_info;
    3549                 :            : 
    3550   [ +  +  #  #  :       6294 :         TAILQ_FOREACH(raid_bdev, &g_raid_bdev_list, global_link) {
             #  #  #  # ]
    3551   [ +  +  -  +  :        915 :                 if (raid_bdev->state != RAID_BDEV_STATE_CONFIGURING || raid_bdev->sb != NULL) {
          #  #  #  #  #  
                #  #  # ]
    3552                 :        809 :                         continue;
    3553                 :            :                 }
    3554   [ +  -  #  #  :        187 :                 RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) {
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
    3555   [ +  +  #  #  :        187 :                         if (base_info->desc == NULL &&
             #  #  #  # ]
    3556   [ +  +  -  +  :        122 :                             ((base_info->name != NULL && strcmp(bdev->name, base_info->name) == 0) ||
          -  +  -  +  +  
          -  #  #  #  #  
             #  #  #  # ]
    3557   [ #  #  #  # ]:         16 :                              spdk_uuid_compare(&base_info->uuid, &bdev->uuid) == 0)) {
    3558                 :        106 :                                 raid_bdev_configure_base_bdev(base_info, true, NULL, NULL);
    3559                 :        106 :                                 break;
    3560                 :            :                         }
    3561                 :          0 :                 }
    3562                 :          0 :         }
    3563                 :       5379 : }
    3564                 :            : 
    3565                 :            : struct raid_bdev_examine_others_ctx {
    3566                 :            :         struct spdk_uuid raid_bdev_uuid;
    3567                 :            :         uint8_t current_base_bdev_idx;
    3568                 :            :         raid_base_bdev_cb cb_fn;
    3569                 :            :         void *cb_ctx;
    3570                 :            : };
    3571                 :            : 
    3572                 :            : static void
    3573                 :         49 : raid_bdev_examine_others_done(void *_ctx, int status)
    3574                 :            : {
    3575                 :         49 :         struct raid_bdev_examine_others_ctx *ctx = _ctx;
    3576                 :            : 
    3577   [ +  -  #  #  :         49 :         if (ctx->cb_fn != NULL) {
                   #  # ]
    3578   [ #  #  #  #  :         49 :                 ctx->cb_fn(ctx->cb_ctx, status);
          #  #  #  #  #  
                #  #  # ]
    3579                 :          0 :         }
    3580                 :         49 :         free(ctx);
    3581                 :         49 : }
    3582                 :            : 
    3583                 :            : typedef void (*raid_bdev_examine_load_sb_cb)(struct spdk_bdev *bdev,
    3584                 :            :                 const struct raid_bdev_superblock *sb, int status, void *ctx);
    3585                 :            : static int raid_bdev_examine_load_sb(const char *bdev_name, raid_bdev_examine_load_sb_cb cb,
    3586                 :            :                                      void *cb_ctx);
    3587                 :            : static void raid_bdev_examine_sb(const struct raid_bdev_superblock *sb, struct spdk_bdev *bdev,
    3588                 :            :                                  raid_base_bdev_cb cb_fn, void *cb_ctx);
    3589                 :            : static void raid_bdev_examine_others(void *_ctx, int status);
    3590                 :            : 
    3591                 :            : static void
    3592                 :         26 : raid_bdev_examine_others_load_cb(struct spdk_bdev *bdev, const struct raid_bdev_superblock *sb,
    3593                 :            :                                  int status, void *_ctx)
    3594                 :            : {
    3595                 :         26 :         struct raid_bdev_examine_others_ctx *ctx = _ctx;
    3596                 :            : 
    3597         [ -  + ]:         26 :         if (status != 0) {
    3598                 :          0 :                 raid_bdev_examine_others_done(ctx, status);
    3599                 :          0 :                 return;
    3600                 :            :         }
    3601                 :            : 
    3602                 :         26 :         raid_bdev_examine_sb(sb, bdev, raid_bdev_examine_others, ctx);
    3603                 :          0 : }
    3604                 :            : 
    3605                 :            : static void
    3606                 :         75 : raid_bdev_examine_others(void *_ctx, int status)
    3607                 :            : {
    3608                 :         75 :         struct raid_bdev_examine_others_ctx *ctx = _ctx;
    3609                 :            :         struct raid_bdev *raid_bdev;
    3610                 :            :         struct raid_base_bdev_info *base_info;
    3611                 :         75 :         char uuid_str[SPDK_UUID_STRING_LEN];
    3612                 :            : 
    3613   [ +  +  -  + ]:         75 :         if (status != 0 && status != -EEXIST) {
    3614                 :          0 :                 goto out;
    3615                 :            :         }
    3616                 :            : 
    3617         [ #  # ]:         75 :         raid_bdev = raid_bdev_find_by_uuid(&ctx->raid_bdev_uuid);
    3618         [ -  + ]:         75 :         if (raid_bdev == NULL) {
    3619                 :          0 :                 status = -ENODEV;
    3620                 :          0 :                 goto out;
    3621                 :            :         }
    3622                 :            : 
    3623   [ #  #  #  #  :         75 :         for (base_info = &raid_bdev->base_bdev_info[ctx->current_base_bdev_idx];
          #  #  #  #  #  
                #  #  # ]
    3624   [ +  +  #  #  :        210 :              base_info < &raid_bdev->base_bdev_info[raid_bdev->num_base_bdevs];
          #  #  #  #  #  
                      # ]
    3625         [ #  # ]:        135 :              base_info++) {
    3626   [ -  +  +  +  :        161 :                 if (base_info->is_configured || spdk_uuid_is_null(&base_info->uuid)) {
          +  +  #  #  #  
                #  #  # ]
    3627                 :         95 :                         continue;
    3628                 :            :                 }
    3629                 :            : 
    3630         [ #  # ]:         66 :                 spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &base_info->uuid);
    3631                 :            : 
    3632         [ +  + ]:         66 :                 if (spdk_bdev_get_by_name(uuid_str) == NULL) {
    3633                 :         40 :                         continue;
    3634                 :            :                 }
    3635                 :            : 
    3636   [ #  #  #  # ]:         26 :                 ctx->current_base_bdev_idx = raid_bdev_base_bdev_slot(base_info);
    3637                 :            : 
    3638                 :         26 :                 status = raid_bdev_examine_load_sb(uuid_str, raid_bdev_examine_others_load_cb, ctx);
    3639         [ -  + ]:         26 :                 if (status != 0) {
    3640                 :          0 :                         continue;
    3641                 :            :                 }
    3642                 :         26 :                 return;
    3643                 :          0 :         }
    3644                 :         49 : out:
    3645                 :         49 :         raid_bdev_examine_others_done(ctx, status);
    3646                 :          0 : }
    3647                 :            : 
    3648                 :            : static void
    3649                 :        149 : raid_bdev_examine_sb(const struct raid_bdev_superblock *sb, struct spdk_bdev *bdev,
    3650                 :            :                      raid_base_bdev_cb cb_fn, void *cb_ctx)
    3651                 :            : {
    3652                 :        149 :         const struct raid_bdev_sb_base_bdev *sb_base_bdev = NULL;
    3653                 :        149 :         struct raid_bdev *raid_bdev;
    3654                 :            :         struct raid_base_bdev_info *iter, *base_info;
    3655                 :            :         uint8_t i;
    3656                 :            :         int rc;
    3657                 :            : 
    3658   [ -  +  #  #  :        149 :         if (sb->block_size != spdk_bdev_get_data_block_size(bdev)) {
                   #  # ]
    3659   [ #  #  #  #  :          0 :                 SPDK_WARNLOG("Bdev %s block size (%u) does not match the value in superblock (%u)\n",
             #  #  #  # ]
    3660                 :            :                              bdev->name, sb->block_size, spdk_bdev_get_data_block_size(bdev));
    3661                 :          0 :                 rc = -EINVAL;
    3662                 :          0 :                 goto out;
    3663                 :            :         }
    3664                 :            : 
    3665   [ -  +  #  # ]:        149 :         if (spdk_uuid_is_null(&sb->uuid)) {
    3666   [ #  #  #  # ]:          0 :                 SPDK_WARNLOG("NULL raid bdev UUID in superblock on bdev %s\n", bdev->name);
    3667                 :          0 :                 rc = -EINVAL;
    3668                 :          0 :                 goto out;
    3669                 :            :         }
    3670                 :            : 
    3671         [ #  # ]:        149 :         raid_bdev = raid_bdev_find_by_uuid(&sb->uuid);
    3672                 :            : 
    3673         [ +  + ]:        149 :         if (raid_bdev) {
    3674   [ +  +  #  #  :        108 :                 if (sb->seq_number > raid_bdev->sb->seq_number) {
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    3675   [ -  +  +  -  :          8 :                         SPDK_DEBUGLOG(bdev_raid,
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
    3676                 :            :                                       "raid superblock seq_number on bdev %s (%lu) greater than existing raid bdev %s (%lu)\n",
    3677                 :            :                                       bdev->name, sb->seq_number, raid_bdev->bdev.name, raid_bdev->sb->seq_number);
    3678                 :            : 
    3679   [ -  +  #  #  :          8 :                         if (raid_bdev->state != RAID_BDEV_STATE_CONFIGURING) {
                   #  # ]
    3680   [ #  #  #  #  :          0 :                                 SPDK_WARNLOG("Newer version of raid bdev %s superblock found on bdev %s but raid bdev is not in configuring state.\n",
          #  #  #  #  #  
                      # ]
    3681                 :            :                                              raid_bdev->bdev.name, bdev->name);
    3682                 :          0 :                                 rc = -EBUSY;
    3683                 :          0 :                                 goto out;
    3684                 :            :                         }
    3685                 :            : 
    3686                 :            :                         /* remove and then recreate the raid bdev using the newer superblock */
    3687                 :          8 :                         raid_bdev_delete(raid_bdev, NULL, NULL);
    3688                 :          8 :                         raid_bdev = NULL;
    3689   [ +  +  #  #  :        100 :                 } else if (sb->seq_number < raid_bdev->sb->seq_number) {
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    3690   [ -  +  +  -  :         38 :                         SPDK_DEBUGLOG(bdev_raid,
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
    3691                 :            :                                       "raid superblock seq_number on bdev %s (%lu) smaller than existing raid bdev %s (%lu)\n",
    3692                 :            :                                       bdev->name, sb->seq_number, raid_bdev->bdev.name, raid_bdev->sb->seq_number);
    3693                 :            :                         /* use the current raid bdev superblock */
    3694   [ #  #  #  # ]:         38 :                         sb = raid_bdev->sb;
    3695                 :          0 :                 }
    3696                 :          0 :         }
    3697                 :            : 
    3698   [ +  +  #  #  :        321 :         for (i = 0; i < sb->base_bdevs_size; i++) {
                   #  # ]
    3699   [ #  #  #  # ]:        303 :                 sb_base_bdev = &sb->base_bdevs[i];
    3700                 :            : 
    3701   [ -  +  #  #  :        303 :                 assert(spdk_uuid_is_null(&sb_base_bdev->uuid) == false);
                   #  # ]
    3702                 :            : 
    3703   [ +  +  #  # ]:        303 :                 if (spdk_uuid_compare(&sb_base_bdev->uuid, spdk_bdev_get_uuid(bdev)) == 0) {
    3704                 :        131 :                         break;
    3705                 :            :                 }
    3706                 :          0 :         }
    3707                 :            : 
    3708   [ +  +  #  #  :        149 :         if (i == sb->base_bdevs_size) {
                   #  # ]
    3709   [ -  +  +  -  :         18 :                 SPDK_DEBUGLOG(bdev_raid, "raid superblock does not contain this bdev's uuid\n");
                   #  # ]
    3710                 :         18 :                 rc = -EINVAL;
    3711                 :         18 :                 goto out;
    3712                 :            :         }
    3713                 :            : 
    3714         [ +  + ]:        131 :         if (!raid_bdev) {
    3715                 :            :                 struct raid_bdev_examine_others_ctx *ctx;
    3716                 :            : 
    3717                 :         49 :                 ctx = calloc(1, sizeof(*ctx));
    3718         [ -  + ]:         49 :                 if (ctx == NULL) {
    3719                 :          0 :                         rc = -ENOMEM;
    3720                 :          0 :                         goto out;
    3721                 :            :                 }
    3722                 :            : 
    3723                 :         49 :                 rc = raid_bdev_create_from_sb(sb, &raid_bdev);
    3724         [ -  + ]:         49 :                 if (rc != 0) {
    3725   [ #  #  #  # ]:          0 :                         SPDK_ERRLOG("Failed to create raid bdev %s: %s\n",
    3726                 :            :                                     sb->name, spdk_strerror(-rc));
    3727                 :          0 :                         free(ctx);
    3728                 :          0 :                         goto out;
    3729                 :            :                 }
    3730                 :            : 
    3731                 :            :                 /* after this base bdev is configured, examine other base bdevs that may be present */
    3732   [ #  #  #  # ]:         49 :                 spdk_uuid_copy(&ctx->raid_bdev_uuid, &sb->uuid);
    3733   [ #  #  #  # ]:         49 :                 ctx->cb_fn = cb_fn;
    3734   [ #  #  #  # ]:         49 :                 ctx->cb_ctx = cb_ctx;
    3735                 :            : 
    3736                 :         49 :                 cb_fn = raid_bdev_examine_others;
    3737                 :         49 :                 cb_ctx = ctx;
    3738                 :          0 :         }
    3739                 :            : 
    3740   [ +  +  #  #  :        131 :         if (raid_bdev->state == RAID_BDEV_STATE_ONLINE) {
                   #  # ]
    3741   [ -  +  #  #  :         18 :                 assert(sb_base_bdev->slot < raid_bdev->num_base_bdevs);
          #  #  #  #  #  
                #  #  # ]
    3742   [ #  #  #  #  :         18 :                 base_info = &raid_bdev->base_bdev_info[sb_base_bdev->slot];
          #  #  #  #  #  
                      # ]
    3743   [ -  +  -  +  :         18 :                 assert(base_info->is_configured == false);
          #  #  #  #  #  
                      # ]
    3744   [ -  +  -  -  :         18 :                 assert(sb_base_bdev->state == RAID_SB_BASE_BDEV_MISSING ||
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    3745                 :            :                        sb_base_bdev->state == RAID_SB_BASE_BDEV_FAILED);
    3746   [ -  +  #  #  :         18 :                 assert(spdk_uuid_is_null(&base_info->uuid));
                   #  # ]
    3747   [ #  #  #  # ]:         18 :                 spdk_uuid_copy(&base_info->uuid, &sb_base_bdev->uuid);
    3748   [ #  #  #  #  :         18 :                 SPDK_NOTICELOG("Re-adding bdev %s to raid bdev %s.\n", bdev->name, raid_bdev->bdev.name);
          #  #  #  #  #  
                      # ]
    3749                 :         18 :                 rc = raid_bdev_configure_base_bdev(base_info, true, cb_fn, cb_ctx);
    3750         [ -  + ]:         18 :                 if (rc != 0) {
    3751   [ #  #  #  #  :          0 :                         SPDK_ERRLOG("Failed to configure bdev %s as base bdev of raid %s: %s\n",
          #  #  #  #  #  
                #  #  # ]
    3752                 :            :                                     bdev->name, raid_bdev->bdev.name, spdk_strerror(-rc));
    3753                 :          0 :                 }
    3754                 :         18 :                 goto out;
    3755                 :            :         }
    3756                 :            : 
    3757   [ -  +  #  #  :        113 :         if (sb_base_bdev->state != RAID_SB_BASE_BDEV_CONFIGURED) {
                   #  # ]
    3758   [ #  #  #  #  :          0 :                 SPDK_NOTICELOG("Bdev %s is not an active member of raid bdev %s. Ignoring.\n",
          #  #  #  #  #  
                      # ]
    3759                 :            :                                bdev->name, raid_bdev->bdev.name);
    3760                 :          0 :                 rc = -EINVAL;
    3761                 :          0 :                 goto out;
    3762                 :            :         }
    3763                 :            : 
    3764                 :        113 :         base_info = NULL;
    3765   [ +  -  #  #  :        235 :         RAID_FOR_EACH_BASE_BDEV(raid_bdev, iter) {
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
    3766   [ +  +  #  # ]:        235 :                 if (spdk_uuid_compare(&iter->uuid, spdk_bdev_get_uuid(bdev)) == 0) {
    3767                 :        113 :                         base_info = iter;
    3768                 :        113 :                         break;
    3769                 :            :                 }
    3770                 :          0 :         }
    3771                 :            : 
    3772         [ -  + ]:        113 :         if (base_info == NULL) {
    3773   [ #  #  #  #  :          0 :                 SPDK_ERRLOG("Bdev %s is not a member of raid bdev %s\n",
          #  #  #  #  #  
                      # ]
    3774                 :            :                             bdev->name, raid_bdev->bdev.name);
    3775                 :          0 :                 rc = -EINVAL;
    3776                 :          0 :                 goto out;
    3777                 :            :         }
    3778                 :            : 
    3779   [ -  +  +  +  :        113 :         if (base_info->is_configured) {
             #  #  #  # ]
    3780                 :          2 :                 rc = -EEXIST;
    3781                 :          2 :                 goto out;
    3782                 :            :         }
    3783                 :            : 
    3784                 :        111 :         rc = raid_bdev_configure_base_bdev(base_info, true, cb_fn, cb_ctx);
    3785         [ +  - ]:        111 :         if (rc != 0) {
    3786   [ #  #  #  #  :          0 :                 SPDK_ERRLOG("Failed to configure bdev %s as base bdev of raid %s: %s\n",
          #  #  #  #  #  
                #  #  # ]
    3787                 :            :                             bdev->name, raid_bdev->bdev.name, spdk_strerror(-rc));
    3788                 :          0 :         }
    3789                 :        149 : out:
    3790   [ +  +  +  - ]:        149 :         if (rc != 0 && cb_fn != 0) {
    3791   [ #  #  #  # ]:         20 :                 cb_fn(cb_ctx, rc);
    3792                 :          0 :         }
    3793                 :        149 : }
    3794                 :            : 
    3795                 :            : struct raid_bdev_examine_ctx {
    3796                 :            :         struct spdk_bdev_desc *desc;
    3797                 :            :         struct spdk_io_channel *ch;
    3798                 :            :         raid_bdev_examine_load_sb_cb cb;
    3799                 :            :         void *cb_ctx;
    3800                 :            : };
    3801                 :            : 
    3802                 :            : static void
    3803                 :       5480 : raid_bdev_examine_ctx_free(struct raid_bdev_examine_ctx *ctx)
    3804                 :            : {
    3805         [ +  + ]:       5480 :         if (!ctx) {
    3806                 :          0 :                 return;
    3807                 :            :         }
    3808                 :            : 
    3809   [ +  -  +  -  :       5480 :         if (ctx->ch) {
                   -  + ]
    3810   [ +  -  +  - ]:       5480 :                 spdk_put_io_channel(ctx->ch);
    3811                 :         47 :         }
    3812                 :            : 
    3813   [ +  -  +  -  :       5480 :         if (ctx->desc) {
                   -  + ]
    3814   [ +  -  +  - ]:       5480 :                 spdk_bdev_close(ctx->desc);
    3815                 :         47 :         }
    3816                 :            : 
    3817                 :       5480 :         free(ctx);
    3818                 :         47 : }
    3819                 :            : 
    3820                 :            : static void
    3821                 :       5480 : raid_bdev_examine_load_sb_done(const struct raid_bdev_superblock *sb, int status, void *_ctx)
    3822                 :            : {
    3823                 :       5480 :         struct raid_bdev_examine_ctx *ctx = _ctx;
    3824   [ +  -  +  - ]:       5480 :         struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(ctx->desc);
    3825                 :            : 
    3826   [ +  -  +  -  :       5480 :         ctx->cb(bdev, sb, status, ctx->cb_ctx);
          -  +  +  -  +  
                -  +  - ]
    3827                 :            : 
    3828                 :       5480 :         raid_bdev_examine_ctx_free(ctx);
    3829                 :       5480 : }
    3830                 :            : 
    3831                 :            : static void
    3832                 :          0 : raid_bdev_examine_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *event_ctx)
    3833                 :            : {
    3834                 :          0 : }
    3835                 :            : 
    3836                 :            : static int
    3837                 :       5480 : raid_bdev_examine_load_sb(const char *bdev_name, raid_bdev_examine_load_sb_cb cb, void *cb_ctx)
    3838                 :            : {
    3839                 :            :         struct raid_bdev_examine_ctx *ctx;
    3840                 :            :         int rc;
    3841                 :            : 
    3842   [ +  +  #  # ]:       5480 :         assert(cb != NULL);
    3843                 :            : 
    3844                 :       5480 :         ctx = calloc(1, sizeof(*ctx));
    3845         [ +  + ]:       5480 :         if (!ctx) {
    3846                 :          0 :                 return -ENOMEM;
    3847                 :            :         }
    3848                 :            : 
    3849         [ +  - ]:       5480 :         rc = spdk_bdev_open_ext(bdev_name, false, raid_bdev_examine_event_cb, NULL, &ctx->desc);
    3850         [ -  + ]:       5480 :         if (rc) {
    3851         [ #  # ]:          0 :                 SPDK_ERRLOG("Failed to open bdev %s: %s\n", bdev_name, spdk_strerror(-rc));
    3852                 :          0 :                 goto err;
    3853                 :            :         }
    3854                 :            : 
    3855   [ +  -  +  -  :       5480 :         ctx->ch = spdk_bdev_get_io_channel(ctx->desc);
             +  -  +  - ]
    3856   [ +  +  +  -  :       5480 :         if (!ctx->ch) {
                   +  - ]
    3857                 :          0 :                 SPDK_ERRLOG("Failed to get io channel for bdev %s\n", bdev_name);
    3858                 :          0 :                 rc = -ENOMEM;
    3859                 :          0 :                 goto err;
    3860                 :            :         }
    3861                 :            : 
    3862   [ +  -  +  - ]:       5480 :         ctx->cb = cb;
    3863   [ +  -  +  - ]:       5480 :         ctx->cb_ctx = cb_ctx;
    3864                 :            : 
    3865   [ +  -  +  -  :       5480 :         rc = raid_bdev_load_base_bdev_superblock(ctx->desc, ctx->ch, raid_bdev_examine_load_sb_done, ctx);
             +  -  +  - ]
    3866         [ -  + ]:       5480 :         if (rc) {
    3867         [ #  # ]:          0 :                 SPDK_ERRLOG("Failed to read bdev %s superblock: %s\n",
    3868                 :            :                             bdev_name, spdk_strerror(-rc));
    3869                 :          0 :                 goto err;
    3870                 :            :         }
    3871                 :            : 
    3872                 :       5480 :         return 0;
    3873                 :          0 : err:
    3874                 :          0 :         raid_bdev_examine_ctx_free(ctx);
    3875                 :          0 :         return rc;
    3876                 :         47 : }
    3877                 :            : 
    3878                 :            : static void
    3879                 :       5484 : raid_bdev_examine_done(void *ctx, int status)
    3880                 :            : {
    3881                 :       5484 :         struct spdk_bdev *bdev = ctx;
    3882                 :            : 
    3883         [ +  + ]:       5484 :         if (status != 0) {
    3884   [ #  #  #  #  :         11 :                 SPDK_ERRLOG("Failed to examine bdev %s: %s\n",
                   #  # ]
    3885                 :            :                             bdev->name, spdk_strerror(-status));
    3886                 :          0 :         }
    3887                 :       5484 :         spdk_bdev_module_examine_done(&g_raid_if);
    3888                 :       5484 : }
    3889                 :            : 
    3890                 :            : static void
    3891                 :       5454 : raid_bdev_examine_cont(struct spdk_bdev *bdev, const struct raid_bdev_superblock *sb, int status,
    3892                 :            :                        void *ctx)
    3893                 :            : {
    3894      [ +  +  + ]:       5454 :         switch (status) {
    3895                 :        105 :         case 0:
    3896                 :            :                 /* valid superblock found */
    3897   [ -  +  +  -  :        105 :                 SPDK_DEBUGLOG(bdev_raid, "raid superblock found on bdev %s\n", bdev->name);
          #  #  #  #  #  
                      # ]
    3898                 :        105 :                 raid_bdev_examine_sb(sb, bdev, raid_bdev_examine_done, bdev);
    3899                 :        105 :                 return;
    3900                 :       5302 :         case -EINVAL:
    3901                 :            :                 /* no valid superblock, check if it can be claimed anyway */
    3902                 :       5349 :                 raid_bdev_examine_no_sb(bdev);
    3903                 :       5349 :                 status = 0;
    3904                 :       5349 :                 break;
    3905                 :            :         }
    3906                 :            : 
    3907                 :       5349 :         raid_bdev_examine_done(bdev, status);
    3908                 :         47 : }
    3909                 :            : 
    3910                 :            : /*
    3911                 :            :  * brief:
    3912                 :            :  * raid_bdev_examine function is the examine function call by the below layers
    3913                 :            :  * like bdev_nvme layer. This function will check if this base bdev can be
    3914                 :            :  * claimed by this raid bdev or not.
    3915                 :            :  * params:
    3916                 :            :  * bdev - pointer to base bdev
    3917                 :            :  * returns:
    3918                 :            :  * none
    3919                 :            :  */
    3920                 :            : static void
    3921                 :       5484 : raid_bdev_examine(struct spdk_bdev *bdev)
    3922                 :            : {
    3923                 :       5484 :         int rc = 0;
    3924                 :            : 
    3925         [ -  + ]:       5484 :         if (raid_bdev_find_base_info_by_bdev(bdev) != NULL) {
    3926                 :          0 :                 goto done;
    3927                 :            :         }
    3928                 :            : 
    3929         [ +  + ]:       5484 :         if (spdk_bdev_get_dif_type(bdev) != SPDK_DIF_DISABLE) {
    3930                 :         30 :                 raid_bdev_examine_no_sb(bdev);
    3931                 :         30 :                 goto done;
    3932                 :            :         }
    3933                 :            : 
    3934   [ +  -  +  - ]:       5454 :         rc = raid_bdev_examine_load_sb(bdev->name, raid_bdev_examine_cont, NULL);
    3935         [ -  + ]:       5454 :         if (rc != 0) {
    3936                 :          0 :                 goto done;
    3937                 :            :         }
    3938                 :            : 
    3939                 :       5454 :         return;
    3940                 :         30 : done:
    3941                 :         30 :         raid_bdev_examine_done(bdev, rc);
    3942                 :         47 : }
    3943                 :            : 
    3944                 :            : /* Log component for bdev raid bdev module */
    3945                 :       2122 : SPDK_LOG_REGISTER_COMPONENT(bdev_raid)
    3946                 :            : 
    3947                 :            : static void
    3948                 :       1959 : bdev_raid_trace(void)
    3949                 :            : {
    3950                 :       1959 :         struct spdk_trace_tpoint_opts opts[] = {
    3951                 :            :                 {
    3952                 :            :                         "BDEV_RAID_IO_START", TRACE_BDEV_RAID_IO_START,
    3953                 :            :                         OWNER_TYPE_NONE, OBJECT_BDEV_RAID_IO, 1,
    3954                 :            :                         {{ "ctx", SPDK_TRACE_ARG_TYPE_PTR, 8 }}
    3955                 :            :                 },
    3956                 :            :                 {
    3957                 :            :                         "BDEV_RAID_IO_DONE", TRACE_BDEV_RAID_IO_DONE,
    3958                 :            :                         OWNER_TYPE_NONE, OBJECT_BDEV_RAID_IO, 0,
    3959                 :            :                         {{ "ctx", SPDK_TRACE_ARG_TYPE_PTR, 8 }}
    3960                 :            :                 }
    3961                 :            :         };
    3962                 :            : 
    3963                 :            : 
    3964                 :       1959 :         spdk_trace_register_object(OBJECT_BDEV_RAID_IO, 'R');
    3965                 :       1959 :         spdk_trace_register_description_ext(opts, SPDK_COUNTOF(opts));
    3966                 :       1959 :         spdk_trace_tpoint_register_relation(TRACE_BDEV_IO_START, OBJECT_BDEV_RAID_IO, 1);
    3967                 :       1959 :         spdk_trace_tpoint_register_relation(TRACE_BDEV_IO_DONE, OBJECT_BDEV_RAID_IO, 0);
    3968                 :       1959 : }
    3969                 :       2122 : SPDK_TRACE_REGISTER_FN(bdev_raid_trace, "bdev_raid", TRACE_GROUP_BDEV_RAID)

Generated by: LCOV version 1.15