LCOV - code coverage report
Current view: top level - spdk/module/bdev/raid - bdev_raid.c (source / functions) Hit Total Coverage
Test: Combined Lines: 1619 2081 77.8 %
Date: 2024-11-20 08:04:53 Functions: 138 145 95.2 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 984 6769 14.5 %

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

Generated by: LCOV version 1.15