LCOV - code coverage report
Current view: top level - spdk/lib/lvol - lvol.c (source / functions) Hit Total Coverage
Test: Combined Lines: 1150 1414 81.3 %
Date: 2024-12-10 23:09:01 Functions: 91 97 93.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 751 5942 12.6 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (C) 2017 Intel Corporation.
       3                 :            :  *   All rights reserved.
       4                 :            :  *   Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
       5                 :            :  */
       6                 :            : 
       7                 :            : #include "spdk_internal/lvolstore.h"
       8                 :            : #include "spdk/log.h"
       9                 :            : #include "spdk/string.h"
      10                 :            : #include "spdk/thread.h"
      11                 :            : #include "spdk/blob_bdev.h"
      12                 :            : #include "spdk/tree.h"
      13                 :            : #include "spdk/util.h"
      14                 :            : 
      15                 :            : /* Default blob channel opts for lvol */
      16                 :            : #define SPDK_LVOL_BLOB_OPTS_CHANNEL_OPS 512
      17                 :            : 
      18                 :            : #define LVOL_NAME "name"
      19                 :            : 
      20                 :       2161 : SPDK_LOG_REGISTER_COMPONENT(lvol)
      21                 :            : 
      22                 :            : struct spdk_lvs_degraded_lvol_set {
      23                 :            :         struct spdk_lvol_store                  *lvol_store;
      24                 :            :         const void                              *esnap_id;
      25                 :            :         uint32_t                                id_len;
      26                 :            :         TAILQ_HEAD(degraded_lvols, spdk_lvol)   lvols;
      27                 :            :         RB_ENTRY(spdk_lvs_degraded_lvol_set)    node;
      28                 :            : };
      29                 :            : 
      30                 :            : static TAILQ_HEAD(, spdk_lvol_store) g_lvol_stores = TAILQ_HEAD_INITIALIZER(g_lvol_stores);
      31                 :            : static pthread_mutex_t g_lvol_stores_mutex = PTHREAD_MUTEX_INITIALIZER;
      32                 :            : 
      33                 :            : static inline int lvs_opts_copy(const struct spdk_lvs_opts *src, struct spdk_lvs_opts *dst);
      34                 :            : static int lvs_esnap_bs_dev_create(void *bs_ctx, void *blob_ctx, struct spdk_blob *blob,
      35                 :            :                                    const void *esnap_id, uint32_t id_len,
      36                 :            :                                    struct spdk_bs_dev **_bs_dev);
      37                 :            : static struct spdk_lvol *lvs_get_lvol_by_blob_id(struct spdk_lvol_store *lvs, spdk_blob_id blob_id);
      38                 :            : static void lvs_degraded_lvol_set_add(struct spdk_lvs_degraded_lvol_set *degraded_set,
      39                 :            :                                       struct spdk_lvol *lvol);
      40                 :            : static void lvs_degraded_lvol_set_remove(struct spdk_lvs_degraded_lvol_set *degraded_set,
      41                 :            :                 struct spdk_lvol *lvol);
      42                 :            : 
      43                 :            : static int
      44                 :        471 : add_lvs_to_list(struct spdk_lvol_store *lvs)
      45                 :            : {
      46                 :            :         struct spdk_lvol_store *tmp;
      47                 :        471 :         bool name_conflict = false;
      48                 :            : 
      49         [ #  # ]:        471 :         pthread_mutex_lock(&g_lvol_stores_mutex);
      50   [ +  +  #  #  :        512 :         TAILQ_FOREACH(tmp, &g_lvol_stores, link) {
             #  #  #  # ]
      51   [ +  +  -  +  :         50 :                 if (!strncmp(lvs->name, tmp->name, SPDK_LVS_NAME_MAX)) {
          +  +  #  #  #  
                      # ]
      52                 :          9 :                         name_conflict = true;
      53                 :          9 :                         break;
      54                 :            :                 }
      55                 :          7 :         }
      56   [ +  +  #  # ]:        471 :         if (!name_conflict) {
      57   [ #  #  #  # ]:        462 :                 lvs->on_list = true;
      58   [ #  #  #  #  :        462 :                 TAILQ_INSERT_TAIL(&g_lvol_stores, lvs, link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
      59                 :         60 :         }
      60         [ #  # ]:        471 :         pthread_mutex_unlock(&g_lvol_stores_mutex);
      61                 :            : 
      62         [ +  + ]:        471 :         return name_conflict ? -1 : 0;
      63                 :            : }
      64                 :            : 
      65                 :            : static struct spdk_lvol_store *
      66                 :       5738 : lvs_alloc(void)
      67                 :            : {
      68                 :            :         struct spdk_lvol_store *lvs;
      69                 :            : 
      70                 :       5738 :         lvs = calloc(1, sizeof(*lvs));
      71         [ +  + ]:       5738 :         if (lvs == NULL) {
      72                 :          0 :                 return NULL;
      73                 :            :         }
      74                 :            : 
      75   [ +  -  +  -  :       5738 :         TAILQ_INIT(&lvs->lvols);
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
      76   [ +  -  +  -  :       5738 :         TAILQ_INIT(&lvs->pending_lvols);
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
      77   [ +  -  +  -  :       5738 :         TAILQ_INIT(&lvs->retry_open_lvols);
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
      78                 :            : 
      79   [ +  -  +  - ]:       5738 :         lvs->load_esnaps = false;
      80   [ +  -  +  -  :       5738 :         RB_INIT(&lvs->degraded_lvol_sets_tree);
                   +  - ]
      81   [ +  -  +  - ]:       5738 :         lvs->thread = spdk_get_thread();
      82                 :            : 
      83                 :       5738 :         return lvs;
      84                 :        355 : }
      85                 :            : 
      86                 :            : static void
      87                 :       5738 : lvs_free(struct spdk_lvol_store *lvs)
      88                 :            : {
      89         [ +  + ]:       5738 :         pthread_mutex_lock(&g_lvol_stores_mutex);
      90   [ +  +  +  +  :       5738 :         if (lvs->on_list) {
             +  -  +  - ]
      91   [ +  +  #  #  :        462 :                 TAILQ_REMOVE(&g_lvol_stores, lvs, link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
      92                 :         60 :         }
      93         [ +  + ]:       5738 :         pthread_mutex_unlock(&g_lvol_stores_mutex);
      94                 :            : 
      95   [ +  +  +  -  :       5738 :         assert(RB_EMPTY(&lvs->degraded_lvol_sets_tree));
          +  -  +  -  #  
                      # ]
      96                 :            : 
      97                 :       5738 :         free(lvs);
      98                 :       5738 : }
      99                 :            : 
     100                 :            : static struct spdk_lvol *
     101                 :        651 : lvol_alloc(struct spdk_lvol_store *lvs, const char *name, bool thin_provision,
     102                 :            :            enum lvol_clear_method clear_method)
     103                 :            : {
     104                 :            :         struct spdk_lvol *lvol;
     105                 :            : 
     106                 :        651 :         lvol = calloc(1, sizeof(*lvol));
     107         [ -  + ]:        651 :         if (lvol == NULL) {
     108                 :          0 :                 return NULL;
     109                 :            :         }
     110                 :            : 
     111   [ #  #  #  # ]:        651 :         lvol->lvol_store = lvs;
     112   [ #  #  #  # ]:        651 :         lvol->clear_method = (enum blob_clear_method)clear_method;
     113         [ -  + ]:        651 :         snprintf(lvol->name, sizeof(lvol->name), "%s", name);
     114         [ #  # ]:        651 :         spdk_uuid_generate(&lvol->uuid);
     115   [ #  #  #  # ]:        651 :         spdk_uuid_fmt_lower(lvol->uuid_str, sizeof(lvol->uuid_str), &lvol->uuid);
     116   [ #  #  #  # ]:        651 :         spdk_uuid_fmt_lower(lvol->unique_id, sizeof(lvol->uuid_str), &lvol->uuid);
     117                 :            : 
     118   [ #  #  #  #  :        651 :         TAILQ_INSERT_TAIL(&lvs->pending_lvols, lvol, link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     119                 :            : 
     120                 :        651 :         return lvol;
     121                 :         83 : }
     122                 :            : 
     123                 :            : static void
     124                 :        778 : lvol_free(struct spdk_lvol *lvol)
     125                 :            : {
     126                 :        778 :         free(lvol);
     127                 :        778 : }
     128                 :            : 
     129                 :            : static void
     130                 :        123 : lvol_open_cb(void *cb_arg, struct spdk_blob *blob, int lvolerrno)
     131                 :            : {
     132                 :        123 :         struct spdk_lvol_with_handle_req *req = cb_arg;
     133   [ #  #  #  # ]:        123 :         struct spdk_lvol *lvol = req->lvol;
     134                 :            : 
     135         [ +  + ]:        123 :         if (lvolerrno != 0) {
     136   [ -  +  -  +  :         12 :                 SPDK_INFOLOG(lvol, "Failed to open lvol %s\n", lvol->unique_id);
             #  #  #  # ]
     137                 :         12 :                 goto end;
     138                 :            :         }
     139                 :            : 
     140   [ #  #  #  # ]:        111 :         lvol->ref_count++;
     141   [ #  #  #  # ]:        111 :         lvol->blob = blob;
     142                 :        113 : end:
     143   [ #  #  #  #  :        123 :         req->cb_fn(req->cb_arg, lvol, lvolerrno);
          #  #  #  #  #  
                #  #  # ]
     144                 :        123 :         free(req);
     145                 :        123 : }
     146                 :            : 
     147                 :            : void
     148                 :        127 : spdk_lvol_open(struct spdk_lvol *lvol, spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg)
     149                 :            : {
     150                 :            :         struct spdk_lvol_with_handle_req *req;
     151                 :         98 :         struct spdk_blob_open_opts opts;
     152                 :            : 
     153   [ +  +  #  # ]:        127 :         assert(cb_fn != NULL);
     154                 :            : 
     155         [ +  + ]:        127 :         if (lvol == NULL) {
     156                 :          0 :                 SPDK_ERRLOG("lvol does not exist\n");
     157   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, NULL, -ENODEV);
     158                 :          0 :                 return;
     159                 :            :         }
     160                 :            : 
     161   [ -  +  -  +  :        127 :         if (lvol->action_in_progress == true) {
             #  #  #  # ]
     162                 :          0 :                 SPDK_ERRLOG("Cannot open lvol - operations on lvol pending\n");
     163   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, lvol, -EBUSY);
     164                 :          0 :                 return;
     165                 :            :         }
     166                 :            : 
     167   [ +  +  #  #  :        127 :         if (lvol->ref_count > 0) {
                   #  # ]
     168   [ #  #  #  # ]:          4 :                 lvol->ref_count++;
     169   [ #  #  #  # ]:          4 :                 cb_fn(cb_arg, lvol, 0);
     170                 :          4 :                 return;
     171                 :            :         }
     172                 :            : 
     173                 :        123 :         req = calloc(1, sizeof(*req));
     174         [ +  + ]:        123 :         if (req == NULL) {
     175                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for request structure\n");
     176   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, NULL, -ENOMEM);
     177                 :          0 :                 return;
     178                 :            :         }
     179                 :            : 
     180   [ #  #  #  # ]:        123 :         req->cb_fn = cb_fn;
     181   [ #  #  #  # ]:        123 :         req->cb_arg = cb_arg;
     182   [ #  #  #  # ]:        123 :         req->lvol = lvol;
     183                 :            : 
     184                 :        123 :         spdk_blob_open_opts_init(&opts, sizeof(opts));
     185   [ #  #  #  # ]:        123 :         opts.clear_method = lvol->clear_method;
     186                 :            : 
     187   [ #  #  #  #  :        123 :         spdk_bs_open_blob_ext(lvol->lvol_store->blobstore, lvol->blob_id, &opts, lvol_open_cb, req);
          #  #  #  #  #  
                #  #  # ]
     188                 :         11 : }
     189                 :            : 
     190                 :            : static void
     191                 :         32 : bs_unload_with_error_cb(void *cb_arg, int lvolerrno)
     192                 :            : {
     193                 :         32 :         struct spdk_lvs_with_handle_req *req = (struct spdk_lvs_with_handle_req *)cb_arg;
     194                 :            : 
     195   [ #  #  #  #  :         32 :         req->cb_fn(req->cb_arg, NULL, req->lvserrno);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     196                 :         32 :         free(req);
     197                 :         32 : }
     198                 :            : 
     199                 :            : static void
     200                 :        351 : load_next_lvol(void *cb_arg, struct spdk_blob *blob, int lvolerrno)
     201                 :            : {
     202                 :        351 :         struct spdk_lvs_with_handle_req *req = cb_arg;
     203   [ #  #  #  # ]:        351 :         struct spdk_lvol_store *lvs = req->lvol_store;
     204   [ #  #  #  # ]:        351 :         struct spdk_blob_store *bs = lvs->blobstore;
     205                 :            :         struct spdk_lvol *lvol, *tmp;
     206                 :            :         spdk_blob_id blob_id;
     207                 :        265 :         const char *attr;
     208                 :        265 :         size_t value_len;
     209                 :            :         int rc;
     210                 :            : 
     211         [ +  + ]:        351 :         if (lvolerrno == -ENOENT) {
     212                 :            :                 /* Finished iterating */
     213   [ +  +  #  #  :        102 :                 if (req->lvserrno == 0) {
                   #  # ]
     214   [ #  #  #  # ]:         94 :                         lvs->load_esnaps = true;
     215   [ #  #  #  #  :         94 :                         req->cb_fn(req->cb_arg, lvs, req->lvserrno);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     216                 :         94 :                         free(req);
     217                 :          7 :                 } else {
     218   [ +  +  +  +  :         24 :                         TAILQ_FOREACH_SAFE(lvol, &lvs->lvols, link, tmp) {
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     219   [ +  +  #  #  :         16 :                                 TAILQ_REMOVE(&lvs->lvols, lvol, link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
     220                 :         16 :                                 lvol_free(lvol);
     221                 :          4 :                         }
     222                 :          8 :                         lvs_free(lvs);
     223                 :          8 :                         spdk_bs_unload(bs, bs_unload_with_error_cb, req);
     224                 :            :                 }
     225                 :        119 :                 return;
     226         [ +  + ]:        249 :         } else if (lvolerrno < 0) {
     227                 :          8 :                 SPDK_ERRLOG("Failed to fetch blobs list\n");
     228   [ #  #  #  # ]:          8 :                 req->lvserrno = lvolerrno;
     229                 :          8 :                 goto invalid;
     230                 :            :         }
     231                 :            : 
     232                 :        241 :         blob_id = spdk_blob_get_id(blob);
     233                 :            : 
     234   [ +  +  #  #  :        241 :         if (blob_id == lvs->super_blob_id) {
                   #  # ]
     235   [ +  +  -  +  :        102 :                 SPDK_INFOLOG(lvol, "found superblob %"PRIu64"\n", (uint64_t)blob_id);
                   #  # ]
     236                 :        102 :                 spdk_bs_iter_next(bs, blob, load_next_lvol, req);
     237                 :        102 :                 return;
     238                 :            :         }
     239                 :            : 
     240                 :        139 :         lvol = calloc(1, sizeof(*lvol));
     241         [ +  + ]:        139 :         if (!lvol) {
     242                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol base pointer\n");
     243   [ #  #  #  # ]:          0 :                 req->lvserrno = -ENOMEM;
     244                 :          0 :                 goto invalid;
     245                 :            :         }
     246                 :            : 
     247                 :            :         /*
     248                 :            :          * Do not store a reference to blob now because spdk_bs_iter_next() will close it.
     249                 :            :          * Storing blob_id for future lookups is fine.
     250                 :            :          */
     251   [ #  #  #  # ]:        139 :         lvol->blob_id = blob_id;
     252   [ #  #  #  # ]:        139 :         lvol->lvol_store = lvs;
     253                 :            : 
     254                 :        139 :         rc = spdk_blob_get_xattr_value(blob, "uuid", (const void **)&attr, &value_len);
     255   [ +  -  +  -  :        264 :         if (rc != 0 || value_len != SPDK_UUID_STRING_LEN || attr[SPDK_UUID_STRING_LEN - 1] != '\0' ||
          +  -  -  +  #  
                #  #  # ]
     256         [ #  # ]:        139 :             spdk_uuid_parse(&lvol->uuid, attr) != 0) {
     257   [ #  #  #  #  :          0 :                 SPDK_INFOLOG(lvol, "Missing or corrupt lvol uuid\n");
                   #  # ]
     258         [ #  # ]:          0 :                 spdk_uuid_set_null(&lvol->uuid);
     259                 :          0 :         }
     260   [ #  #  #  # ]:        139 :         spdk_uuid_fmt_lower(lvol->uuid_str, sizeof(lvol->uuid_str), &lvol->uuid);
     261                 :            : 
     262   [ +  +  #  # ]:        139 :         if (!spdk_uuid_is_null(&lvol->uuid)) {
     263   [ #  #  #  # ]:        139 :                 snprintf(lvol->unique_id, sizeof(lvol->unique_id), "%s", lvol->uuid_str);
     264                 :         14 :         } else {
     265   [ #  #  #  #  :          0 :                 spdk_uuid_fmt_lower(lvol->unique_id, sizeof(lvol->unique_id), &lvol->lvol_store->uuid);
             #  #  #  # ]
     266   [ #  #  #  # ]:          0 :                 value_len = strlen(lvol->unique_id);
     267   [ #  #  #  #  :          0 :                 snprintf(lvol->unique_id + value_len, sizeof(lvol->unique_id) - value_len, "_%"PRIu64,
                   #  # ]
     268                 :          0 :                          (uint64_t)blob_id);
     269                 :            :         }
     270                 :            : 
     271                 :        139 :         rc = spdk_blob_get_xattr_value(blob, "name", (const void **)&attr, &value_len);
     272   [ +  -  -  + ]:        139 :         if (rc != 0 || value_len > SPDK_LVOL_NAME_MAX) {
     273                 :          0 :                 SPDK_ERRLOG("Cannot assign lvol name\n");
     274                 :          0 :                 lvol_free(lvol);
     275   [ #  #  #  # ]:          0 :                 req->lvserrno = -EINVAL;
     276                 :          0 :                 goto invalid;
     277                 :            :         }
     278                 :            : 
     279         [ #  # ]:        139 :         snprintf(lvol->name, sizeof(lvol->name), "%s", attr);
     280                 :            : 
     281   [ #  #  #  #  :        139 :         TAILQ_INSERT_TAIL(&lvs->lvols, lvol, link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     282                 :            : 
     283   [ #  #  #  # ]:        139 :         lvs->lvol_count++;
     284                 :            : 
     285   [ +  +  +  -  :        139 :         SPDK_INFOLOG(lvol, "added lvol %s (%s)\n", lvol->unique_id, lvol->uuid_str);
          #  #  #  #  #  
                      # ]
     286                 :            : 
     287                 :        131 : invalid:
     288                 :        147 :         spdk_bs_iter_next(bs, blob, load_next_lvol, req);
     289                 :         34 : }
     290                 :            : 
     291                 :            : static void
     292                 :        106 : close_super_cb(void *cb_arg, int lvolerrno)
     293                 :            : {
     294                 :        106 :         struct spdk_lvs_with_handle_req *req = (struct spdk_lvs_with_handle_req *)cb_arg;
     295   [ #  #  #  # ]:        106 :         struct spdk_lvol_store *lvs = req->lvol_store;
     296   [ #  #  #  # ]:        106 :         struct spdk_blob_store *bs = lvs->blobstore;
     297                 :            : 
     298         [ +  + ]:        106 :         if (lvolerrno != 0) {
     299   [ -  +  -  +  :          4 :                 SPDK_INFOLOG(lvol, "Could not close super blob\n");
                   #  # ]
     300                 :          4 :                 lvs_free(lvs);
     301   [ #  #  #  # ]:          4 :                 req->lvserrno = -ENODEV;
     302                 :          4 :                 spdk_bs_unload(bs, bs_unload_with_error_cb, req);
     303                 :          4 :                 return;
     304                 :            :         }
     305                 :            : 
     306                 :            :         /* Start loading lvols */
     307   [ #  #  #  # ]:        102 :         spdk_bs_iter_first(lvs->blobstore, load_next_lvol, req);
     308                 :         10 : }
     309                 :            : 
     310                 :            : static void
     311                 :         12 : close_super_blob_with_error_cb(void *cb_arg, int lvolerrno)
     312                 :            : {
     313                 :         12 :         struct spdk_lvs_with_handle_req *req = (struct spdk_lvs_with_handle_req *)cb_arg;
     314   [ #  #  #  # ]:         12 :         struct spdk_lvol_store *lvs = req->lvol_store;
     315   [ #  #  #  # ]:         12 :         struct spdk_blob_store *bs = lvs->blobstore;
     316                 :            : 
     317                 :         12 :         lvs_free(lvs);
     318                 :            : 
     319                 :         12 :         spdk_bs_unload(bs, bs_unload_with_error_cb, req);
     320                 :         12 : }
     321                 :            : 
     322                 :            : static void
     323                 :        122 : lvs_read_uuid(void *cb_arg, struct spdk_blob *blob, int lvolerrno)
     324                 :            : {
     325                 :        122 :         struct spdk_lvs_with_handle_req *req = (struct spdk_lvs_with_handle_req *)cb_arg;
     326   [ #  #  #  # ]:        122 :         struct spdk_lvol_store *lvs = req->lvol_store;
     327   [ #  #  #  # ]:        122 :         struct spdk_blob_store *bs = lvs->blobstore;
     328                 :         91 :         const char *attr;
     329                 :         91 :         size_t value_len;
     330                 :            :         int rc;
     331                 :            : 
     332         [ +  + ]:        122 :         if (lvolerrno != 0) {
     333   [ +  +  -  +  :          4 :                 SPDK_INFOLOG(lvol, "Could not open super blob\n");
                   #  # ]
     334                 :          4 :                 lvs_free(lvs);
     335   [ #  #  #  # ]:          4 :                 req->lvserrno = -ENODEV;
     336                 :          4 :                 spdk_bs_unload(bs, bs_unload_with_error_cb, req);
     337                 :          4 :                 return;
     338                 :            :         }
     339                 :            : 
     340                 :        118 :         rc = spdk_blob_get_xattr_value(blob, "uuid", (const void **)&attr, &value_len);
     341   [ +  +  +  -  :        118 :         if (rc != 0 || value_len != SPDK_UUID_STRING_LEN || attr[SPDK_UUID_STRING_LEN - 1] != '\0') {
          -  +  #  #  #  
                      # ]
     342   [ +  +  -  +  :          4 :                 SPDK_INFOLOG(lvol, "degraded_set or incorrect UUID\n");
                   #  # ]
     343   [ #  #  #  # ]:          4 :                 req->lvserrno = -EINVAL;
     344                 :          4 :                 spdk_blob_close(blob, close_super_blob_with_error_cb, req);
     345                 :          4 :                 return;
     346                 :            :         }
     347                 :            : 
     348   [ -  +  #  # ]:        114 :         if (spdk_uuid_parse(&lvs->uuid, attr)) {
     349   [ #  #  #  #  :          0 :                 SPDK_INFOLOG(lvol, "incorrect UUID '%s'\n", attr);
                   #  # ]
     350   [ #  #  #  # ]:          0 :                 req->lvserrno = -EINVAL;
     351                 :          0 :                 spdk_blob_close(blob, close_super_blob_with_error_cb, req);
     352                 :          0 :                 return;
     353                 :            :         }
     354                 :            : 
     355                 :        114 :         rc = spdk_blob_get_xattr_value(blob, "name", (const void **)&attr, &value_len);
     356   [ +  +  -  + ]:        114 :         if (rc != 0 || value_len > SPDK_LVS_NAME_MAX) {
     357   [ +  +  -  +  :          4 :                 SPDK_INFOLOG(lvol, "degraded_set or invalid name\n");
                   #  # ]
     358   [ #  #  #  # ]:          4 :                 req->lvserrno = -EINVAL;
     359                 :          4 :                 spdk_blob_close(blob, close_super_blob_with_error_cb, req);
     360                 :          4 :                 return;
     361                 :            :         }
     362                 :            : 
     363         [ -  + ]:        110 :         snprintf(lvs->name, sizeof(lvs->name), "%s", attr);
     364                 :            : 
     365                 :        110 :         rc = add_lvs_to_list(lvs);
     366         [ +  + ]:        110 :         if (rc) {
     367   [ -  +  -  +  :          4 :                 SPDK_INFOLOG(lvol, "lvolstore with name %s already exists\n", lvs->name);
             #  #  #  # ]
     368   [ #  #  #  # ]:          4 :                 req->lvserrno = -EEXIST;
     369                 :          4 :                 spdk_blob_close(blob, close_super_blob_with_error_cb, req);
     370                 :          4 :                 return;
     371                 :            :         }
     372                 :            : 
     373   [ #  #  #  # ]:        106 :         lvs->super_blob_id = spdk_blob_get_id(blob);
     374                 :            : 
     375                 :        106 :         spdk_blob_close(blob, close_super_cb, req);
     376                 :         14 : }
     377                 :            : 
     378                 :            : static void
     379                 :        126 : lvs_open_super(void *cb_arg, spdk_blob_id blobid, int lvolerrno)
     380                 :            : {
     381                 :        126 :         struct spdk_lvs_with_handle_req *req = (struct spdk_lvs_with_handle_req *)cb_arg;
     382   [ #  #  #  # ]:        126 :         struct spdk_lvol_store *lvs = req->lvol_store;
     383   [ #  #  #  # ]:        126 :         struct spdk_blob_store *bs = lvs->blobstore;
     384                 :            : 
     385         [ +  + ]:        126 :         if (lvolerrno != 0) {
     386   [ -  +  -  +  :          4 :                 SPDK_INFOLOG(lvol, "Super blob not found\n");
                   #  # ]
     387                 :          4 :                 lvs_free(lvs);
     388   [ #  #  #  # ]:          4 :                 req->lvserrno = -ENODEV;
     389                 :          4 :                 spdk_bs_unload(bs, bs_unload_with_error_cb, req);
     390                 :          4 :                 return;
     391                 :            :         }
     392                 :            : 
     393                 :        122 :         spdk_bs_open_blob(bs, blobid, lvs_read_uuid, req);
     394                 :         15 : }
     395                 :            : 
     396                 :            : static void
     397                 :       5365 : lvs_load_cb(void *cb_arg, struct spdk_blob_store *bs, int lvolerrno)
     398                 :            : {
     399                 :       5365 :         struct spdk_lvs_with_handle_req *req = (struct spdk_lvs_with_handle_req *)cb_arg;
     400   [ +  -  +  - ]:       5365 :         struct spdk_lvol_store *lvs = req->lvol_store;
     401                 :            : 
     402         [ +  + ]:       5365 :         if (lvolerrno != 0) {
     403   [ +  -  +  -  :       5239 :                 req->cb_fn(req->cb_arg, NULL, lvolerrno);
          -  +  -  +  +  
                -  +  - ]
     404                 :       5239 :                 lvs_free(lvs);
     405                 :       5239 :                 free(req);
     406                 :       5239 :                 return;
     407                 :            :         }
     408                 :            : 
     409   [ #  #  #  # ]:        126 :         lvs->blobstore = bs;
     410   [ #  #  #  #  :        126 :         lvs->bs_dev = req->bs_dev;
             #  #  #  # ]
     411                 :            : 
     412                 :        126 :         spdk_bs_get_super(bs, lvs_open_super, req);
     413                 :        301 : }
     414                 :            : 
     415                 :            : static void
     416                 :       5734 : lvs_bs_opts_init(struct spdk_bs_opts *opts)
     417                 :            : {
     418                 :       5734 :         spdk_bs_opts_init(opts, sizeof(*opts));
     419   [ +  -  +  - ]:       5734 :         opts->max_channel_ops = SPDK_LVOL_BLOB_OPTS_CHANNEL_OPS;
     420                 :       5734 : }
     421                 :            : 
     422                 :            : static void
     423                 :       5369 : lvs_load(struct spdk_bs_dev *bs_dev, const struct spdk_lvs_opts *_lvs_opts,
     424                 :            :          spdk_lvs_op_with_handle_complete cb_fn, void *cb_arg)
     425                 :            : {
     426                 :            :         struct spdk_lvs_with_handle_req *req;
     427                 :       5369 :         struct spdk_bs_opts bs_opts = {};
     428                 :       2638 :         struct spdk_lvs_opts lvs_opts;
     429                 :            : 
     430   [ +  +  #  # ]:       5369 :         assert(cb_fn != NULL);
     431                 :            : 
     432         [ +  + ]:       5369 :         if (bs_dev == NULL) {
     433                 :          0 :                 SPDK_ERRLOG("Blobstore device does not exist\n");
     434   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, NULL, -ENODEV);
     435                 :          0 :                 return;
     436                 :            :         }
     437                 :            : 
     438                 :       5369 :         spdk_lvs_opts_init(&lvs_opts);
     439         [ +  + ]:       5369 :         if (_lvs_opts != NULL) {
     440         [ +  + ]:       5313 :                 if (lvs_opts_copy(_lvs_opts, &lvs_opts) != 0) {
     441                 :          4 :                         SPDK_ERRLOG("Invalid options\n");
     442   [ #  #  #  # ]:          4 :                         cb_fn(cb_arg, NULL, -EINVAL);
     443                 :          4 :                         return;
     444                 :            :                 }
     445                 :        287 :         }
     446                 :            : 
     447                 :       5365 :         req = calloc(1, sizeof(*req));
     448         [ +  + ]:       5365 :         if (req == NULL) {
     449                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for request structure\n");
     450   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, NULL, -ENOMEM);
     451                 :          0 :                 return;
     452                 :            :         }
     453                 :            : 
     454   [ +  -  +  - ]:       5365 :         req->lvol_store = lvs_alloc();
     455   [ +  +  +  -  :       5365 :         if (req->lvol_store == NULL) {
                   +  - ]
     456                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol store\n");
     457                 :          0 :                 free(req);
     458   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, NULL, -ENOMEM);
     459                 :          0 :                 return;
     460                 :            :         }
     461   [ +  -  +  - ]:       5365 :         req->cb_fn = cb_fn;
     462   [ +  -  +  - ]:       5365 :         req->cb_arg = cb_arg;
     463   [ +  -  +  - ]:       5365 :         req->bs_dev = bs_dev;
     464                 :            : 
     465                 :       5365 :         lvs_bs_opts_init(&bs_opts);
     466         [ -  + ]:       5365 :         snprintf(bs_opts.bstype.bstype, sizeof(bs_opts.bstype.bstype), "LVOLSTORE");
     467                 :            : 
     468         [ +  + ]:       5365 :         if (lvs_opts.esnap_bs_dev_create != NULL) {
     469   [ +  -  +  -  :       5309 :                 req->lvol_store->esnap_bs_dev_create = lvs_opts.esnap_bs_dev_create;
             +  -  +  - ]
     470                 :       5309 :                 bs_opts.esnap_bs_dev_create = lvs_esnap_bs_dev_create;
     471   [ +  -  +  - ]:       5309 :                 bs_opts.esnap_ctx = req->lvol_store;
     472                 :        287 :         }
     473                 :            : 
     474                 :       5365 :         spdk_bs_load(bs_dev, &bs_opts, lvs_load_cb, req);
     475                 :        302 : }
     476                 :            : 
     477                 :            : void
     478                 :         56 : spdk_lvs_load(struct spdk_bs_dev *bs_dev, spdk_lvs_op_with_handle_complete cb_fn, void *cb_arg)
     479                 :            : {
     480                 :         56 :         lvs_load(bs_dev, NULL, cb_fn, cb_arg);
     481                 :         56 : }
     482                 :            : 
     483                 :            : void
     484                 :       5313 : spdk_lvs_load_ext(struct spdk_bs_dev *bs_dev, const struct spdk_lvs_opts *opts,
     485                 :            :                   spdk_lvs_op_with_handle_complete cb_fn, void *cb_arg)
     486                 :            : {
     487                 :       5313 :         lvs_load(bs_dev, opts, cb_fn, cb_arg);
     488                 :       5313 : }
     489                 :            : 
     490                 :            : static void
     491                 :          0 : remove_bs_on_error_cb(void *cb_arg, int bserrno)
     492                 :            : {
     493                 :          0 : }
     494                 :            : 
     495                 :            : static void
     496                 :          0 : exit_error_lvs_req(struct spdk_lvs_with_handle_req *req, struct spdk_lvol_store *lvs, int lvolerrno)
     497                 :            : {
     498   [ #  #  #  #  :          0 :         req->cb_fn(req->cb_arg, NULL, lvolerrno);
          #  #  #  #  #  
                #  #  # ]
     499   [ #  #  #  # ]:          0 :         spdk_bs_destroy(lvs->blobstore, remove_bs_on_error_cb, NULL);
     500                 :          0 :         lvs_free(lvs);
     501                 :          0 :         free(req);
     502                 :          0 : }
     503                 :            : 
     504                 :            : static void
     505                 :        356 : super_create_close_cb(void *cb_arg, int lvolerrno)
     506                 :            : {
     507                 :        356 :         struct spdk_lvs_with_handle_req *req = cb_arg;
     508   [ #  #  #  # ]:        356 :         struct spdk_lvol_store *lvs = req->lvol_store;
     509                 :            : 
     510         [ -  + ]:        356 :         if (lvolerrno < 0) {
     511                 :          0 :                 SPDK_ERRLOG("Lvol store init failed: could not close super blob\n");
     512                 :          0 :                 exit_error_lvs_req(req, lvs, lvolerrno);
     513                 :          0 :                 return;
     514                 :            :         }
     515                 :            : 
     516   [ #  #  #  #  :        356 :         req->cb_fn(req->cb_arg, lvs, lvolerrno);
          #  #  #  #  #  
                #  #  # ]
     517                 :        356 :         free(req);
     518                 :         50 : }
     519                 :            : 
     520                 :            : static void
     521                 :        356 : super_blob_set_cb(void *cb_arg, int lvolerrno)
     522                 :            : {
     523                 :        356 :         struct spdk_lvs_with_handle_req *req = cb_arg;
     524   [ #  #  #  # ]:        356 :         struct spdk_lvol_store *lvs = req->lvol_store;
     525   [ #  #  #  # ]:        356 :         struct spdk_blob *blob = lvs->super_blob;
     526                 :            : 
     527         [ -  + ]:        356 :         if (lvolerrno < 0) {
     528                 :          0 :                 SPDK_ERRLOG("Lvol store init failed: could not set uuid for super blob\n");
     529                 :          0 :                 exit_error_lvs_req(req, lvs, lvolerrno);
     530                 :          0 :                 return;
     531                 :            :         }
     532                 :            : 
     533                 :        356 :         spdk_blob_close(blob, super_create_close_cb, req);
     534                 :         50 : }
     535                 :            : 
     536                 :            : static void
     537                 :        356 : super_blob_init_cb(void *cb_arg, int lvolerrno)
     538                 :            : {
     539                 :        356 :         struct spdk_lvs_with_handle_req *req = cb_arg;
     540   [ #  #  #  # ]:        356 :         struct spdk_lvol_store *lvs = req->lvol_store;
     541   [ #  #  #  # ]:        356 :         struct spdk_blob *blob = lvs->super_blob;
     542                 :        256 :         char uuid[SPDK_UUID_STRING_LEN];
     543                 :            : 
     544         [ -  + ]:        356 :         if (lvolerrno < 0) {
     545                 :          0 :                 SPDK_ERRLOG("Lvol store init failed: could not set super blob\n");
     546                 :          0 :                 exit_error_lvs_req(req, lvs, lvolerrno);
     547                 :          0 :                 return;
     548                 :            :         }
     549                 :            : 
     550         [ #  # ]:        356 :         spdk_uuid_fmt_lower(uuid, sizeof(uuid), &lvs->uuid);
     551                 :            : 
     552                 :        356 :         spdk_blob_set_xattr(blob, "uuid", uuid, sizeof(uuid));
     553   [ -  +  #  #  :        356 :         spdk_blob_set_xattr(blob, "name", lvs->name, strnlen(lvs->name, SPDK_LVS_NAME_MAX) + 1);
                   #  # ]
     554                 :        356 :         spdk_blob_sync_md(blob, super_blob_set_cb, req);
     555                 :         50 : }
     556                 :            : 
     557                 :            : static void
     558                 :        356 : super_blob_create_open_cb(void *cb_arg, struct spdk_blob *blob, int lvolerrno)
     559                 :            : {
     560                 :        356 :         struct spdk_lvs_with_handle_req *req = cb_arg;
     561   [ #  #  #  # ]:        356 :         struct spdk_lvol_store *lvs = req->lvol_store;
     562                 :            : 
     563         [ -  + ]:        356 :         if (lvolerrno < 0) {
     564                 :          0 :                 SPDK_ERRLOG("Lvol store init failed: could not open super blob\n");
     565                 :          0 :                 exit_error_lvs_req(req, lvs, lvolerrno);
     566                 :          0 :                 return;
     567                 :            :         }
     568                 :            : 
     569   [ #  #  #  # ]:        356 :         lvs->super_blob = blob;
     570   [ #  #  #  # ]:        356 :         lvs->super_blob_id = spdk_blob_get_id(blob);
     571                 :            : 
     572   [ #  #  #  #  :        356 :         spdk_bs_set_super(lvs->blobstore, lvs->super_blob_id, super_blob_init_cb, req);
             #  #  #  # ]
     573                 :         50 : }
     574                 :            : 
     575                 :            : static void
     576                 :        356 : super_blob_create_cb(void *cb_arg, spdk_blob_id blobid, int lvolerrno)
     577                 :            : {
     578                 :        356 :         struct spdk_lvs_with_handle_req *req = cb_arg;
     579   [ #  #  #  # ]:        356 :         struct spdk_lvol_store *lvs = req->lvol_store;
     580                 :            :         struct spdk_blob_store *bs;
     581                 :            : 
     582         [ -  + ]:        356 :         if (lvolerrno < 0) {
     583                 :          0 :                 SPDK_ERRLOG("Lvol store init failed: could not create super blob\n");
     584                 :          0 :                 exit_error_lvs_req(req, lvs, lvolerrno);
     585                 :          0 :                 return;
     586                 :            :         }
     587                 :            : 
     588   [ #  #  #  #  :        356 :         bs = req->lvol_store->blobstore;
             #  #  #  # ]
     589                 :            : 
     590                 :        356 :         spdk_bs_open_blob(bs, blobid, super_blob_create_open_cb, req);
     591                 :         50 : }
     592                 :            : 
     593                 :            : static void
     594                 :        356 : lvs_init_cb(void *cb_arg, struct spdk_blob_store *bs, int lvserrno)
     595                 :            : {
     596                 :        356 :         struct spdk_lvs_with_handle_req *lvs_req = cb_arg;
     597   [ #  #  #  # ]:        356 :         struct spdk_lvol_store *lvs = lvs_req->lvol_store;
     598                 :            : 
     599         [ -  + ]:        356 :         if (lvserrno != 0) {
     600   [ #  #  #  # ]:          0 :                 assert(bs == NULL);
     601   [ #  #  #  #  :          0 :                 lvs_req->cb_fn(lvs_req->cb_arg, NULL, lvserrno);
          #  #  #  #  #  
                #  #  # ]
     602                 :          0 :                 SPDK_ERRLOG("Lvol store init failed: could not initialize blobstore\n");
     603                 :          0 :                 lvs_free(lvs);
     604                 :          0 :                 free(lvs_req);
     605                 :          0 :                 return;
     606                 :            :         }
     607                 :            : 
     608   [ +  +  #  # ]:        356 :         assert(bs != NULL);
     609   [ #  #  #  # ]:        356 :         lvs->blobstore = bs;
     610                 :            : 
     611   [ +  +  -  +  :        356 :         SPDK_INFOLOG(lvol, "Lvol store initialized\n");
                   #  # ]
     612                 :            : 
     613                 :            :         /* create super blob */
     614   [ #  #  #  # ]:        356 :         spdk_bs_create_blob(lvs->blobstore, super_blob_create_cb, lvs_req);
     615                 :         50 : }
     616                 :            : 
     617                 :            : void
     618                 :      11410 : spdk_lvs_opts_init(struct spdk_lvs_opts *o)
     619                 :            : {
     620         [ +  + ]:      11410 :         memset(o, 0, sizeof(*o));
     621   [ +  -  +  - ]:      11410 :         o->cluster_sz = SPDK_LVS_OPTS_CLUSTER_SZ;
     622   [ +  -  +  - ]:      11410 :         o->clear_method = LVS_CLEAR_WITH_UNMAP;
     623   [ +  -  +  - ]:      11410 :         o->num_md_pages_per_cluster_ratio = 100;
     624   [ +  -  +  - ]:      11410 :         o->opts_size = sizeof(*o);
     625                 :      11410 : }
     626                 :            : 
     627                 :            : static inline int
     628                 :       5684 : lvs_opts_copy(const struct spdk_lvs_opts *src, struct spdk_lvs_opts *dst)
     629                 :            : {
     630   [ +  +  +  -  :       5684 :         if (src->opts_size == 0) {
                   +  - ]
     631                 :          4 :                 SPDK_ERRLOG("opts_size should not be zero value\n");
     632                 :          4 :                 return -1;
     633                 :            :         }
     634                 :            : #define FIELD_OK(field) \
     635                 :            :         offsetof(struct spdk_lvs_opts, field) + sizeof(src->field) <= src->opts_size
     636                 :            : 
     637                 :            : #define SET_FIELD(field) \
     638                 :            :         if (FIELD_OK(field)) { \
     639                 :            :                 dst->field = src->field; \
     640                 :            :         } \
     641                 :            : 
     642   [ +  +  +  -  :       5680 :         SET_FIELD(cluster_sz);
          -  +  +  -  +  
             -  +  -  +  
                      - ]
     643   [ +  +  +  -  :       5680 :         SET_FIELD(clear_method);
          -  +  +  -  +  
             -  +  -  +  
                      - ]
     644   [ +  +  +  -  :       5680 :         if (FIELD_OK(name)) {
                   -  + ]
     645   [ +  +  +  +  :       5680 :                 memcpy(&dst->name, &src->name, sizeof(dst->name));
             +  -  +  - ]
     646                 :        340 :         }
     647   [ +  +  +  -  :       5680 :         SET_FIELD(num_md_pages_per_cluster_ratio);
          -  +  +  -  +  
             -  +  -  +  
                      - ]
     648   [ +  +  +  -  :       5680 :         SET_FIELD(opts_size);
          -  +  +  -  +  
             -  +  -  +  
                      - ]
     649   [ +  +  +  -  :       5680 :         SET_FIELD(esnap_bs_dev_create);
          -  +  +  -  +  
             -  +  -  +  
                      - ]
     650   [ +  +  +  -  :       5680 :         SET_FIELD(md_page_size);
          -  +  +  -  +  
             -  +  -  +  
                      - ]
     651                 :            : 
     652   [ +  -  +  -  :       5680 :         dst->opts_size = src->opts_size;
             +  -  +  - ]
     653                 :            : 
     654                 :            :         /* You should not remove this statement, but need to update the assert statement
     655                 :            :          * if you add a new field, and also add a corresponding SET_FIELD statement */
     656                 :            :         SPDK_STATIC_ASSERT(sizeof(struct spdk_lvs_opts) == 92, "Incorrect size");
     657                 :            : 
     658                 :            : #undef FIELD_OK
     659                 :            : #undef SET_FIELD
     660                 :            : 
     661                 :       5680 :         return 0;
     662                 :        341 : }
     663                 :            : 
     664                 :            : static void
     665                 :        369 : setup_lvs_opts(struct spdk_bs_opts *bs_opts, struct spdk_lvs_opts *o, uint32_t total_clusters,
     666                 :            :                void *esnap_ctx)
     667                 :            : {
     668   [ +  +  #  # ]:        369 :         assert(o != NULL);
     669                 :        369 :         lvs_bs_opts_init(bs_opts);
     670   [ #  #  #  #  :        369 :         bs_opts->cluster_sz = o->cluster_sz;
             #  #  #  # ]
     671   [ #  #  #  #  :        369 :         bs_opts->clear_method = (enum bs_clear_method)o->clear_method;
             #  #  #  # ]
     672   [ #  #  #  #  :        369 :         bs_opts->num_md_pages = (o->num_md_pages_per_cluster_ratio * total_clusters) / 100;
          #  #  #  #  #  
                      # ]
     673   [ #  #  #  #  :        369 :         bs_opts->md_page_size = o->md_page_size;
             #  #  #  # ]
     674   [ #  #  #  #  :        369 :         bs_opts->esnap_bs_dev_create = o->esnap_bs_dev_create;
             #  #  #  # ]
     675   [ #  #  #  # ]:        369 :         bs_opts->esnap_ctx = esnap_ctx;
     676   [ -  +  #  # ]:        369 :         snprintf(bs_opts->bstype.bstype, sizeof(bs_opts->bstype.bstype), "LVOLSTORE");
     677                 :        369 : }
     678                 :            : 
     679                 :            : int
     680                 :        375 : spdk_lvs_init(struct spdk_bs_dev *bs_dev, struct spdk_lvs_opts *o,
     681                 :            :               spdk_lvs_op_with_handle_complete cb_fn, void *cb_arg)
     682                 :            : {
     683                 :            :         struct spdk_lvol_store *lvs;
     684                 :            :         struct spdk_lvs_with_handle_req *lvs_req;
     685                 :        375 :         struct spdk_bs_opts opts = {};
     686                 :        271 :         struct spdk_lvs_opts lvs_opts;
     687                 :            :         uint32_t total_clusters;
     688                 :            :         int rc, len;
     689                 :            : 
     690         [ +  + ]:        375 :         if (bs_dev == NULL) {
     691                 :          4 :                 SPDK_ERRLOG("Blobstore device does not exist\n");
     692                 :          4 :                 return -ENODEV;
     693                 :            :         }
     694                 :            : 
     695         [ +  + ]:        371 :         if (o == NULL) {
     696                 :          0 :                 SPDK_ERRLOG("spdk_lvs_opts not specified\n");
     697                 :          0 :                 return -EINVAL;
     698                 :            :         }
     699                 :            : 
     700                 :        371 :         spdk_lvs_opts_init(&lvs_opts);
     701         [ -  + ]:        371 :         if (lvs_opts_copy(o, &lvs_opts) != 0) {
     702                 :          0 :                 SPDK_ERRLOG("spdk_lvs_opts invalid\n");
     703                 :          0 :                 return -EINVAL;
     704                 :            :         }
     705                 :            : 
     706   [ +  +  -  +  :        371 :         if (lvs_opts.cluster_sz < bs_dev->blocklen || (lvs_opts.cluster_sz % bs_dev->blocklen) != 0) {
          +  +  #  #  #  
             #  #  #  #  
                      # ]
     707   [ #  #  #  # ]:          2 :                 SPDK_ERRLOG("Cluster size %" PRIu32 " is smaller than blocklen %" PRIu32
     708                 :            :                             "Or not an integral multiple\n", lvs_opts.cluster_sz, bs_dev->blocklen);
     709                 :          2 :                 return -EINVAL;
     710                 :            :         }
     711   [ -  +  -  +  :        369 :         total_clusters = bs_dev->blockcnt / (lvs_opts.cluster_sz / bs_dev->blocklen);
          #  #  #  #  #  
                #  #  # ]
     712                 :            : 
     713                 :        369 :         lvs = lvs_alloc();
     714         [ +  + ]:        369 :         if (!lvs) {
     715                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol store base pointer\n");
     716                 :          0 :                 return -ENOMEM;
     717                 :            :         }
     718                 :            : 
     719                 :        369 :         setup_lvs_opts(&opts, o, total_clusters, lvs);
     720                 :            : 
     721         [ #  # ]:        369 :         len = strnlen(lvs_opts.name, SPDK_LVS_NAME_MAX);
     722   [ +  +  +  + ]:        369 :         if (len == 0 || len == SPDK_LVS_NAME_MAX) {
     723                 :          8 :                 SPDK_ERRLOG("Name must be between 1 and %d characters\n", SPDK_LVS_NAME_MAX - 1);
     724                 :          8 :                 lvs_free(lvs);
     725                 :          8 :                 return -EINVAL;
     726                 :            :         }
     727                 :            : 
     728         [ #  # ]:        361 :         spdk_uuid_generate(&lvs->uuid);
     729         [ #  # ]:        361 :         snprintf(lvs->name, sizeof(lvs->name), "%s", lvs_opts.name);
     730                 :            : 
     731                 :        361 :         rc = add_lvs_to_list(lvs);
     732         [ +  + ]:        361 :         if (rc) {
     733         [ #  # ]:          5 :                 SPDK_ERRLOG("lvolstore with name %s already exists\n", lvs->name);
     734                 :          5 :                 lvs_free(lvs);
     735                 :          5 :                 return -EEXIST;
     736                 :            :         }
     737                 :            : 
     738                 :        356 :         lvs_req = calloc(1, sizeof(*lvs_req));
     739         [ +  + ]:        356 :         if (!lvs_req) {
     740                 :          0 :                 lvs_free(lvs);
     741                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol store request pointer\n");
     742                 :          0 :                 return -ENOMEM;
     743                 :            :         }
     744                 :            : 
     745   [ -  +  #  # ]:        356 :         assert(cb_fn != NULL);
     746   [ #  #  #  # ]:        356 :         lvs_req->cb_fn = cb_fn;
     747   [ #  #  #  # ]:        356 :         lvs_req->cb_arg = cb_arg;
     748   [ #  #  #  # ]:        356 :         lvs_req->lvol_store = lvs;
     749   [ #  #  #  # ]:        356 :         lvs->bs_dev = bs_dev;
     750                 :            : 
     751   [ +  +  -  +  :        356 :         SPDK_INFOLOG(lvol, "Initializing lvol store\n");
                   #  # ]
     752                 :        356 :         spdk_bs_init(bs_dev, &opts, lvs_init_cb, lvs_req);
     753                 :            : 
     754                 :        356 :         return 0;
     755                 :         54 : }
     756                 :            : 
     757                 :            : static void
     758                 :          9 : lvs_rename_cb(void *cb_arg, int lvolerrno)
     759                 :            : {
     760                 :          9 :         struct spdk_lvs_req *req = cb_arg;
     761                 :            : 
     762         [ +  + ]:          9 :         if (lvolerrno != 0) {
     763   [ #  #  #  # ]:          4 :                 req->lvserrno = lvolerrno;
     764                 :          1 :         }
     765   [ +  +  #  #  :          9 :         if (req->lvserrno != 0) {
                   #  # ]
     766                 :          4 :                 SPDK_ERRLOG("Lvol store rename operation failed\n");
     767                 :            :                 /* Lvs renaming failed, so we should 'clear' new_name.
     768                 :            :                  * Otherwise it could cause a failure on the next attempt to change the name to 'new_name'  */
     769   [ -  +  #  #  :          5 :                 snprintf(req->lvol_store->new_name,
                   #  # ]
     770                 :            :                          sizeof(req->lvol_store->new_name),
     771   [ #  #  #  #  :          4 :                          "%s", req->lvol_store->name);
                   #  # ]
     772                 :          1 :         } else {
     773                 :            :                 /* Update lvs name with new_name */
     774   [ -  +  #  #  :          6 :                 snprintf(req->lvol_store->name,
                   #  # ]
     775                 :            :                          sizeof(req->lvol_store->name),
     776   [ #  #  #  #  :          5 :                          "%s", req->lvol_store->new_name);
                   #  # ]
     777                 :            :         }
     778                 :            : 
     779   [ #  #  #  #  :          9 :         req->cb_fn(req->cb_arg, req->lvserrno);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     780                 :          9 :         free(req);
     781                 :          9 : }
     782                 :            : 
     783                 :            : static void
     784                 :          5 : lvs_rename_sync_cb(void *cb_arg, int lvolerrno)
     785                 :            : {
     786                 :          5 :         struct spdk_lvs_req *req = cb_arg;
     787   [ #  #  #  #  :          5 :         struct spdk_blob *blob = req->lvol_store->super_blob;
             #  #  #  # ]
     788                 :            : 
     789         [ -  + ]:          5 :         if (lvolerrno < 0) {
     790   [ #  #  #  # ]:          0 :                 req->lvserrno = lvolerrno;
     791                 :          0 :         }
     792                 :            : 
     793                 :          5 :         spdk_blob_close(blob, lvs_rename_cb, req);
     794                 :          5 : }
     795                 :            : 
     796                 :            : static void
     797                 :          9 : lvs_rename_open_cb(void *cb_arg, struct spdk_blob *blob, int lvolerrno)
     798                 :            : {
     799                 :          9 :         struct spdk_lvs_req *req = cb_arg;
     800                 :            :         int rc;
     801                 :            : 
     802         [ +  + ]:          9 :         if (lvolerrno < 0) {
     803                 :          4 :                 lvs_rename_cb(cb_arg, lvolerrno);
     804                 :          4 :                 return;
     805                 :            :         }
     806                 :            : 
     807   [ #  #  #  #  :          6 :         rc = spdk_blob_set_xattr(blob, "name", req->lvol_store->new_name,
                   #  # ]
     808   [ -  +  #  #  :          5 :                                  strlen(req->lvol_store->new_name) + 1);
             #  #  #  # ]
     809         [ -  + ]:          5 :         if (rc < 0) {
     810   [ #  #  #  # ]:          0 :                 req->lvserrno = rc;
     811                 :          0 :                 lvs_rename_sync_cb(req, rc);
     812                 :          0 :                 return;
     813                 :            :         }
     814                 :            : 
     815   [ #  #  #  #  :          5 :         req->lvol_store->super_blob = blob;
             #  #  #  # ]
     816                 :            : 
     817                 :          5 :         spdk_blob_sync_md(blob, lvs_rename_sync_cb, req);
     818                 :          2 : }
     819                 :            : 
     820                 :            : void
     821                 :         22 : spdk_lvs_rename(struct spdk_lvol_store *lvs, const char *new_name,
     822                 :            :                 spdk_lvs_op_complete cb_fn, void *cb_arg)
     823                 :            : {
     824                 :            :         struct spdk_lvs_req *req;
     825                 :            :         struct spdk_lvol_store *tmp;
     826                 :            : 
     827                 :            :         /* Check if new name is current lvs name.
     828                 :            :          * If so, return success immediately */
     829   [ +  +  -  +  :         22 :         if (strncmp(lvs->name, new_name, SPDK_LVS_NAME_MAX) == 0) {
             +  +  #  # ]
     830   [ #  #  #  # ]:          4 :                 cb_fn(cb_arg, 0);
     831                 :          4 :                 return;
     832                 :            :         }
     833                 :            : 
     834                 :            :         /* Check if new or new_name is already used in other lvs */
     835         [ #  # ]:         18 :         pthread_mutex_lock(&g_lvol_stores_mutex);
     836   [ +  +  #  #  :         40 :         TAILQ_FOREACH(tmp, &g_lvol_stores, link) {
             #  #  #  # ]
     837   [ +  +  +  +  :         31 :                 if (!strncmp(new_name, tmp->name, SPDK_LVS_NAME_MAX) ||
          +  +  #  #  #  
                      # ]
     838   [ +  +  -  +  :         26 :                     !strncmp(new_name, tmp->new_name, SPDK_LVS_NAME_MAX)) {
                   +  + ]
     839         [ #  # ]:          9 :                         pthread_mutex_unlock(&g_lvol_stores_mutex);
     840   [ #  #  #  # ]:          9 :                         cb_fn(cb_arg, -EEXIST);
     841                 :          9 :                         return;
     842                 :            :                 }
     843                 :          5 :         }
     844         [ #  # ]:          9 :         pthread_mutex_unlock(&g_lvol_stores_mutex);
     845                 :            : 
     846                 :          9 :         req = calloc(1, sizeof(*req));
     847         [ -  + ]:          9 :         if (!req) {
     848                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
     849   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, -ENOMEM);
     850                 :          0 :                 return;
     851                 :            :         }
     852         [ #  # ]:          9 :         snprintf(lvs->new_name, sizeof(lvs->new_name), "%s", new_name);
     853   [ #  #  #  # ]:          9 :         req->lvol_store = lvs;
     854   [ #  #  #  # ]:          9 :         req->cb_fn = cb_fn;
     855   [ #  #  #  # ]:          9 :         req->cb_arg = cb_arg;
     856                 :            : 
     857   [ #  #  #  #  :          9 :         spdk_bs_open_blob(lvs->blobstore, lvs->super_blob_id, lvs_rename_open_cb, req);
             #  #  #  # ]
     858                 :          5 : }
     859                 :            : 
     860                 :            : static void
     861                 :        225 : _lvs_unload_cb(void *cb_arg, int lvserrno)
     862                 :            : {
     863                 :        225 :         struct spdk_lvs_req *lvs_req = cb_arg;
     864                 :            : 
     865   [ +  +  -  +  :        225 :         SPDK_INFOLOG(lvol, "Lvol store unloaded\n");
                   #  # ]
     866   [ +  +  #  #  :        225 :         assert(lvs_req->cb_fn != NULL);
             #  #  #  # ]
     867   [ #  #  #  #  :        225 :         lvs_req->cb_fn(lvs_req->cb_arg, lvserrno);
          #  #  #  #  #  
                #  #  # ]
     868                 :        225 :         free(lvs_req);
     869                 :        225 : }
     870                 :            : 
     871                 :            : int
     872                 :        233 : spdk_lvs_unload(struct spdk_lvol_store *lvs, spdk_lvs_op_complete cb_fn,
     873                 :            :                 void *cb_arg)
     874                 :            : {
     875                 :            :         struct spdk_lvs_req *lvs_req;
     876                 :            :         struct spdk_lvol *lvol, *tmp;
     877                 :            : 
     878         [ +  + ]:        233 :         if (lvs == NULL) {
     879                 :          4 :                 SPDK_ERRLOG("Lvol store is NULL\n");
     880                 :          4 :                 return -ENODEV;
     881                 :            :         }
     882                 :            : 
     883   [ +  +  +  +  :        476 :         TAILQ_FOREACH_SAFE(lvol, &lvs->lvols, link, tmp) {
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     884   [ +  +  -  +  :        251 :                 if (lvol->action_in_progress == true) {
             #  #  #  # ]
     885                 :          0 :                         SPDK_ERRLOG("Cannot unload lvol store - operations on lvols pending\n");
     886   [ #  #  #  # ]:          0 :                         cb_fn(cb_arg, -EBUSY);
     887                 :          0 :                         return -EBUSY;
     888   [ +  +  #  #  :        251 :                 } else if (lvol->ref_count != 0) {
                   #  # ]
     889                 :          4 :                         SPDK_ERRLOG("Lvols still open on lvol store\n");
     890   [ #  #  #  # ]:          4 :                         cb_fn(cb_arg, -EBUSY);
     891                 :          4 :                         return -EBUSY;
     892                 :            :                 }
     893                 :         28 :         }
     894                 :            : 
     895   [ +  +  +  +  :        472 :         TAILQ_FOREACH_SAFE(lvol, &lvs->lvols, link, tmp) {
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     896                 :        247 :                 spdk_lvs_esnap_missing_remove(lvol);
     897   [ +  +  #  #  :        247 :                 TAILQ_REMOVE(&lvs->lvols, lvol, link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
     898                 :        247 :                 lvol_free(lvol);
     899                 :         28 :         }
     900                 :            : 
     901                 :        225 :         lvs_req = calloc(1, sizeof(*lvs_req));
     902         [ +  + ]:        225 :         if (!lvs_req) {
     903                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol store request pointer\n");
     904                 :          0 :                 return -ENOMEM;
     905                 :            :         }
     906                 :            : 
     907   [ #  #  #  # ]:        225 :         lvs_req->cb_fn = cb_fn;
     908   [ #  #  #  # ]:        225 :         lvs_req->cb_arg = cb_arg;
     909                 :            : 
     910   [ -  +  -  +  :        225 :         SPDK_INFOLOG(lvol, "Unloading lvol store\n");
                   #  # ]
     911   [ #  #  #  # ]:        225 :         spdk_bs_unload(lvs->blobstore, _lvs_unload_cb, lvs_req);
     912                 :        225 :         lvs_free(lvs);
     913                 :            : 
     914                 :        225 :         return 0;
     915                 :         30 : }
     916                 :            : 
     917                 :            : static void
     918                 :        225 : _lvs_destroy_cb(void *cb_arg, int lvserrno)
     919                 :            : {
     920                 :        225 :         struct spdk_lvs_destroy_req *lvs_req = cb_arg;
     921                 :            : 
     922   [ +  +  -  +  :        225 :         SPDK_INFOLOG(lvol, "Lvol store destroyed\n");
                   #  # ]
     923   [ +  +  #  #  :        225 :         assert(lvs_req->cb_fn != NULL);
             #  #  #  # ]
     924   [ #  #  #  #  :        225 :         lvs_req->cb_fn(lvs_req->cb_arg, lvserrno);
          #  #  #  #  #  
                #  #  # ]
     925                 :        225 :         free(lvs_req);
     926                 :        225 : }
     927                 :            : 
     928                 :            : static void
     929                 :        225 : _lvs_destroy_super_cb(void *cb_arg, int bserrno)
     930                 :            : {
     931                 :        225 :         struct spdk_lvs_destroy_req *lvs_req = cb_arg;
     932   [ #  #  #  # ]:        225 :         struct spdk_lvol_store *lvs = lvs_req->lvs;
     933                 :            : 
     934   [ +  +  #  # ]:        225 :         assert(lvs != NULL);
     935                 :            : 
     936   [ +  +  -  +  :        225 :         SPDK_INFOLOG(lvol, "Destroying lvol store\n");
                   #  # ]
     937   [ #  #  #  # ]:        225 :         spdk_bs_destroy(lvs->blobstore, _lvs_destroy_cb, lvs_req);
     938                 :        225 :         lvs_free(lvs);
     939                 :        225 : }
     940                 :            : 
     941                 :            : int
     942                 :        229 : spdk_lvs_destroy(struct spdk_lvol_store *lvs, spdk_lvs_op_complete cb_fn,
     943                 :            :                  void *cb_arg)
     944                 :            : {
     945                 :            :         struct spdk_lvs_destroy_req *lvs_req;
     946                 :            :         struct spdk_lvol *iter_lvol, *tmp;
     947                 :            : 
     948         [ +  + ]:        229 :         if (lvs == NULL) {
     949                 :          0 :                 SPDK_ERRLOG("Lvol store is NULL\n");
     950                 :          0 :                 return -ENODEV;
     951                 :            :         }
     952                 :            : 
     953   [ +  +  +  +  :        241 :         TAILQ_FOREACH_SAFE(iter_lvol, &lvs->lvols, link, tmp) {
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     954   [ +  +  -  +  :         16 :                 if (iter_lvol->action_in_progress == true) {
             #  #  #  # ]
     955                 :          0 :                         SPDK_ERRLOG("Cannot destroy lvol store - operations on lvols pending\n");
     956   [ #  #  #  # ]:          0 :                         cb_fn(cb_arg, -EBUSY);
     957                 :          0 :                         return -EBUSY;
     958   [ +  +  #  #  :         16 :                 } else if (iter_lvol->ref_count != 0) {
                   #  # ]
     959                 :          4 :                         SPDK_ERRLOG("Lvols still open on lvol store\n");
     960   [ #  #  #  # ]:          4 :                         cb_fn(cb_arg, -EBUSY);
     961                 :          4 :                         return -EBUSY;
     962                 :            :                 }
     963                 :          3 :         }
     964                 :            : 
     965   [ +  +  +  +  :        237 :         TAILQ_FOREACH_SAFE(iter_lvol, &lvs->lvols, link, tmp) {
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     966                 :         12 :                 free(iter_lvol);
     967                 :          3 :         }
     968                 :            : 
     969                 :        225 :         lvs_req = calloc(1, sizeof(*lvs_req));
     970         [ +  + ]:        225 :         if (!lvs_req) {
     971                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol store request pointer\n");
     972                 :          0 :                 return -ENOMEM;
     973                 :            :         }
     974                 :            : 
     975   [ #  #  #  # ]:        225 :         lvs_req->cb_fn = cb_fn;
     976   [ #  #  #  # ]:        225 :         lvs_req->cb_arg = cb_arg;
     977   [ #  #  #  # ]:        225 :         lvs_req->lvs = lvs;
     978                 :            : 
     979   [ -  +  -  +  :        225 :         SPDK_INFOLOG(lvol, "Deleting super blob\n");
                   #  # ]
     980   [ #  #  #  #  :        225 :         spdk_bs_delete_blob(lvs->blobstore, lvs->super_blob_id, _lvs_destroy_super_cb, lvs_req);
             #  #  #  # ]
     981                 :            : 
     982                 :        225 :         return 0;
     983                 :         30 : }
     984                 :            : 
     985                 :            : static void
     986                 :        749 : lvol_close_blob_cb(void *cb_arg, int lvolerrno)
     987                 :            : {
     988                 :        749 :         struct spdk_lvol_req *req = cb_arg;
     989   [ #  #  #  # ]:        749 :         struct spdk_lvol *lvol = req->lvol;
     990                 :            : 
     991         [ +  + ]:        749 :         if (lvolerrno < 0) {
     992                 :          4 :                 SPDK_ERRLOG("Could not close blob on lvol\n");
     993                 :          4 :                 goto end;
     994                 :            :         }
     995                 :            : 
     996   [ #  #  #  # ]:        745 :         lvol->ref_count--;
     997   [ #  #  #  # ]:        745 :         lvol->blob = NULL;
     998   [ +  +  +  -  :        745 :         SPDK_INFOLOG(lvol, "Lvol %s closed\n", lvol->unique_id);
             #  #  #  # ]
     999                 :            : 
    1000                 :        658 : end:
    1001   [ #  #  #  # ]:        749 :         lvol->action_in_progress = false;
    1002   [ #  #  #  #  :        749 :         req->cb_fn(req->cb_arg, lvolerrno);
          #  #  #  #  #  
                #  #  # ]
    1003                 :        749 :         free(req);
    1004                 :        749 : }
    1005                 :            : 
    1006                 :            : bool
    1007                 :         74 : spdk_lvol_deletable(struct spdk_lvol *lvol)
    1008                 :            : {
    1009                 :         74 :         size_t count = 0;
    1010                 :            : 
    1011   [ #  #  #  #  :         74 :         spdk_blob_get_clones(lvol->lvol_store->blobstore, lvol->blob_id, NULL, &count);
          #  #  #  #  #  
                #  #  # ]
    1012                 :         74 :         return (count == 0);
    1013                 :            : }
    1014                 :            : 
    1015                 :            : static void
    1016                 :        502 : lvol_delete_blob_cb(void *cb_arg, int lvolerrno)
    1017                 :            : {
    1018                 :        502 :         struct spdk_lvol_req *req = cb_arg;
    1019   [ #  #  #  # ]:        502 :         struct spdk_lvol *lvol = req->lvol;
    1020   [ #  #  #  # ]:        502 :         struct spdk_lvol *clone_lvol = req->clone_lvol;
    1021                 :            : 
    1022         [ +  + ]:        502 :         if (lvolerrno < 0) {
    1023                 :          4 :                 SPDK_ERRLOG("Could not remove blob on lvol gracefully - forced removal\n");
    1024                 :          1 :         } else {
    1025   [ +  +  -  +  :        498 :                 SPDK_INFOLOG(lvol, "Lvol %s deleted\n", lvol->unique_id);
             #  #  #  # ]
    1026                 :            :         }
    1027                 :            : 
    1028   [ +  +  #  #  :        502 :         if (lvol->degraded_set != NULL) {
                   #  # ]
    1029         [ +  + ]:         51 :                 if (clone_lvol != NULL) {
    1030                 :            :                         /*
    1031                 :            :                          * A degraded esnap clone that has a blob clone has been deleted. clone_lvol
    1032                 :            :                          * becomes an esnap clone and needs to be associated with the
    1033                 :            :                          * spdk_lvs_degraded_lvol_set.
    1034                 :            :                          */
    1035   [ #  #  #  # ]:          5 :                         struct spdk_lvs_degraded_lvol_set *degraded_set = lvol->degraded_set;
    1036                 :            : 
    1037                 :          5 :                         lvs_degraded_lvol_set_remove(degraded_set, lvol);
    1038                 :          5 :                         lvs_degraded_lvol_set_add(degraded_set, clone_lvol);
    1039                 :          1 :                 } else {
    1040                 :         46 :                         spdk_lvs_esnap_missing_remove(lvol);
    1041                 :            :                 }
    1042                 :         12 :         }
    1043                 :            : 
    1044   [ +  +  #  #  :        502 :         TAILQ_REMOVE(&lvol->lvol_store->lvols, lvol, link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    1045                 :        502 :         lvol_free(lvol);
    1046   [ #  #  #  #  :        502 :         req->cb_fn(req->cb_arg, lvolerrno);
          #  #  #  #  #  
                #  #  # ]
    1047                 :        502 :         free(req);
    1048                 :        502 : }
    1049                 :            : 
    1050                 :            : static void
    1051                 :        630 : lvol_create_open_cb(void *cb_arg, struct spdk_blob *blob, int lvolerrno)
    1052                 :            : {
    1053                 :        630 :         struct spdk_lvol_with_handle_req *req = cb_arg;
    1054   [ #  #  #  # ]:        630 :         struct spdk_lvol *lvol = req->lvol;
    1055                 :            : 
    1056   [ -  +  #  #  :        630 :         TAILQ_REMOVE(&req->lvol->lvol_store->pending_lvols, req->lvol, link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1057                 :            : 
    1058         [ +  + ]:        630 :         if (lvolerrno < 0) {
    1059                 :          0 :                 lvol_free(lvol);
    1060   [ #  #  #  #  :          0 :                 req->cb_fn(req->cb_arg, NULL, lvolerrno);
          #  #  #  #  #  
                #  #  # ]
    1061                 :          0 :                 free(req);
    1062                 :          0 :                 return;
    1063                 :            :         }
    1064                 :            : 
    1065   [ #  #  #  # ]:        630 :         lvol->blob = blob;
    1066   [ #  #  #  # ]:        630 :         lvol->blob_id = spdk_blob_get_id(blob);
    1067                 :            : 
    1068   [ #  #  #  #  :        630 :         TAILQ_INSERT_TAIL(&lvol->lvol_store->lvols, lvol, link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
    1069                 :            : 
    1070   [ #  #  #  # ]:        630 :         lvol->ref_count++;
    1071                 :            : 
    1072   [ +  +  #  #  :        630 :         assert(req->cb_fn != NULL);
             #  #  #  # ]
    1073   [ #  #  #  #  :        630 :         req->cb_fn(req->cb_arg, req->lvol, lvolerrno);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    1074                 :        630 :         free(req);
    1075                 :         79 : }
    1076                 :            : 
    1077                 :            : static void
    1078                 :        639 : lvol_create_cb(void *cb_arg, spdk_blob_id blobid, int lvolerrno)
    1079                 :            : {
    1080                 :        639 :         struct spdk_lvol_with_handle_req *req = cb_arg;
    1081                 :            :         struct spdk_blob_store *bs;
    1082                 :        432 :         struct spdk_blob_open_opts opts;
    1083                 :            : 
    1084         [ +  + ]:        639 :         if (lvolerrno < 0) {
    1085   [ -  +  #  #  :          9 :                 TAILQ_REMOVE(&req->lvol->lvol_store->pending_lvols, req->lvol, link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1086   [ #  #  #  # ]:          9 :                 lvol_free(req->lvol);
    1087   [ -  +  #  #  :          9 :                 assert(req->cb_fn != NULL);
             #  #  #  # ]
    1088   [ #  #  #  #  :          9 :                 req->cb_fn(req->cb_arg, NULL, lvolerrno);
          #  #  #  #  #  
                #  #  # ]
    1089                 :          9 :                 free(req);
    1090                 :          9 :                 return;
    1091                 :            :         }
    1092                 :            : 
    1093                 :        630 :         spdk_blob_open_opts_init(&opts, sizeof(opts));
    1094   [ #  #  #  #  :        630 :         opts.clear_method = req->lvol->clear_method;
             #  #  #  # ]
    1095                 :            :         /*
    1096                 :            :          * If the lvol that is being created is an esnap clone, the blobstore needs to be able to
    1097                 :            :          * pass the lvol to the esnap_bs_dev_create callback. In order for that to happen, we need
    1098                 :            :          * to pass it here.
    1099                 :            :          *
    1100                 :            :          * This does set ensap_ctx in cases where it's not needed, but we don't know that it's not
    1101                 :            :          * needed until after the blob is open. When the blob is not an esnap clone, a reference to
    1102                 :            :          * the value stored in opts.esnap_ctx is not retained by the blobstore.
    1103                 :            :          */
    1104   [ #  #  #  #  :        630 :         opts.esnap_ctx = req->lvol;
                   #  # ]
    1105   [ #  #  #  #  :        630 :         bs = req->lvol->lvol_store->blobstore;
          #  #  #  #  #  
                #  #  # ]
    1106                 :            : 
    1107   [ +  +  +  +  :        630 :         if (req->origlvol != NULL && req->origlvol->degraded_set != NULL) {
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    1108                 :            :                 /*
    1109                 :            :                  * A snapshot was created from a degraded esnap clone. The new snapshot is now a
    1110                 :            :                  * degraded esnap clone. The previous clone is now a regular clone of a blob. Update
    1111                 :            :                  * the set of directly-related clones to the missing external snapshot.
    1112                 :            :                  */
    1113   [ #  #  #  #  :          4 :                 struct spdk_lvs_degraded_lvol_set *degraded_set = req->origlvol->degraded_set;
             #  #  #  # ]
    1114                 :            : 
    1115   [ #  #  #  # ]:          4 :                 lvs_degraded_lvol_set_remove(degraded_set, req->origlvol);
    1116   [ #  #  #  # ]:          4 :                 lvs_degraded_lvol_set_add(degraded_set, req->lvol);
    1117                 :          1 :         }
    1118                 :            : 
    1119                 :        630 :         spdk_bs_open_blob_ext(bs, blobid, &opts, lvol_create_open_cb, req);
    1120                 :         80 : }
    1121                 :            : 
    1122                 :            : static void
    1123                 :        672 : lvol_get_xattr_value(void *xattr_ctx, const char *name,
    1124                 :            :                      const void **value, size_t *value_len)
    1125                 :            : {
    1126                 :        672 :         struct spdk_lvol *lvol = xattr_ctx;
    1127                 :            : 
    1128   [ +  +  +  +  :        672 :         if (!strcmp(LVOL_NAME, name)) {
                   #  # ]
    1129   [ #  #  #  # ]:        336 :                 *value = lvol->name;
    1130         [ #  # ]:        336 :                 *value_len = SPDK_LVOL_NAME_MAX;
    1131                 :        336 :                 return;
    1132                 :            :         }
    1133   [ +  +  +  +  :        336 :         if (!strcmp("uuid", name)) {
                   #  # ]
    1134   [ #  #  #  # ]:        332 :                 *value = lvol->uuid_str;
    1135         [ #  # ]:        332 :                 *value_len = sizeof(lvol->uuid_str);
    1136                 :        332 :                 return;
    1137                 :            :         }
    1138         [ #  # ]:          4 :         *value = NULL;
    1139         [ #  # ]:          4 :         *value_len = 0;
    1140                 :         10 : }
    1141                 :            : 
    1142                 :            : static int
    1143                 :        716 : lvs_verify_lvol_name(struct spdk_lvol_store *lvs, const char *name)
    1144                 :            : {
    1145                 :            :         struct spdk_lvol *tmp;
    1146                 :            : 
    1147   [ +  +  +  +  :        716 :         if (name == NULL || strnlen(name, SPDK_LVOL_NAME_MAX) == 0) {
                   +  + ]
    1148   [ +  +  -  +  :         28 :                 SPDK_INFOLOG(lvol, "lvol name not provided.\n");
                   #  # ]
    1149                 :         28 :                 return -EINVAL;
    1150                 :            :         }
    1151                 :            : 
    1152   [ +  +  +  + ]:        688 :         if (strnlen(name, SPDK_LVOL_NAME_MAX) == SPDK_LVOL_NAME_MAX) {
    1153                 :          8 :                 SPDK_ERRLOG("Name has no null terminator.\n");
    1154                 :          8 :                 return -EINVAL;
    1155                 :            :         }
    1156                 :            : 
    1157   [ +  +  #  #  :       2001 :         TAILQ_FOREACH(tmp, &lvs->lvols, link) {
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1158   [ +  +  -  +  :       1354 :                 if (!strncmp(name, tmp->name, SPDK_LVOL_NAME_MAX)) {
             +  +  #  # ]
    1159                 :         33 :                         SPDK_ERRLOG("lvol with name %s already exists\n", name);
    1160                 :         33 :                         return -EEXIST;
    1161                 :            :                 }
    1162                 :         50 :         }
    1163                 :            : 
    1164   [ +  +  #  #  :        647 :         TAILQ_FOREACH(tmp, &lvs->pending_lvols, link) {
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1165   [ +  +  -  +  :          4 :                 if (!strncmp(name, tmp->name, SPDK_LVOL_NAME_MAX)) {
             +  -  #  # ]
    1166                 :          4 :                         SPDK_ERRLOG("lvol with name %s is being already created\n", name);
    1167                 :          4 :                         return -EEXIST;
    1168                 :            :                 }
    1169                 :          0 :         }
    1170                 :            : 
    1171                 :        643 :         return 0;
    1172                 :         99 : }
    1173                 :            : 
    1174                 :            : int
    1175                 :        428 : spdk_lvol_create(struct spdk_lvol_store *lvs, const char *name, uint64_t sz,
    1176                 :            :                  bool thin_provision, enum lvol_clear_method clear_method, spdk_lvol_op_with_handle_complete cb_fn,
    1177                 :            :                  void *cb_arg)
    1178                 :            : {
    1179                 :            :         struct spdk_lvol_with_handle_req *req;
    1180                 :            :         struct spdk_blob_store *bs;
    1181                 :            :         struct spdk_lvol *lvol;
    1182                 :        271 :         struct spdk_blob_opts opts;
    1183                 :        428 :         char *xattr_names[] = {LVOL_NAME, "uuid"};
    1184                 :            :         int rc;
    1185                 :            : 
    1186         [ +  + ]:        428 :         if (lvs == NULL) {
    1187                 :          4 :                 SPDK_ERRLOG("lvol store does not exist\n");
    1188                 :          4 :                 return -EINVAL;
    1189                 :            :         }
    1190                 :            : 
    1191                 :        424 :         rc = lvs_verify_lvol_name(lvs, name);
    1192         [ +  + ]:        424 :         if (rc < 0) {
    1193                 :         29 :                 return rc;
    1194                 :            :         }
    1195                 :            : 
    1196   [ #  #  #  # ]:        395 :         bs = lvs->blobstore;
    1197                 :            : 
    1198                 :        395 :         req = calloc(1, sizeof(*req));
    1199         [ +  + ]:        395 :         if (!req) {
    1200                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
    1201                 :          0 :                 return -ENOMEM;
    1202                 :            :         }
    1203   [ #  #  #  # ]:        395 :         req->cb_fn = cb_fn;
    1204   [ #  #  #  # ]:        395 :         req->cb_arg = cb_arg;
    1205                 :            : 
    1206         [ #  # ]:        395 :         lvol = lvol_alloc(lvs, name, thin_provision, clear_method);
    1207         [ -  + ]:        395 :         if (!lvol) {
    1208                 :          0 :                 free(req);
    1209                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol base pointer\n");
    1210                 :          0 :                 return -ENOMEM;
    1211                 :            :         }
    1212                 :            : 
    1213   [ #  #  #  # ]:        395 :         req->lvol = lvol;
    1214                 :        395 :         spdk_blob_opts_init(&opts, sizeof(opts));
    1215   [ #  #  #  # ]:        395 :         opts.thin_provision = thin_provision;
    1216                 :        395 :         opts.num_clusters = spdk_divide_round_up(sz, spdk_bs_get_cluster_size(bs));
    1217   [ #  #  #  #  :        395 :         opts.clear_method = lvol->clear_method;
                   #  # ]
    1218   [ #  #  #  # ]:        395 :         opts.xattrs.count = SPDK_COUNTOF(xattr_names);
    1219   [ #  #  #  # ]:        395 :         opts.xattrs.names = xattr_names;
    1220   [ #  #  #  # ]:        395 :         opts.xattrs.ctx = lvol;
    1221   [ #  #  #  # ]:        395 :         opts.xattrs.get_value = lvol_get_xattr_value;
    1222                 :            : 
    1223   [ #  #  #  # ]:        395 :         spdk_bs_create_blob_ext(lvs->blobstore, &opts, lvol_create_cb, req);
    1224                 :            : 
    1225                 :        395 :         return 0;
    1226                 :         44 : }
    1227                 :            : 
    1228                 :            : int
    1229                 :        162 : spdk_lvol_create_esnap_clone(const void *esnap_id, uint32_t id_len, uint64_t size_bytes,
    1230                 :            :                              struct spdk_lvol_store *lvs, const char *clone_name,
    1231                 :            :                              spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg)
    1232                 :            : {
    1233                 :            :         struct spdk_lvol_with_handle_req *req;
    1234                 :            :         struct spdk_blob_store *bs;
    1235                 :            :         struct spdk_lvol *lvol;
    1236                 :        124 :         struct spdk_blob_opts opts;
    1237                 :            :         uint64_t cluster_sz;
    1238                 :        162 :         char *xattr_names[] = {LVOL_NAME, "uuid"};
    1239                 :            :         int rc;
    1240                 :            : 
    1241         [ +  + ]:        162 :         if (lvs == NULL) {
    1242                 :          4 :                 SPDK_ERRLOG("lvol store does not exist\n");
    1243                 :          4 :                 return -EINVAL;
    1244                 :            :         }
    1245                 :            : 
    1246                 :        158 :         rc = lvs_verify_lvol_name(lvs, clone_name);
    1247         [ +  + ]:        158 :         if (rc < 0) {
    1248                 :         20 :                 return rc;
    1249                 :            :         }
    1250                 :            : 
    1251   [ #  #  #  # ]:        138 :         bs = lvs->blobstore;
    1252                 :            : 
    1253                 :        138 :         cluster_sz = spdk_bs_get_cluster_size(bs);
    1254   [ +  +  +  + ]:        138 :         if ((size_bytes % cluster_sz) != 0) {
    1255         [ #  # ]:          4 :                 SPDK_ERRLOG("Cannot create '%s/%s': size %" PRIu64 " is not an integer multiple of "
    1256                 :            :                             "cluster size %" PRIu64 "\n", lvs->name, clone_name, size_bytes,
    1257                 :            :                             cluster_sz);
    1258                 :          4 :                 return -EINVAL;
    1259                 :            :         }
    1260                 :            : 
    1261                 :        134 :         req = calloc(1, sizeof(*req));
    1262         [ +  + ]:        134 :         if (!req) {
    1263                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
    1264                 :          0 :                 return -ENOMEM;
    1265                 :            :         }
    1266   [ #  #  #  # ]:        134 :         req->cb_fn = cb_fn;
    1267   [ #  #  #  # ]:        134 :         req->cb_arg = cb_arg;
    1268                 :            : 
    1269                 :        134 :         lvol = lvol_alloc(lvs, clone_name, true, LVOL_CLEAR_WITH_DEFAULT);
    1270         [ -  + ]:        134 :         if (!lvol) {
    1271                 :          0 :                 free(req);
    1272                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol base pointer\n");
    1273                 :          0 :                 return -ENOMEM;
    1274                 :            :         }
    1275   [ #  #  #  # ]:        134 :         req->lvol = lvol;
    1276                 :            : 
    1277                 :        134 :         spdk_blob_opts_init(&opts, sizeof(opts));
    1278         [ #  # ]:        134 :         opts.esnap_id = esnap_id;
    1279         [ #  # ]:        134 :         opts.esnap_id_len = id_len;
    1280         [ #  # ]:        134 :         opts.thin_provision = true;
    1281                 :        134 :         opts.num_clusters = spdk_divide_round_up(size_bytes, cluster_sz);
    1282   [ #  #  #  #  :        134 :         opts.clear_method = lvol->clear_method;
                   #  # ]
    1283   [ #  #  #  # ]:        134 :         opts.xattrs.count = SPDK_COUNTOF(xattr_names);
    1284   [ #  #  #  # ]:        134 :         opts.xattrs.names = xattr_names;
    1285   [ #  #  #  # ]:        134 :         opts.xattrs.ctx = lvol;
    1286   [ #  #  #  # ]:        134 :         opts.xattrs.get_value = lvol_get_xattr_value;
    1287                 :            : 
    1288   [ #  #  #  # ]:        134 :         spdk_bs_create_blob_ext(lvs->blobstore, &opts, lvol_create_cb, req);
    1289                 :            : 
    1290                 :        134 :         return 0;
    1291                 :         38 : }
    1292                 :            : 
    1293                 :            : void
    1294                 :         84 : spdk_lvol_create_snapshot(struct spdk_lvol *origlvol, const char *snapshot_name,
    1295                 :            :                           spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg)
    1296                 :            : {
    1297                 :            :         struct spdk_lvol_store *lvs;
    1298                 :            :         struct spdk_lvol *newlvol;
    1299                 :            :         struct spdk_blob *origblob;
    1300                 :            :         struct spdk_lvol_with_handle_req *req;
    1301                 :         65 :         struct spdk_blob_xattr_opts snapshot_xattrs;
    1302                 :         84 :         char *xattr_names[] = {LVOL_NAME, "uuid"};
    1303                 :            :         int rc;
    1304                 :            : 
    1305         [ +  + ]:         84 :         if (origlvol == NULL) {
    1306   [ +  +  -  +  :          4 :                 SPDK_INFOLOG(lvol, "Lvol not provided.\n");
                   #  # ]
    1307   [ #  #  #  # ]:          4 :                 cb_fn(cb_arg, NULL, -EINVAL);
    1308                 :          4 :                 return;
    1309                 :            :         }
    1310                 :            : 
    1311   [ #  #  #  # ]:         80 :         origblob = origlvol->blob;
    1312   [ #  #  #  # ]:         80 :         lvs = origlvol->lvol_store;
    1313         [ +  + ]:         80 :         if (lvs == NULL) {
    1314                 :          0 :                 SPDK_ERRLOG("lvol store does not exist\n");
    1315   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, NULL, -EINVAL);
    1316                 :          0 :                 return;
    1317                 :            :         }
    1318                 :            : 
    1319                 :         80 :         rc = lvs_verify_lvol_name(lvs, snapshot_name);
    1320         [ +  + ]:         80 :         if (rc < 0) {
    1321   [ #  #  #  # ]:         12 :                 cb_fn(cb_arg, NULL, rc);
    1322                 :         12 :                 return;
    1323                 :            :         }
    1324                 :            : 
    1325                 :         68 :         req = calloc(1, sizeof(*req));
    1326         [ +  + ]:         68 :         if (!req) {
    1327                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
    1328   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, NULL, -ENOMEM);
    1329                 :          0 :                 return;
    1330                 :            :         }
    1331                 :            : 
    1332   [ #  #  #  # ]:         76 :         newlvol = lvol_alloc(origlvol->lvol_store, snapshot_name, true,
    1333   [ #  #  #  # ]:         68 :                              (enum lvol_clear_method)origlvol->clear_method);
    1334         [ -  + ]:         68 :         if (!newlvol) {
    1335                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol base pointer\n");
    1336                 :          0 :                 free(req);
    1337   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, NULL, -ENOMEM);
    1338                 :          0 :                 return;
    1339                 :            :         }
    1340                 :            : 
    1341                 :         68 :         snapshot_xattrs.count = SPDK_COUNTOF(xattr_names);
    1342         [ #  # ]:         68 :         snapshot_xattrs.ctx = newlvol;
    1343         [ #  # ]:         68 :         snapshot_xattrs.names = xattr_names;
    1344         [ #  # ]:         68 :         snapshot_xattrs.get_value = lvol_get_xattr_value;
    1345   [ #  #  #  # ]:         68 :         req->lvol = newlvol;
    1346   [ #  #  #  # ]:         68 :         req->origlvol = origlvol;
    1347   [ #  #  #  # ]:         68 :         req->cb_fn = cb_fn;
    1348   [ #  #  #  # ]:         68 :         req->cb_arg = cb_arg;
    1349                 :            : 
    1350   [ #  #  #  # ]:         76 :         spdk_bs_create_snapshot(lvs->blobstore, spdk_blob_get_id(origblob), &snapshot_xattrs,
    1351                 :          8 :                                 lvol_create_cb, req);
    1352                 :         12 : }
    1353                 :            : 
    1354                 :            : void
    1355                 :         58 : spdk_lvol_create_clone(struct spdk_lvol *origlvol, const char *clone_name,
    1356                 :            :                        spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg)
    1357                 :            : {
    1358                 :            :         struct spdk_lvol *newlvol;
    1359                 :            :         struct spdk_lvol_with_handle_req *req;
    1360                 :            :         struct spdk_lvol_store *lvs;
    1361                 :            :         struct spdk_blob *origblob;
    1362                 :         42 :         struct spdk_blob_xattr_opts clone_xattrs;
    1363                 :         58 :         char *xattr_names[] = {LVOL_NAME, "uuid"};
    1364                 :            :         int rc;
    1365                 :            : 
    1366         [ +  + ]:         58 :         if (origlvol == NULL) {
    1367   [ +  +  -  +  :          4 :                 SPDK_INFOLOG(lvol, "Lvol not provided.\n");
                   #  # ]
    1368   [ #  #  #  # ]:          4 :                 cb_fn(cb_arg, NULL, -EINVAL);
    1369                 :          4 :                 return;
    1370                 :            :         }
    1371                 :            : 
    1372   [ #  #  #  # ]:         54 :         origblob = origlvol->blob;
    1373   [ #  #  #  # ]:         54 :         lvs = origlvol->lvol_store;
    1374         [ +  + ]:         54 :         if (lvs == NULL) {
    1375                 :          0 :                 SPDK_ERRLOG("lvol store does not exist\n");
    1376   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, NULL, -EINVAL);
    1377                 :          0 :                 return;
    1378                 :            :         }
    1379                 :            : 
    1380                 :         54 :         rc = lvs_verify_lvol_name(lvs, clone_name);
    1381         [ +  + ]:         54 :         if (rc < 0) {
    1382   [ #  #  #  # ]:         12 :                 cb_fn(cb_arg, NULL, rc);
    1383                 :         12 :                 return;
    1384                 :            :         }
    1385                 :            : 
    1386                 :         42 :         req = calloc(1, sizeof(*req));
    1387         [ +  + ]:         42 :         if (!req) {
    1388                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
    1389   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, NULL, -ENOMEM);
    1390                 :          0 :                 return;
    1391                 :            :         }
    1392                 :            : 
    1393   [ #  #  #  # ]:         42 :         newlvol = lvol_alloc(lvs, clone_name, true, (enum lvol_clear_method)origlvol->clear_method);
    1394         [ -  + ]:         42 :         if (!newlvol) {
    1395                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol base pointer\n");
    1396                 :          0 :                 free(req);
    1397   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, NULL, -ENOMEM);
    1398                 :          0 :                 return;
    1399                 :            :         }
    1400                 :            : 
    1401                 :         42 :         clone_xattrs.count = SPDK_COUNTOF(xattr_names);
    1402         [ #  # ]:         42 :         clone_xattrs.ctx = newlvol;
    1403         [ #  # ]:         42 :         clone_xattrs.names = xattr_names;
    1404         [ #  # ]:         42 :         clone_xattrs.get_value = lvol_get_xattr_value;
    1405   [ #  #  #  # ]:         42 :         req->lvol = newlvol;
    1406   [ #  #  #  # ]:         42 :         req->cb_fn = cb_fn;
    1407   [ #  #  #  # ]:         42 :         req->cb_arg = cb_arg;
    1408                 :            : 
    1409   [ #  #  #  # ]:         47 :         spdk_bs_create_clone(lvs->blobstore, spdk_blob_get_id(origblob), &clone_xattrs,
    1410                 :            :                              lvol_create_cb,
    1411                 :          5 :                              req);
    1412                 :          9 : }
    1413                 :            : 
    1414                 :            : static void
    1415                 :         39 : lvol_resize_done(void *cb_arg, int lvolerrno)
    1416                 :            : {
    1417                 :         39 :         struct spdk_lvol_req *req = cb_arg;
    1418                 :            : 
    1419   [ #  #  #  #  :         39 :         req->cb_fn(req->cb_arg,  lvolerrno);
          #  #  #  #  #  
                #  #  # ]
    1420                 :         39 :         free(req);
    1421                 :         39 : }
    1422                 :            : 
    1423                 :            : static void
    1424                 :         48 : lvol_blob_resize_cb(void *cb_arg, int bserrno)
    1425                 :            : {
    1426                 :         48 :         struct spdk_lvol_req *req = cb_arg;
    1427   [ #  #  #  # ]:         48 :         struct spdk_lvol *lvol = req->lvol;
    1428                 :            : 
    1429         [ +  + ]:         48 :         if (bserrno != 0) {
    1430   [ #  #  #  #  :          9 :                 req->cb_fn(req->cb_arg, bserrno);
          #  #  #  #  #  
                #  #  # ]
    1431                 :          9 :                 free(req);
    1432                 :          9 :                 return;
    1433                 :            :         }
    1434                 :            : 
    1435   [ #  #  #  # ]:         39 :         spdk_blob_sync_md(lvol->blob, lvol_resize_done, req);
    1436                 :          6 : }
    1437                 :            : 
    1438                 :            : void
    1439                 :         48 : spdk_lvol_resize(struct spdk_lvol *lvol, uint64_t sz,
    1440                 :            :                  spdk_lvol_op_complete cb_fn, void *cb_arg)
    1441                 :            : {
    1442   [ #  #  #  # ]:         48 :         struct spdk_blob *blob = lvol->blob;
    1443   [ #  #  #  # ]:         48 :         struct spdk_lvol_store *lvs = lvol->lvol_store;
    1444                 :            :         struct spdk_lvol_req *req;
    1445   [ #  #  #  # ]:         48 :         uint64_t new_clusters = spdk_divide_round_up(sz, spdk_bs_get_cluster_size(lvs->blobstore));
    1446                 :            : 
    1447                 :         48 :         req = calloc(1, sizeof(*req));
    1448         [ -  + ]:         48 :         if (!req) {
    1449                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
    1450   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, -ENOMEM);
    1451                 :          0 :                 return;
    1452                 :            :         }
    1453   [ #  #  #  # ]:         48 :         req->cb_fn = cb_fn;
    1454   [ #  #  #  # ]:         48 :         req->cb_arg = cb_arg;
    1455   [ #  #  #  # ]:         48 :         req->lvol = lvol;
    1456                 :            : 
    1457                 :         48 :         spdk_blob_resize(blob, new_clusters, lvol_blob_resize_cb, req);
    1458                 :          6 : }
    1459                 :            : 
    1460                 :            : static void
    1461                 :          8 : lvol_set_read_only_cb(void *cb_arg, int lvolerrno)
    1462                 :            : {
    1463                 :          8 :         struct spdk_lvol_req *req = cb_arg;
    1464                 :            : 
    1465   [ #  #  #  #  :          8 :         req->cb_fn(req->cb_arg, lvolerrno);
          #  #  #  #  #  
                #  #  # ]
    1466                 :          8 :         free(req);
    1467                 :          8 : }
    1468                 :            : 
    1469                 :            : void
    1470                 :          8 : spdk_lvol_set_read_only(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_arg)
    1471                 :            : {
    1472                 :            :         struct spdk_lvol_req *req;
    1473                 :            : 
    1474                 :          8 :         req = calloc(1, sizeof(*req));
    1475         [ -  + ]:          8 :         if (!req) {
    1476                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
    1477   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, -ENOMEM);
    1478                 :          0 :                 return;
    1479                 :            :         }
    1480   [ #  #  #  # ]:          8 :         req->cb_fn = cb_fn;
    1481   [ #  #  #  # ]:          8 :         req->cb_arg = cb_arg;
    1482                 :            : 
    1483   [ #  #  #  # ]:          8 :         spdk_blob_set_read_only(lvol->blob);
    1484   [ #  #  #  # ]:          8 :         spdk_blob_sync_md(lvol->blob, lvol_set_read_only_cb, req);
    1485                 :          1 : }
    1486                 :            : 
    1487                 :            : static void
    1488                 :          8 : lvol_rename_cb(void *cb_arg, int lvolerrno)
    1489                 :            : {
    1490                 :          8 :         struct spdk_lvol_req *req = cb_arg;
    1491                 :            : 
    1492         [ -  + ]:          8 :         if (lvolerrno != 0) {
    1493                 :          0 :                 SPDK_ERRLOG("Lvol rename operation failed\n");
    1494                 :          0 :         } else {
    1495   [ -  +  #  #  :          8 :                 snprintf(req->lvol->name, sizeof(req->lvol->name), "%s", req->name);
             #  #  #  # ]
    1496                 :            :         }
    1497                 :            : 
    1498   [ #  #  #  #  :          8 :         req->cb_fn(req->cb_arg, lvolerrno);
          #  #  #  #  #  
                #  #  # ]
    1499                 :          8 :         free(req);
    1500                 :          8 : }
    1501                 :            : 
    1502                 :            : void
    1503                 :         12 : spdk_lvol_rename(struct spdk_lvol *lvol, const char *new_name,
    1504                 :            :                  spdk_lvol_op_complete cb_fn, void *cb_arg)
    1505                 :            : {
    1506                 :            :         struct spdk_lvol *tmp;
    1507   [ #  #  #  # ]:         12 :         struct spdk_blob *blob = lvol->blob;
    1508                 :            :         struct spdk_lvol_req *req;
    1509                 :            :         int rc;
    1510                 :            : 
    1511                 :            :         /* Check if new name is current lvol name.
    1512                 :            :          * If so, return success immediately */
    1513   [ +  +  -  +  :         12 :         if (strncmp(lvol->name, new_name, SPDK_LVOL_NAME_MAX) == 0) {
             -  +  #  # ]
    1514   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, 0);
    1515                 :          0 :                 return;
    1516                 :            :         }
    1517                 :            : 
    1518                 :            :         /* Check if lvol with 'new_name' already exists in lvolstore */
    1519   [ +  +  #  #  :         36 :         TAILQ_FOREACH(tmp, &lvol->lvol_store->lvols, link) {
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
    1520   [ +  +  -  +  :         28 :                 if (strncmp(tmp->name, new_name, SPDK_LVOL_NAME_MAX) == 0) {
             +  +  #  # ]
    1521   [ #  #  #  #  :          4 :                         SPDK_ERRLOG("Lvol %s already exists in lvol store %s\n", new_name, lvol->lvol_store->name);
                   #  # ]
    1522   [ #  #  #  # ]:          4 :                         cb_fn(cb_arg, -EEXIST);
    1523                 :          4 :                         return;
    1524                 :            :                 }
    1525                 :          2 :         }
    1526                 :            : 
    1527                 :          8 :         req = calloc(1, sizeof(*req));
    1528         [ +  + ]:          8 :         if (!req) {
    1529                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
    1530   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, -ENOMEM);
    1531                 :          0 :                 return;
    1532                 :            :         }
    1533   [ #  #  #  # ]:          8 :         req->cb_fn = cb_fn;
    1534   [ #  #  #  # ]:          8 :         req->cb_arg = cb_arg;
    1535   [ #  #  #  # ]:          8 :         req->lvol = lvol;
    1536         [ #  # ]:          8 :         snprintf(req->name, sizeof(req->name), "%s", new_name);
    1537                 :            : 
    1538         [ -  + ]:          8 :         rc = spdk_blob_set_xattr(blob, "name", new_name, strlen(new_name) + 1);
    1539         [ -  + ]:          8 :         if (rc < 0) {
    1540                 :          0 :                 free(req);
    1541   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, rc);
    1542                 :          0 :                 return;
    1543                 :            :         }
    1544                 :            : 
    1545                 :          8 :         spdk_blob_sync_md(blob, lvol_rename_cb, req);
    1546                 :          2 : }
    1547                 :            : 
    1548                 :            : void
    1549                 :        506 : spdk_lvol_destroy(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_arg)
    1550                 :            : {
    1551                 :            :         struct spdk_lvol_req *req;
    1552                 :            :         struct spdk_blob_store *bs;
    1553                 :            :         struct spdk_lvol_store  *lvs;
    1554                 :        335 :         spdk_blob_id    clone_id;
    1555                 :        506 :         size_t          count = 1;
    1556                 :            :         int             rc;
    1557                 :            : 
    1558   [ +  +  #  # ]:        506 :         assert(cb_fn != NULL);
    1559                 :            : 
    1560         [ +  + ]:        506 :         if (lvol == NULL) {
    1561                 :          0 :                 SPDK_ERRLOG("lvol does not exist\n");
    1562   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, -ENODEV);
    1563                 :          0 :                 return;
    1564                 :            :         }
    1565                 :            : 
    1566   [ #  #  #  # ]:        506 :         lvs = lvol->lvol_store;
    1567                 :            : 
    1568   [ +  +  #  #  :        506 :         if (lvol->ref_count != 0) {
                   #  # ]
    1569         [ #  # ]:          4 :                 SPDK_ERRLOG("Cannot destroy lvol %s because it is still open\n", lvol->unique_id);
    1570   [ #  #  #  # ]:          4 :                 cb_fn(cb_arg, -EBUSY);
    1571                 :          4 :                 return;
    1572                 :            :         }
    1573                 :            : 
    1574                 :        502 :         req = calloc(1, sizeof(*req));
    1575         [ +  + ]:        502 :         if (!req) {
    1576                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
    1577   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, -ENOMEM);
    1578                 :          0 :                 return;
    1579                 :            :         }
    1580                 :            : 
    1581   [ #  #  #  # ]:        502 :         req->cb_fn = cb_fn;
    1582   [ #  #  #  # ]:        502 :         req->cb_arg = cb_arg;
    1583   [ #  #  #  # ]:        502 :         req->lvol = lvol;
    1584   [ #  #  #  #  :        502 :         bs = lvol->lvol_store->blobstore;
             #  #  #  # ]
    1585                 :            : 
    1586   [ #  #  #  #  :        502 :         rc = spdk_blob_get_clones(lvs->blobstore, lvol->blob_id, &clone_id, &count);
             #  #  #  # ]
    1587   [ +  -  +  + ]:        502 :         if (rc == 0 && count == 1) {
    1588   [ #  #  #  # ]:         12 :                 req->clone_lvol = lvs_get_lvol_by_blob_id(lvs, clone_id);
    1589         [ -  + ]:        491 :         } else if (rc == -ENOMEM) {
    1590   [ #  #  #  #  :          0 :                 SPDK_INFOLOG(lvol, "lvol %s: cannot destroy: has %" PRIu64 " clones\n",
             #  #  #  # ]
    1591                 :            :                              lvol->unique_id, count);
    1592                 :          0 :                 free(req);
    1593   [ #  #  #  # ]:          0 :                 assert(count > 1);
    1594   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, -EBUSY);
    1595                 :          0 :                 return;
    1596                 :            :         }
    1597                 :            : 
    1598   [ #  #  #  # ]:        502 :         lvol->action_in_progress = true;
    1599                 :            : 
    1600   [ #  #  #  # ]:        502 :         spdk_bs_delete_blob(bs, lvol->blob_id, lvol_delete_blob_cb, req);
    1601                 :         61 : }
    1602                 :            : 
    1603                 :            : void
    1604                 :        765 : spdk_lvol_close(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_arg)
    1605                 :            : {
    1606                 :            :         struct spdk_lvol_req *req;
    1607                 :            : 
    1608   [ +  +  #  # ]:        765 :         assert(cb_fn != NULL);
    1609                 :            : 
    1610         [ +  + ]:        765 :         if (lvol == NULL) {
    1611                 :          4 :                 SPDK_ERRLOG("lvol does not exist\n");
    1612   [ #  #  #  # ]:          4 :                 cb_fn(cb_arg, -ENODEV);
    1613                 :          4 :                 return;
    1614                 :            :         }
    1615                 :            : 
    1616   [ +  +  #  #  :        761 :         if (lvol->ref_count > 1) {
                   #  # ]
    1617   [ #  #  #  # ]:          4 :                 lvol->ref_count--;
    1618   [ #  #  #  # ]:          4 :                 cb_fn(cb_arg, 0);
    1619                 :          4 :                 return;
    1620   [ +  +  #  #  :        757 :         } else if (lvol->ref_count == 0) {
                   #  # ]
    1621   [ #  #  #  # ]:          8 :                 cb_fn(cb_arg, -EINVAL);
    1622                 :          8 :                 return;
    1623                 :            :         }
    1624                 :            : 
    1625                 :        749 :         req = calloc(1, sizeof(*req));
    1626         [ +  + ]:        749 :         if (!req) {
    1627                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
    1628   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, -ENOMEM);
    1629                 :          0 :                 return;
    1630                 :            :         }
    1631                 :            : 
    1632   [ #  #  #  # ]:        749 :         req->cb_fn = cb_fn;
    1633   [ #  #  #  # ]:        749 :         req->cb_arg = cb_arg;
    1634   [ #  #  #  # ]:        749 :         req->lvol = lvol;
    1635                 :            : 
    1636   [ #  #  #  # ]:        749 :         lvol->action_in_progress = true;
    1637                 :            : 
    1638   [ #  #  #  # ]:        749 :         spdk_blob_close(lvol->blob, lvol_close_blob_cb, req);
    1639                 :         92 : }
    1640                 :            : 
    1641                 :            : struct spdk_io_channel *
    1642                 :        708 : spdk_lvol_get_io_channel(struct spdk_lvol *lvol)
    1643                 :            : {
    1644   [ #  #  #  #  :        708 :         return spdk_bs_alloc_io_channel(lvol->lvol_store->blobstore);
             #  #  #  # ]
    1645                 :            : }
    1646                 :            : 
    1647                 :            : static void
    1648                 :         26 : lvol_inflate_cb(void *cb_arg, int lvolerrno)
    1649                 :            : {
    1650                 :         26 :         struct spdk_lvol_req *req = cb_arg;
    1651                 :            : 
    1652   [ #  #  #  # ]:         26 :         spdk_bs_free_io_channel(req->channel);
    1653                 :            : 
    1654         [ +  + ]:         26 :         if (lvolerrno < 0) {
    1655                 :          9 :                 SPDK_ERRLOG("Could not inflate lvol\n");
    1656                 :          2 :         }
    1657                 :            : 
    1658   [ #  #  #  #  :         26 :         req->cb_fn(req->cb_arg, lvolerrno);
          #  #  #  #  #  
                #  #  # ]
    1659                 :         26 :         free(req);
    1660                 :         26 : }
    1661                 :            : 
    1662                 :            : void
    1663                 :         15 : spdk_lvol_inflate(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_arg)
    1664                 :            : {
    1665                 :            :         struct spdk_lvol_req *req;
    1666                 :            :         spdk_blob_id blob_id;
    1667                 :            : 
    1668   [ +  +  #  # ]:         15 :         assert(cb_fn != NULL);
    1669                 :            : 
    1670         [ +  + ]:         15 :         if (lvol == NULL) {
    1671                 :          0 :                 SPDK_ERRLOG("Lvol does not exist\n");
    1672   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, -ENODEV);
    1673                 :          0 :                 return;
    1674                 :            :         }
    1675                 :            : 
    1676                 :         15 :         req = calloc(1, sizeof(*req));
    1677         [ +  + ]:         15 :         if (!req) {
    1678                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
    1679   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, -ENOMEM);
    1680                 :          0 :                 return;
    1681                 :            :         }
    1682                 :            : 
    1683   [ #  #  #  # ]:         15 :         req->cb_fn = cb_fn;
    1684   [ #  #  #  # ]:         15 :         req->cb_arg = cb_arg;
    1685   [ #  #  #  #  :         15 :         req->channel = spdk_bs_alloc_io_channel(lvol->lvol_store->blobstore);
          #  #  #  #  #  
                #  #  # ]
    1686   [ +  +  #  #  :         15 :         if (req->channel == NULL) {
                   #  # ]
    1687                 :          0 :                 SPDK_ERRLOG("Cannot alloc io channel for lvol inflate request\n");
    1688                 :          0 :                 free(req);
    1689   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, -ENOMEM);
    1690                 :          0 :                 return;
    1691                 :            :         }
    1692                 :            : 
    1693   [ #  #  #  # ]:         15 :         blob_id = spdk_blob_get_id(lvol->blob);
    1694   [ #  #  #  #  :         17 :         spdk_bs_inflate_blob(lvol->lvol_store->blobstore, req->channel, blob_id, lvol_inflate_cb,
          #  #  #  #  #  
                #  #  # ]
    1695                 :          2 :                              req);
    1696                 :          2 : }
    1697                 :            : 
    1698                 :            : void
    1699                 :         11 : spdk_lvol_decouple_parent(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_arg)
    1700                 :            : {
    1701                 :            :         struct spdk_lvol_req *req;
    1702                 :            :         spdk_blob_id blob_id;
    1703                 :            : 
    1704   [ +  +  #  # ]:         11 :         assert(cb_fn != NULL);
    1705                 :            : 
    1706         [ +  + ]:         11 :         if (lvol == NULL) {
    1707                 :          0 :                 SPDK_ERRLOG("Lvol does not exist\n");
    1708   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, -ENODEV);
    1709                 :          0 :                 return;
    1710                 :            :         }
    1711                 :            : 
    1712                 :         11 :         req = calloc(1, sizeof(*req));
    1713         [ +  + ]:         11 :         if (!req) {
    1714                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
    1715   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, -ENOMEM);
    1716                 :          0 :                 return;
    1717                 :            :         }
    1718                 :            : 
    1719   [ #  #  #  # ]:         11 :         req->cb_fn = cb_fn;
    1720   [ #  #  #  # ]:         11 :         req->cb_arg = cb_arg;
    1721   [ #  #  #  #  :         11 :         req->channel = spdk_bs_alloc_io_channel(lvol->lvol_store->blobstore);
          #  #  #  #  #  
                #  #  # ]
    1722   [ +  +  #  #  :         11 :         if (req->channel == NULL) {
                   #  # ]
    1723                 :          0 :                 SPDK_ERRLOG("Cannot alloc io channel for lvol inflate request\n");
    1724                 :          0 :                 free(req);
    1725   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, -ENOMEM);
    1726                 :          0 :                 return;
    1727                 :            :         }
    1728                 :            : 
    1729   [ #  #  #  # ]:         11 :         blob_id = spdk_blob_get_id(lvol->blob);
    1730   [ #  #  #  #  :         13 :         spdk_bs_blob_decouple_parent(lvol->lvol_store->blobstore, req->channel, blob_id,
          #  #  #  #  #  
                #  #  # ]
    1731                 :          2 :                                      lvol_inflate_cb, req);
    1732                 :          2 : }
    1733                 :            : 
    1734                 :            : static void
    1735                 :          2 : lvs_grow_live_cb(void *cb_arg, int lvolerrno)
    1736                 :            : {
    1737                 :          2 :         struct spdk_lvs_req *req = (struct spdk_lvs_req *)cb_arg;
    1738                 :            : 
    1739   [ +  -  #  #  :          2 :         if (req->cb_fn) {
                   #  # ]
    1740   [ #  #  #  #  :          2 :                 req->cb_fn(req->cb_arg, lvolerrno);
          #  #  #  #  #  
                #  #  # ]
    1741                 :          0 :         }
    1742                 :          2 :         free(req);
    1743                 :          2 :         return;
    1744                 :            : }
    1745                 :            : 
    1746                 :            : void
    1747                 :          2 : spdk_lvs_grow_live(struct spdk_lvol_store *lvs, spdk_lvs_op_complete cb_fn, void *cb_arg)
    1748                 :            : {
    1749                 :            :         struct spdk_lvs_req *req;
    1750                 :            : 
    1751                 :          2 :         req = calloc(1, sizeof(*req));
    1752         [ -  + ]:          2 :         if (req == NULL) {
    1753                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for request structure\n");
    1754         [ #  # ]:          0 :                 if (cb_fn) {
    1755   [ #  #  #  # ]:          0 :                         cb_fn(cb_arg, -ENOMEM);
    1756                 :          0 :                 }
    1757                 :          0 :                 return;
    1758                 :            :         }
    1759                 :            : 
    1760   [ #  #  #  # ]:          2 :         req->cb_fn = cb_fn;
    1761   [ #  #  #  # ]:          2 :         req->cb_arg = cb_arg;
    1762   [ #  #  #  # ]:          2 :         req->lvol_store = lvs;
    1763                 :            : 
    1764   [ #  #  #  # ]:          2 :         spdk_bs_grow_live(lvs->blobstore, lvs_grow_live_cb, req);
    1765                 :          0 : }
    1766                 :            : 
    1767                 :            : void
    1768                 :          0 : spdk_lvs_grow(struct spdk_bs_dev *bs_dev, spdk_lvs_op_with_handle_complete cb_fn, void *cb_arg)
    1769                 :            : {
    1770                 :            :         struct spdk_lvs_with_handle_req *req;
    1771                 :          0 :         struct spdk_bs_opts opts = {};
    1772                 :            : 
    1773   [ #  #  #  # ]:          0 :         assert(cb_fn != NULL);
    1774                 :            : 
    1775         [ #  # ]:          0 :         if (bs_dev == NULL) {
    1776                 :          0 :                 SPDK_ERRLOG("Blobstore device does not exist\n");
    1777   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, NULL, -ENODEV);
    1778                 :          0 :                 return;
    1779                 :            :         }
    1780                 :            : 
    1781                 :          0 :         req = calloc(1, sizeof(*req));
    1782         [ #  # ]:          0 :         if (req == NULL) {
    1783                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for request structure\n");
    1784   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, NULL, -ENOMEM);
    1785                 :          0 :                 return;
    1786                 :            :         }
    1787                 :            : 
    1788   [ #  #  #  # ]:          0 :         req->lvol_store = lvs_alloc();
    1789   [ #  #  #  #  :          0 :         if (req->lvol_store == NULL) {
                   #  # ]
    1790                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol store\n");
    1791                 :          0 :                 free(req);
    1792   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, NULL, -ENOMEM);
    1793                 :          0 :                 return;
    1794                 :            :         }
    1795   [ #  #  #  # ]:          0 :         req->cb_fn = cb_fn;
    1796   [ #  #  #  # ]:          0 :         req->cb_arg = cb_arg;
    1797   [ #  #  #  # ]:          0 :         req->bs_dev = bs_dev;
    1798                 :            : 
    1799                 :          0 :         lvs_bs_opts_init(&opts);
    1800         [ #  # ]:          0 :         snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "LVOLSTORE");
    1801                 :            : 
    1802                 :          0 :         spdk_bs_grow(bs_dev, &opts, lvs_load_cb, req);
    1803                 :          0 : }
    1804                 :            : 
    1805                 :            : static struct spdk_lvol *
    1806                 :         48 : lvs_get_lvol_by_blob_id(struct spdk_lvol_store *lvs, spdk_blob_id blob_id)
    1807                 :            : {
    1808                 :            :         struct spdk_lvol *lvol;
    1809                 :            : 
    1810   [ +  -  #  #  :         66 :         TAILQ_FOREACH(lvol, &lvs->lvols, link) {
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1811   [ +  +  #  #  :         66 :                 if (lvol->blob_id == blob_id) {
                   #  # ]
    1812                 :         48 :                         return lvol;
    1813                 :            :                 }
    1814                 :          2 :         }
    1815                 :          0 :         return NULL;
    1816                 :          5 : }
    1817                 :            : 
    1818                 :            : static int
    1819                 :         92 : lvs_esnap_bs_dev_create(void *bs_ctx, void *blob_ctx, struct spdk_blob *blob,
    1820                 :            :                         const void *esnap_id, uint32_t id_len,
    1821                 :            :                         struct spdk_bs_dev **bs_dev)
    1822                 :            : {
    1823                 :         92 :         struct spdk_lvol_store  *lvs = bs_ctx;
    1824                 :         92 :         struct spdk_lvol        *lvol = blob_ctx;
    1825                 :         92 :         spdk_blob_id            blob_id = spdk_blob_get_id(blob);
    1826                 :            : 
    1827         [ +  + ]:         92 :         if (lvs == NULL) {
    1828   [ +  +  -  +  :          8 :                 if (lvol == NULL || lvol->lvol_store == NULL) {
             #  #  #  # ]
    1829                 :          4 :                         SPDK_ERRLOG("Blob 0x%" PRIx64 ": no lvs context nor lvol context\n",
    1830                 :            :                                     blob_id);
    1831                 :          4 :                         return -EINVAL;
    1832                 :            :                 }
    1833   [ #  #  #  # ]:          4 :                 lvs = lvol->lvol_store;
    1834                 :          1 :         }
    1835                 :            : 
    1836                 :            :         /*
    1837                 :            :          * When spdk_lvs_load() is called, it iterates through all blobs in its blobstore building
    1838                 :            :          * up a list of lvols (lvs->lvols). During this initial iteration, each blob is opened,
    1839                 :            :          * passed to load_next_lvol(), then closed. There is no need to open the external snapshot
    1840                 :            :          * during this phase. Once the blobstore is loaded, lvs->load_esnaps is set to true so that
    1841                 :            :          * future lvol opens cause the external snapshot to be loaded.
    1842                 :            :          */
    1843   [ +  +  +  +  :         88 :         if (!lvs->load_esnaps) {
             #  #  #  # ]
    1844         [ #  # ]:         60 :                 *bs_dev = NULL;
    1845                 :         60 :                 return 0;
    1846                 :            :         }
    1847                 :            : 
    1848         [ +  + ]:         28 :         if (lvol == NULL) {
    1849                 :         18 :                 spdk_blob_id blob_id = spdk_blob_get_id(blob);
    1850                 :            : 
    1851                 :            :                 /*
    1852                 :            :                  * If spdk_bs_blob_open() is used instead of spdk_bs_blob_open_ext() the lvol will
    1853                 :            :                  * not have been passed in. The same is true if the open happens spontaneously due
    1854                 :            :                  * to blobstore activity.
    1855                 :            :                  */
    1856                 :         18 :                 lvol = lvs_get_lvol_by_blob_id(lvs, blob_id);
    1857         [ -  + ]:         18 :                 if (lvol == NULL) {
    1858         [ #  # ]:          0 :                         SPDK_ERRLOG("lvstore %s: no lvol for blob 0x%" PRIx64 "\n",
    1859                 :            :                                     lvs->name, blob_id);
    1860                 :          0 :                         return -ENODEV;
    1861                 :            :                 }
    1862                 :          0 :         }
    1863                 :            : 
    1864   [ #  #  #  #  :         28 :         return lvs->esnap_bs_dev_create(lvs, lvol, blob, esnap_id, id_len, bs_dev);
             #  #  #  # ]
    1865                 :          6 : }
    1866                 :            : 
    1867                 :            : /*
    1868                 :            :  * The theory of missing external snapshots
    1869                 :            :  *
    1870                 :            :  * The lvs->esnap_bs_dev_create() callback may be unable to create an external snapshot bs_dev when
    1871                 :            :  * it is called. This can happen, for instance, as when the device containing the lvolstore is
    1872                 :            :  * examined prior to spdk_bdev_register() being called on a bdev that acts as an external snapshot.
    1873                 :            :  * In such a case, the esnap_bs_dev_create() callback will call spdk_lvs_esnap_missing_add().
    1874                 :            :  *
    1875                 :            :  * Missing external snapshots are tracked in a per-lvolstore tree, lvs->degraded_lvol_sets_tree.
    1876                 :            :  * Each tree node (struct spdk_lvs_degraded_lvol_set) contains a tailq of lvols that are missing
    1877                 :            :  * that particular external snapshot.
    1878                 :            :  *
    1879                 :            :  * When a potential missing snapshot becomes available, spdk_lvs_notify_hotplug() may be called to
    1880                 :            :  * notify this library that it is available. It will then iterate through the active lvolstores and
    1881                 :            :  * search each lvs->degraded_lvol_sets_tree for a set of degraded lvols that are missing an external
    1882                 :            :  * snapshot matching the id passed in the notification. The lvols in the tailq on each matching tree
    1883                 :            :  * node are then asked to create an external snapshot bs_dev using the esnap_bs_dev_create()
    1884                 :            :  * callback that the consumer registered with the lvolstore. If lvs->esnap_bs_dev_create() returns
    1885                 :            :  * 0, the lvol is removed from the spdk_lvs_degraded_lvol_set's lvol tailq. When this tailq becomes
    1886                 :            :  * empty, the degraded lvol set node for this missing external snapshot is removed.
    1887                 :            :  */
    1888                 :            : static int
    1889                 :        375 : lvs_esnap_name_cmp(struct spdk_lvs_degraded_lvol_set *m1, struct spdk_lvs_degraded_lvol_set *m2)
    1890                 :            : {
    1891   [ +  -  #  #  :        375 :         if (m1->id_len == m2->id_len) {
          #  #  #  #  #  
                      # ]
    1892   [ -  +  -  +  :        375 :                 return memcmp(m1->esnap_id, m2->esnap_id, m1->id_len);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    1893                 :            :         }
    1894   [ #  #  #  #  :          0 :         return (m1->id_len > m2->id_len) ? 1 : -1;
             #  #  #  # ]
    1895                 :         93 : }
    1896                 :            : 
    1897   [ +  +  +  +  :       1664 : RB_GENERATE_STATIC(degraded_lvol_sets_tree, spdk_lvs_degraded_lvol_set, node, lvs_esnap_name_cmp)
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  -  
          +  -  -  -  -  
          -  +  +  +  +  
          -  +  +  +  +  
          +  +  +  +  +  
          -  -  -  -  -  
          -  -  +  +  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  +  -  
          +  -  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          +  -  -  +  -  
          +  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  +  +  -  
          +  +  +  +  -  
          +  +  -  +  +  
          +  +  +  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
    1898                 :            : 
    1899                 :            : static void
    1900                 :        160 : lvs_degraded_lvol_set_add(struct spdk_lvs_degraded_lvol_set *degraded_set, struct spdk_lvol *lvol)
    1901                 :            : {
    1902   [ +  +  #  #  :        160 :         assert(lvol->lvol_store->thread == spdk_get_thread());
          #  #  #  #  #  
                #  #  # ]
    1903                 :            : 
    1904   [ #  #  #  # ]:        160 :         lvol->degraded_set = degraded_set;
    1905   [ #  #  #  #  :        160 :         TAILQ_INSERT_TAIL(&degraded_set->lvols, lvol, degraded_link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    1906                 :        160 : }
    1907                 :            : 
    1908                 :            : static void
    1909                 :         57 : lvs_degraded_lvol_set_remove(struct spdk_lvs_degraded_lvol_set *degraded_set,
    1910                 :            :                              struct spdk_lvol *lvol)
    1911                 :            : {
    1912   [ +  +  #  #  :         57 :         assert(lvol->lvol_store->thread == spdk_get_thread());
          #  #  #  #  #  
                #  #  # ]
    1913                 :            : 
    1914   [ #  #  #  # ]:         57 :         lvol->degraded_set = NULL;
    1915   [ +  +  #  #  :         57 :         TAILQ_REMOVE(&degraded_set->lvols, lvol, degraded_link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
    1916                 :            :         /* degraded_set->lvols may be empty. Caller should check if not immediately adding a new
    1917                 :            :          * lvol. */
    1918                 :         57 : }
    1919                 :            : 
    1920                 :            : /*
    1921                 :            :  * Record in lvs->degraded_lvol_sets_tree that a bdev of the specified name is needed by the
    1922                 :            :  * specified lvol.
    1923                 :            :  */
    1924                 :            : int
    1925                 :        151 : spdk_lvs_esnap_missing_add(struct spdk_lvol_store *lvs, struct spdk_lvol *lvol,
    1926                 :            :                            const void *esnap_id, uint32_t id_len)
    1927                 :            : {
    1928                 :        115 :         struct spdk_lvs_degraded_lvol_set find, *degraded_set;
    1929                 :            : 
    1930   [ +  +  #  #  :        151 :         assert(lvs->thread == spdk_get_thread());
             #  #  #  # ]
    1931                 :            : 
    1932         [ #  # ]:        151 :         find.esnap_id = esnap_id;
    1933         [ #  # ]:        151 :         find.id_len = id_len;
    1934         [ #  # ]:        151 :         degraded_set = RB_FIND(degraded_lvol_sets_tree, &lvs->degraded_lvol_sets_tree, &find);
    1935         [ +  + ]:        151 :         if (degraded_set == NULL) {
    1936                 :         71 :                 degraded_set = calloc(1, sizeof(*degraded_set));
    1937         [ +  + ]:         71 :                 if (degraded_set == NULL) {
    1938         [ #  # ]:          0 :                         SPDK_ERRLOG("lvol %s: cannot create degraded_set node: out of memory\n",
    1939                 :            :                                     lvol->unique_id);
    1940                 :          0 :                         return -ENOMEM;
    1941                 :            :                 }
    1942   [ #  #  #  # ]:         71 :                 degraded_set->esnap_id = calloc(1, id_len);
    1943   [ +  +  #  #  :         71 :                 if (degraded_set->esnap_id == NULL) {
                   #  # ]
    1944                 :          0 :                         free(degraded_set);
    1945         [ #  # ]:          0 :                         SPDK_ERRLOG("lvol %s: cannot create degraded_set node: out of memory\n",
    1946                 :            :                                     lvol->unique_id);
    1947                 :          0 :                         return -ENOMEM;
    1948                 :            :                 }
    1949   [ -  +  -  +  :         71 :                 memcpy((void *)degraded_set->esnap_id, esnap_id, id_len);
             #  #  #  # ]
    1950   [ #  #  #  # ]:         71 :                 degraded_set->id_len = id_len;
    1951   [ #  #  #  # ]:         71 :                 degraded_set->lvol_store = lvs;
    1952   [ #  #  #  #  :         71 :                 TAILQ_INIT(&degraded_set->lvols);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    1953         [ #  # ]:         71 :                 RB_INSERT(degraded_lvol_sets_tree, &lvs->degraded_lvol_sets_tree, degraded_set);
    1954                 :         16 :         }
    1955                 :            : 
    1956                 :        151 :         lvs_degraded_lvol_set_add(degraded_set, lvol);
    1957                 :            : 
    1958                 :        151 :         return 0;
    1959                 :         36 : }
    1960                 :            : 
    1961                 :            : /*
    1962                 :            :  * Remove the record of the specified lvol needing a degraded_set bdev.
    1963                 :            :  */
    1964                 :            : void
    1965                 :        293 : spdk_lvs_esnap_missing_remove(struct spdk_lvol *lvol)
    1966                 :            : {
    1967   [ #  #  #  # ]:        293 :         struct spdk_lvol_store          *lvs = lvol->lvol_store;
    1968   [ #  #  #  # ]:        293 :         struct spdk_lvs_degraded_lvol_set       *degraded_set = lvol->degraded_set;
    1969                 :            : 
    1970   [ +  +  #  #  :        293 :         assert(lvs->thread == spdk_get_thread());
             #  #  #  # ]
    1971                 :            : 
    1972         [ +  + ]:        293 :         if (degraded_set == NULL) {
    1973                 :        245 :                 return;
    1974                 :            :         }
    1975                 :            : 
    1976                 :         48 :         lvs_degraded_lvol_set_remove(degraded_set, lvol);
    1977                 :            : 
    1978   [ +  +  #  #  :         48 :         if (!TAILQ_EMPTY(&degraded_set->lvols)) {
             #  #  #  # ]
    1979                 :          4 :                 return;
    1980                 :            :         }
    1981                 :            : 
    1982         [ #  # ]:         44 :         RB_REMOVE(degraded_lvol_sets_tree, &lvs->degraded_lvol_sets_tree, degraded_set);
    1983                 :            : 
    1984   [ #  #  #  # ]:         44 :         free((char *)degraded_set->esnap_id);
    1985                 :         44 :         free(degraded_set);
    1986                 :         39 : }
    1987                 :            : 
    1988                 :            : struct lvs_esnap_hotplug_req {
    1989                 :            :         struct spdk_lvol                        *lvol;
    1990                 :            :         spdk_lvol_op_with_handle_complete       cb_fn;
    1991                 :            :         void                                    *cb_arg;
    1992                 :            : };
    1993                 :            : 
    1994                 :            : static void
    1995                 :        103 : lvs_esnap_hotplug_done(void *cb_arg, int bserrno)
    1996                 :            : {
    1997                 :        103 :         struct lvs_esnap_hotplug_req *req = cb_arg;
    1998   [ #  #  #  # ]:        103 :         struct spdk_lvol        *lvol = req->lvol;
    1999   [ #  #  #  # ]:        103 :         struct spdk_lvol_store  *lvs = lvol->lvol_store;
    2000                 :            : 
    2001         [ -  + ]:        103 :         if (bserrno != 0) {
    2002   [ #  #  #  # ]:          0 :                 SPDK_ERRLOG("lvol %s/%s: failed to hotplug blob_bdev due to error %d\n",
    2003                 :            :                             lvs->name, lvol->name, bserrno);
    2004                 :          0 :         }
    2005   [ #  #  #  #  :        103 :         req->cb_fn(req->cb_arg, lvol, bserrno);
          #  #  #  #  #  
                #  #  # ]
    2006                 :        103 :         free(req);
    2007                 :        103 : }
    2008                 :            : 
    2009                 :            : static void
    2010                 :         63 : lvs_esnap_degraded_hotplug(struct spdk_lvs_degraded_lvol_set *degraded_set,
    2011                 :            :                            spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg)
    2012                 :            : {
    2013   [ #  #  #  # ]:         63 :         struct spdk_lvol_store  *lvs = degraded_set->lvol_store;
    2014                 :            :         struct spdk_lvol        *lvol, *tmp, *last_missing;
    2015                 :         48 :         struct spdk_bs_dev      *bs_dev;
    2016   [ #  #  #  # ]:         63 :         const void              *esnap_id = degraded_set->esnap_id;
    2017   [ #  #  #  # ]:         63 :         uint32_t                id_len = degraded_set->id_len;
    2018                 :            :         struct lvs_esnap_hotplug_req *req;
    2019                 :            :         int                     rc;
    2020                 :            : 
    2021   [ +  +  #  #  :         63 :         assert(lvs->thread == spdk_get_thread());
             #  #  #  # ]
    2022                 :            : 
    2023                 :            :         /*
    2024                 :            :          * When lvs->esnap_bs_bdev_create() tries to load an external snapshot, it can encounter
    2025                 :            :          * errors that lead it to calling spdk_lvs_esnap_missing_add(). This function needs to be
    2026                 :            :          * sure that such modifications do not lead to degraded_set->lvols tailqs or references
    2027                 :            :          * to memory that this function will free.
    2028                 :            :          *
    2029                 :            :          * While this function is running, no other thread can add items to degraded_set->lvols. If
    2030                 :            :          * the list is mutated, it must have been done by this function or something in its call
    2031                 :            :          * graph running on this thread.
    2032                 :            :          */
    2033                 :            : 
    2034                 :            :         /* Remember the last lvol on the list. Iteration will stop once it has been processed. */
    2035   [ #  #  #  #  :         63 :         last_missing = TAILQ_LAST(&degraded_set->lvols, degraded_lvols);
          #  #  #  #  #  
                #  #  # ]
    2036                 :            : 
    2037   [ +  +  -  +  :        115 :         TAILQ_FOREACH_SAFE(lvol, &degraded_set->lvols, degraded_link, tmp) {
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    2038                 :        115 :                 req = calloc(1, sizeof(*req));
    2039         [ +  + ]:        115 :                 if (req == NULL) {
    2040         [ #  # ]:          0 :                         SPDK_ERRLOG("lvol %s: failed to create esnap bs_dev: out of memory\n",
    2041                 :            :                                     lvol->unique_id);
    2042   [ #  #  #  # ]:          0 :                         cb_fn(cb_arg, lvol, -ENOMEM);
    2043                 :            :                         /* The next one likely won't succeed either, but keep going so that all the
    2044                 :            :                          * failed hotplugs are logged.
    2045                 :            :                          */
    2046                 :          0 :                         goto next;
    2047                 :            :                 }
    2048                 :            : 
    2049                 :            :                 /*
    2050                 :            :                  * Remove the lvol from the tailq so that tailq corruption is avoided if
    2051                 :            :                  * lvs->esnap_bs_dev_create() calls spdk_lvs_esnap_missing_add(lvol).
    2052                 :            :                  */
    2053   [ +  +  #  #  :        115 :                 TAILQ_REMOVE(&degraded_set->lvols, lvol, degraded_link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
    2054   [ #  #  #  # ]:        115 :                 lvol->degraded_set = NULL;
    2055                 :            : 
    2056                 :        115 :                 bs_dev = NULL;
    2057   [ #  #  #  #  :        115 :                 rc = lvs->esnap_bs_dev_create(lvs, lvol, lvol->blob, esnap_id, id_len, &bs_dev);
          #  #  #  #  #  
                #  #  # ]
    2058         [ +  + ]:        115 :                 if (rc != 0) {
    2059         [ #  # ]:         12 :                         SPDK_ERRLOG("lvol %s: failed to create esnap bs_dev: error %d\n",
    2060                 :            :                                     lvol->unique_id, rc);
    2061   [ #  #  #  # ]:         12 :                         lvol->degraded_set = degraded_set;
    2062   [ #  #  #  #  :         12 :                         TAILQ_INSERT_TAIL(&degraded_set->lvols, lvol, degraded_link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    2063   [ #  #  #  # ]:         12 :                         cb_fn(cb_arg, lvol, rc);
    2064                 :         12 :                         free(req);
    2065                 :         12 :                         goto next;
    2066                 :            :                 }
    2067                 :            : 
    2068   [ #  #  #  # ]:        103 :                 req->lvol = lvol;
    2069   [ #  #  #  # ]:        103 :                 req->cb_fn = cb_fn;
    2070   [ #  #  #  # ]:        103 :                 req->cb_arg = cb_arg;
    2071   [ #  #  #  # ]:        103 :                 spdk_blob_set_esnap_bs_dev(lvol->blob, bs_dev, lvs_esnap_hotplug_done, req);
    2072                 :            : 
    2073                 :         87 : next:
    2074         [ +  + ]:        115 :                 if (lvol == last_missing) {
    2075                 :            :                         /*
    2076                 :            :                          * Anything after last_missing was added due to some problem encountered
    2077                 :            :                          * while trying to create the esnap bs_dev.
    2078                 :            :                          */
    2079                 :         63 :                         break;
    2080                 :            :                 }
    2081                 :         13 :         }
    2082                 :            : 
    2083   [ +  +  #  #  :         63 :         if (TAILQ_EMPTY(&degraded_set->lvols)) {
             #  #  #  # ]
    2084         [ #  # ]:         27 :                 RB_REMOVE(degraded_lvol_sets_tree, &lvs->degraded_lvol_sets_tree, degraded_set);
    2085   [ #  #  #  # ]:         27 :                 free((void *)degraded_set->esnap_id);
    2086                 :         27 :                 free(degraded_set);
    2087                 :          6 :         }
    2088                 :         63 : }
    2089                 :            : 
    2090                 :            : /*
    2091                 :            :  * Notify each lvstore created on this thread that is missing a bdev by the specified name or uuid
    2092                 :            :  * that the bdev now exists.
    2093                 :            :  */
    2094                 :            : bool
    2095                 :       5780 : spdk_lvs_notify_hotplug(const void *esnap_id, uint32_t id_len,
    2096                 :            :                         spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg)
    2097                 :            : {
    2098                 :            :         struct spdk_lvs_degraded_lvol_set *found;
    2099                 :       5780 :         struct spdk_lvs_degraded_lvol_set find = { 0 };
    2100                 :            :         struct spdk_lvol_store  *lvs;
    2101                 :       5780 :         struct spdk_thread      *thread = spdk_get_thread();
    2102                 :       5780 :         bool                    ret = false;
    2103                 :            : 
    2104         [ +  - ]:       5780 :         find.esnap_id = esnap_id;
    2105         [ +  - ]:       5780 :         find.id_len = id_len;
    2106                 :            : 
    2107         [ +  + ]:       5780 :         pthread_mutex_lock(&g_lvol_stores_mutex);
    2108   [ +  +  #  #  :       6485 :         TAILQ_FOREACH(lvs, &g_lvol_stores, link) {
             #  #  #  # ]
    2109   [ -  +  #  #  :        705 :                 if (thread != lvs->thread) {
                   #  # ]
    2110                 :            :                         /*
    2111                 :            :                          * It is expected that this is called from vbdev_lvol's examine_config()
    2112                 :            :                          * callback. The lvstore was likely loaded do a creation happening as a
    2113                 :            :                          * result of an RPC call or opening of an existing lvstore via
    2114                 :            :                          * examine_disk() callback. RPC calls, examine_disk(), and examine_config()
    2115                 :            :                          * should all be happening only on the app thread. The "wrong thread"
    2116                 :            :                          * condition will only happen when an application is doing something weird.
    2117                 :            :                          */
    2118         [ #  # ]:          0 :                         SPDK_NOTICELOG("Discarded examine for lvstore %s: wrong thread\n",
    2119                 :            :                                        lvs->name);
    2120                 :          0 :                         continue;
    2121                 :            :                 }
    2122                 :            : 
    2123         [ #  # ]:        705 :                 found = RB_FIND(degraded_lvol_sets_tree, &lvs->degraded_lvol_sets_tree, &find);
    2124         [ +  + ]:        705 :                 if (found == NULL) {
    2125                 :        642 :                         continue;
    2126                 :            :                 }
    2127                 :            : 
    2128                 :         63 :                 ret = true;
    2129                 :         63 :                 lvs_esnap_degraded_hotplug(found, cb_fn, cb_arg);
    2130                 :         15 :         }
    2131         [ +  + ]:       5780 :         pthread_mutex_unlock(&g_lvol_stores_mutex);
    2132                 :            : 
    2133         [ +  - ]:       5780 :         return ret;
    2134                 :            : }
    2135                 :            : 
    2136                 :            : int
    2137                 :         21 : spdk_lvol_iter_immediate_clones(struct spdk_lvol *lvol, spdk_lvol_iter_cb cb_fn, void *cb_arg)
    2138                 :            : {
    2139   [ #  #  #  # ]:         21 :         struct spdk_lvol_store *lvs = lvol->lvol_store;
    2140   [ #  #  #  # ]:         21 :         struct spdk_blob_store *bs = lvs->blobstore;
    2141                 :            :         struct spdk_lvol *clone;
    2142                 :            :         spdk_blob_id *ids;
    2143                 :         21 :         size_t id_cnt = 0;
    2144                 :            :         size_t i;
    2145                 :            :         int rc;
    2146                 :            : 
    2147   [ #  #  #  # ]:         21 :         rc = spdk_blob_get_clones(bs, lvol->blob_id, NULL, &id_cnt);
    2148         [ +  + ]:         21 :         if (rc != -ENOMEM) {
    2149                 :            :                 /* -ENOMEM says id_cnt is valid, no other errors should be returned. */
    2150   [ -  +  #  # ]:          7 :                 assert(rc == 0);
    2151                 :          7 :                 return rc;
    2152                 :            :         }
    2153                 :            : 
    2154                 :         14 :         ids = calloc(id_cnt, sizeof(*ids));
    2155         [ +  + ]:         14 :         if (ids == NULL) {
    2156         [ #  # ]:          0 :                 SPDK_ERRLOG("lvol %s: out of memory while iterating clones\n", lvol->unique_id);
    2157                 :          0 :                 return -ENOMEM;
    2158                 :            :         }
    2159                 :            : 
    2160   [ #  #  #  # ]:         14 :         rc = spdk_blob_get_clones(bs, lvol->blob_id, ids, &id_cnt);
    2161         [ -  + ]:         14 :         if (rc != 0) {
    2162         [ #  # ]:          0 :                 SPDK_ERRLOG("lvol %s: unable to get clone blob IDs: %d\n", lvol->unique_id, rc);
    2163                 :          0 :                 free(ids);
    2164                 :          0 :                 return rc;
    2165                 :            :         }
    2166                 :            : 
    2167         [ +  + ]:         28 :         for (i = 0; i < id_cnt; i++) {
    2168   [ #  #  #  # ]:         18 :                 clone = lvs_get_lvol_by_blob_id(lvs, ids[i]);
    2169         [ +  + ]:         18 :                 if (clone == NULL) {
    2170   [ #  #  #  #  :          0 :                         SPDK_NOTICELOG("lvol %s: unable to find clone lvol with blob id 0x%"
                   #  # ]
    2171                 :            :                                        PRIx64 "\n", lvol->unique_id, ids[i]);
    2172                 :          0 :                         continue;
    2173                 :            :                 }
    2174   [ #  #  #  # ]:         18 :                 rc = cb_fn(cb_arg, clone);
    2175         [ +  + ]:         18 :                 if (rc != 0) {
    2176   [ +  +  -  +  :          4 :                         SPDK_DEBUGLOG(lvol, "lvol %s: iteration stopped when lvol %s (blob 0x%"
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    2177                 :            :                                       PRIx64 ") returned %d\n", lvol->unique_id, clone->unique_id,
    2178                 :            :                                       ids[i], rc);
    2179                 :          4 :                         break;
    2180                 :            :                 }
    2181                 :          3 :         }
    2182                 :            : 
    2183                 :         14 :         free(ids);
    2184                 :         14 :         return rc;
    2185                 :          4 : }
    2186                 :            : 
    2187                 :            : struct spdk_lvol *
    2188                 :         10 : spdk_lvol_get_by_uuid(const struct spdk_uuid *uuid)
    2189                 :            : {
    2190                 :            :         struct spdk_lvol_store *lvs;
    2191                 :            :         struct spdk_lvol *lvol;
    2192                 :            : 
    2193         [ -  + ]:         10 :         pthread_mutex_lock(&g_lvol_stores_mutex);
    2194                 :            : 
    2195   [ +  +  #  #  :         10 :         TAILQ_FOREACH(lvs, &g_lvol_stores, link) {
             #  #  #  # ]
    2196   [ +  -  #  #  :         11 :                 TAILQ_FOREACH(lvol, &lvs->lvols, link) {
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    2197   [ +  +  #  # ]:         11 :                         if (spdk_uuid_compare(uuid, &lvol->uuid) == 0) {
    2198         [ -  + ]:         10 :                                 pthread_mutex_unlock(&g_lvol_stores_mutex);
    2199                 :         10 :                                 return lvol;
    2200                 :            :                         }
    2201                 :          0 :                 }
    2202                 :          0 :         }
    2203                 :            : 
    2204         [ #  # ]:          0 :         pthread_mutex_unlock(&g_lvol_stores_mutex);
    2205                 :          0 :         return NULL;
    2206                 :          2 : }
    2207                 :            : 
    2208                 :            : struct spdk_lvol *
    2209                 :        191 : spdk_lvol_get_by_names(const char *lvs_name, const char *lvol_name)
    2210                 :            : {
    2211                 :            :         struct spdk_lvol_store *lvs;
    2212                 :            :         struct spdk_lvol *lvol;
    2213                 :            : 
    2214         [ #  # ]:        191 :         pthread_mutex_lock(&g_lvol_stores_mutex);
    2215                 :            : 
    2216   [ +  +  #  #  :        265 :         TAILQ_FOREACH(lvs, &g_lvol_stores, link) {
             #  #  #  # ]
    2217   [ +  +  -  +  :        164 :                 if (strcmp(lvs_name, lvs->name) != 0) {
             +  +  #  # ]
    2218                 :         12 :                         continue;
    2219                 :            :                 }
    2220   [ +  +  #  #  :        179 :                 TAILQ_FOREACH(lvol, &lvs->lvols, link) {
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    2221   [ +  +  -  +  :        117 :                         if (strcmp(lvol_name, lvol->name) == 0) {
             +  +  #  # ]
    2222         [ #  # ]:         90 :                                 pthread_mutex_unlock(&g_lvol_stores_mutex);
    2223                 :         90 :                                 return lvol;
    2224                 :            :                         }
    2225                 :          5 :                 }
    2226                 :          2 :         }
    2227                 :            : 
    2228         [ #  # ]:        101 :         pthread_mutex_unlock(&g_lvol_stores_mutex);
    2229                 :        101 :         return NULL;
    2230                 :         12 : }
    2231                 :            : 
    2232                 :            : bool
    2233                 :        712 : spdk_lvol_is_degraded(const struct spdk_lvol *lvol)
    2234                 :            : {
    2235   [ #  #  #  # ]:        712 :         struct spdk_blob *blob = lvol->blob;
    2236                 :            : 
    2237         [ -  + ]:        712 :         if (blob == NULL) {
    2238                 :          0 :                 return true;
    2239                 :            :         }
    2240                 :        712 :         return spdk_blob_is_degraded(blob);
    2241                 :         12 : }
    2242                 :            : 
    2243                 :            : static void
    2244                 :          5 : lvol_shallow_copy_cb(void *cb_arg, int lvolerrno)
    2245                 :            : {
    2246                 :          5 :         struct spdk_lvol_copy_req *req = cb_arg;
    2247   [ #  #  #  # ]:          5 :         struct spdk_lvol *lvol = req->lvol;
    2248                 :            : 
    2249   [ #  #  #  # ]:          5 :         spdk_bs_free_io_channel(req->channel);
    2250                 :            : 
    2251         [ -  + ]:          5 :         if (lvolerrno < 0) {
    2252         [ #  # ]:          0 :                 SPDK_ERRLOG("Could not make a shallow copy of lvol %s, error %d\n", lvol->unique_id, lvolerrno);
    2253                 :          0 :         }
    2254                 :            : 
    2255   [ #  #  #  #  :          5 :         req->cb_fn(req->cb_arg, lvolerrno);
          #  #  #  #  #  
                #  #  # ]
    2256                 :          5 :         free(req);
    2257                 :          5 : }
    2258                 :            : 
    2259                 :            : int
    2260                 :         13 : spdk_lvol_shallow_copy(struct spdk_lvol *lvol, struct spdk_bs_dev *ext_dev,
    2261                 :            :                        spdk_blob_shallow_copy_status status_cb_fn, void *status_cb_arg,
    2262                 :            :                        spdk_lvol_op_complete cb_fn, void *cb_arg)
    2263                 :            : {
    2264                 :            :         struct spdk_lvol_copy_req *req;
    2265                 :            :         spdk_blob_id blob_id;
    2266                 :            :         int rc;
    2267                 :            : 
    2268   [ +  +  #  # ]:         13 :         assert(cb_fn != NULL);
    2269                 :            : 
    2270         [ +  + ]:         13 :         if (lvol == NULL) {
    2271                 :          4 :                 SPDK_ERRLOG("lvol must not be NULL\n");
    2272                 :          4 :                 return -EINVAL;
    2273                 :            :         }
    2274                 :            : 
    2275   [ -  +  #  #  :          9 :         assert(lvol->lvol_store->thread == spdk_get_thread());
          #  #  #  #  #  
                #  #  # ]
    2276                 :            : 
    2277         [ +  + ]:          9 :         if (ext_dev == NULL) {
    2278         [ #  # ]:          4 :                 SPDK_ERRLOG("lvol %s shallow copy, ext_dev must not be NULL\n", lvol->unique_id);
    2279                 :          4 :                 return -EINVAL;
    2280                 :            :         }
    2281                 :            : 
    2282                 :          5 :         req = calloc(1, sizeof(*req));
    2283         [ -  + ]:          5 :         if (!req) {
    2284         [ #  # ]:          0 :                 SPDK_ERRLOG("lvol %s shallow copy, cannot alloc memory for lvol request\n", lvol->unique_id);
    2285                 :          0 :                 return -ENOMEM;
    2286                 :            :         }
    2287                 :            : 
    2288   [ #  #  #  # ]:          5 :         req->lvol = lvol;
    2289   [ #  #  #  # ]:          5 :         req->cb_fn = cb_fn;
    2290   [ #  #  #  # ]:          5 :         req->cb_arg = cb_arg;
    2291   [ #  #  #  #  :          5 :         req->channel = spdk_bs_alloc_io_channel(lvol->lvol_store->blobstore);
          #  #  #  #  #  
                #  #  # ]
    2292   [ +  +  #  #  :          5 :         if (req->channel == NULL) {
                   #  # ]
    2293         [ #  # ]:          0 :                 SPDK_ERRLOG("lvol %s shallow copy, cannot alloc io channel for lvol request\n", lvol->unique_id);
    2294                 :          0 :                 free(req);
    2295                 :          0 :                 return -ENOMEM;
    2296                 :            :         }
    2297                 :            : 
    2298   [ #  #  #  # ]:          5 :         blob_id = spdk_blob_get_id(lvol->blob);
    2299                 :            : 
    2300   [ #  #  #  #  :          6 :         rc = spdk_bs_blob_shallow_copy(lvol->lvol_store->blobstore, req->channel, blob_id, ext_dev,
          #  #  #  #  #  
                #  #  # ]
    2301                 :          1 :                                        status_cb_fn, status_cb_arg, lvol_shallow_copy_cb, req);
    2302                 :            : 
    2303         [ +  + ]:          5 :         if (rc < 0) {
    2304         [ #  # ]:          0 :                 SPDK_ERRLOG("Could not make a shallow copy of lvol %s\n", lvol->unique_id);
    2305   [ #  #  #  # ]:          0 :                 spdk_bs_free_io_channel(req->channel);
    2306                 :          0 :                 free(req);
    2307                 :          0 :         }
    2308                 :            : 
    2309                 :          5 :         return rc;
    2310                 :          3 : }
    2311                 :            : 
    2312                 :            : static void
    2313                 :         11 : lvol_set_parent_cb(void *cb_arg, int lvolerrno)
    2314                 :            : {
    2315                 :         11 :         struct spdk_lvol_req *req = cb_arg;
    2316                 :            : 
    2317         [ +  + ]:         11 :         if (lvolerrno < 0) {
    2318   [ #  #  #  #  :          4 :                 SPDK_ERRLOG("could not set parent of lvol %s, error %d\n", req->lvol->name, lvolerrno);
                   #  # ]
    2319                 :          0 :         }
    2320                 :            : 
    2321   [ #  #  #  #  :         11 :         req->cb_fn(req->cb_arg, lvolerrno);
          #  #  #  #  #  
                #  #  # ]
    2322                 :         11 :         free(req);
    2323                 :         11 : }
    2324                 :            : 
    2325                 :            : void
    2326                 :         19 : spdk_lvol_set_parent(struct spdk_lvol *lvol, struct spdk_lvol *snapshot,
    2327                 :            :                      spdk_lvol_op_complete cb_fn, void *cb_arg)
    2328                 :            : {
    2329                 :            :         struct spdk_lvol_req *req;
    2330                 :            :         spdk_blob_id blob_id, snapshot_id;
    2331                 :            : 
    2332   [ +  +  #  # ]:         19 :         assert(cb_fn != NULL);
    2333                 :            : 
    2334         [ +  + ]:         19 :         if (lvol == NULL) {
    2335                 :          4 :                 SPDK_ERRLOG("lvol must not be NULL\n");
    2336   [ #  #  #  # ]:          4 :                 cb_fn(cb_arg, -EINVAL);
    2337                 :          4 :                 return;
    2338                 :            :         }
    2339                 :            : 
    2340         [ +  + ]:         15 :         if (snapshot == NULL) {
    2341                 :          4 :                 SPDK_ERRLOG("snapshot must not be NULL\n");
    2342   [ #  #  #  # ]:          4 :                 cb_fn(cb_arg, -EINVAL);
    2343                 :          4 :                 return;
    2344                 :            :         }
    2345                 :            : 
    2346                 :         11 :         req = calloc(1, sizeof(*req));
    2347         [ +  + ]:         11 :         if (!req) {
    2348                 :          0 :                 SPDK_ERRLOG("cannot alloc memory for lvol request pointer\n");
    2349   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, -ENOMEM);
    2350                 :          0 :                 return;
    2351                 :            :         }
    2352                 :            : 
    2353   [ #  #  #  # ]:         11 :         req->lvol = lvol;
    2354   [ #  #  #  # ]:         11 :         req->cb_fn = cb_fn;
    2355   [ #  #  #  # ]:         11 :         req->cb_arg = cb_arg;
    2356                 :            : 
    2357   [ #  #  #  # ]:         11 :         blob_id = spdk_blob_get_id(lvol->blob);
    2358   [ #  #  #  # ]:         11 :         snapshot_id = spdk_blob_get_id(snapshot->blob);
    2359                 :            : 
    2360   [ #  #  #  #  :         12 :         spdk_bs_blob_set_parent(lvol->lvol_store->blobstore, blob_id, snapshot_id,
             #  #  #  # ]
    2361                 :          1 :                                 lvol_set_parent_cb, req);
    2362                 :          3 : }
    2363                 :            : 
    2364                 :            : static void
    2365                 :         10 : lvol_set_external_parent_cb(void *cb_arg, int lvolerrno)
    2366                 :            : {
    2367                 :         10 :         struct spdk_lvol_bs_dev_req *req = cb_arg;
    2368                 :            : 
    2369         [ +  + ]:         10 :         if (lvolerrno < 0) {
    2370   [ #  #  #  #  :          3 :                 SPDK_ERRLOG("could not set external parent of lvol %s, error %d\n", req->lvol->name, lvolerrno);
                   #  # ]
    2371   [ #  #  #  #  :          3 :                 req->bs_dev->destroy(req->bs_dev);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    2372                 :          0 :         }
    2373                 :            : 
    2374   [ #  #  #  #  :         10 :         req->cb_fn(req->cb_arg, lvolerrno);
          #  #  #  #  #  
                #  #  # ]
    2375                 :         10 :         free(req);
    2376                 :         10 : }
    2377                 :            : 
    2378                 :            : void
    2379                 :         22 : spdk_lvol_set_external_parent(struct spdk_lvol *lvol, const void *esnap_id, uint32_t esnap_id_len,
    2380                 :            :                               spdk_lvol_op_complete cb_fn, void *cb_arg)
    2381                 :            : {
    2382                 :            :         struct spdk_lvol_bs_dev_req *req;
    2383                 :         18 :         struct spdk_bs_dev *bs_dev;
    2384                 :            :         spdk_blob_id blob_id;
    2385                 :            :         int rc;
    2386                 :            : 
    2387   [ +  +  #  # ]:         22 :         assert(cb_fn != NULL);
    2388                 :            : 
    2389         [ +  + ]:         22 :         if (lvol == NULL) {
    2390                 :          4 :                 SPDK_ERRLOG("lvol must not be NULL\n");
    2391   [ #  #  #  # ]:          4 :                 cb_fn(cb_arg, -EINVAL);
    2392                 :          4 :                 return;
    2393                 :            :         }
    2394                 :            : 
    2395         [ +  + ]:         18 :         if (esnap_id == NULL) {
    2396                 :          4 :                 SPDK_ERRLOG("snapshot must not be NULL\n");
    2397   [ #  #  #  # ]:          4 :                 cb_fn(cb_arg, -EINVAL);
    2398                 :          4 :                 return;
    2399                 :            :         }
    2400                 :            : 
    2401   [ +  -  +  + ]:         14 :         if (esnap_id_len == sizeof(lvol->uuid_str) &&
    2402   [ +  +  -  +  :         14 :             memcmp(esnap_id, lvol->uuid_str, esnap_id_len) == 0) {
                   +  + ]
    2403         [ #  # ]:          4 :                 SPDK_ERRLOG("lvol %s and esnap have the same UUID\n", lvol->name);
    2404   [ #  #  #  # ]:          4 :                 cb_fn(cb_arg, -EINVAL);
    2405                 :          4 :                 return;
    2406                 :            :         }
    2407                 :            : 
    2408   [ #  #  #  #  :         10 :         rc = lvs_esnap_bs_dev_create(lvol->lvol_store, lvol, lvol->blob, esnap_id, esnap_id_len, &bs_dev);
             #  #  #  # ]
    2409         [ -  + ]:         10 :         if (rc < 0) {
    2410   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, rc);
    2411                 :          0 :                 return;
    2412                 :            :         }
    2413                 :            : 
    2414                 :         10 :         req = calloc(1, sizeof(*req));
    2415         [ +  + ]:         10 :         if (!req) {
    2416                 :          0 :                 SPDK_ERRLOG("cannot alloc memory for lvol request pointer\n");
    2417   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, -ENOMEM);
    2418                 :          0 :                 return;
    2419                 :            :         }
    2420                 :            : 
    2421   [ #  #  #  # ]:         10 :         req->lvol = lvol;
    2422   [ #  #  #  # ]:         10 :         req->bs_dev = bs_dev;
    2423   [ #  #  #  # ]:         10 :         req->cb_fn = cb_fn;
    2424   [ #  #  #  # ]:         10 :         req->cb_arg = cb_arg;
    2425                 :            : 
    2426   [ #  #  #  # ]:         10 :         blob_id = spdk_blob_get_id(lvol->blob);
    2427                 :            : 
    2428   [ #  #  #  #  :         11 :         spdk_bs_blob_set_external_parent(lvol->lvol_store->blobstore, blob_id, bs_dev, esnap_id,
             #  #  #  # ]
    2429                 :          1 :                                          esnap_id_len, lvol_set_external_parent_cb, req);
    2430                 :          4 : }

Generated by: LCOV version 1.14