LCOV - code coverage report
Current view: top level - spdk/lib/lvol - lvol.c (source / functions) Hit Total Coverage
Test: Combined Lines: 1153 1417 81.4 %
Date: 2024-12-09 03:40:50 Functions: 91 97 93.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 751 5944 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                 :       2160 : 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                 :       5737 : lvs_alloc(void)
      67                 :            : {
      68                 :            :         struct spdk_lvol_store *lvs;
      69                 :            : 
      70                 :       5737 :         lvs = calloc(1, sizeof(*lvs));
      71         [ +  + ]:       5737 :         if (lvs == NULL) {
      72                 :          0 :                 return NULL;
      73                 :            :         }
      74                 :            : 
      75   [ +  -  +  -  :       5737 :         TAILQ_INIT(&lvs->lvols);
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
      76   [ +  -  +  -  :       5737 :         TAILQ_INIT(&lvs->pending_lvols);
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
      77   [ +  -  +  -  :       5737 :         TAILQ_INIT(&lvs->retry_open_lvols);
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
      78                 :            : 
      79   [ +  -  +  - ]:       5737 :         lvs->load_esnaps = false;
      80   [ +  -  +  -  :       5737 :         RB_INIT(&lvs->degraded_lvol_sets_tree);
                   +  - ]
      81   [ +  -  +  - ]:       5737 :         lvs->thread = spdk_get_thread();
      82                 :            : 
      83                 :       5737 :         return lvs;
      84                 :        356 : }
      85                 :            : 
      86                 :            : static void
      87                 :       5737 : lvs_free(struct spdk_lvol_store *lvs)
      88                 :            : {
      89         [ +  + ]:       5737 :         pthread_mutex_lock(&g_lvol_stores_mutex);
      90   [ +  +  +  +  :       5737 :         if (lvs->on_list) {
             +  -  +  - ]
      91   [ +  +  #  #  :        462 :                 TAILQ_REMOVE(&g_lvol_stores, lvs, link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
      92                 :         60 :         }
      93         [ +  + ]:       5737 :         pthread_mutex_unlock(&g_lvol_stores_mutex);
      94                 :            : 
      95   [ +  +  +  -  :       5737 :         assert(RB_EMPTY(&lvs->degraded_lvol_sets_tree));
          +  -  +  -  #  
                      # ]
      96                 :            : 
      97                 :       5737 :         free(lvs);
      98                 :       5737 : }
      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                 :       5364 : lvs_load_cb(void *cb_arg, struct spdk_blob_store *bs, int lvolerrno)
     398                 :            : {
     399                 :       5364 :         struct spdk_lvs_with_handle_req *req = (struct spdk_lvs_with_handle_req *)cb_arg;
     400   [ +  -  +  - ]:       5364 :         struct spdk_lvol_store *lvs = req->lvol_store;
     401                 :            : 
     402         [ +  + ]:       5364 :         if (lvolerrno != 0) {
     403   [ +  -  +  -  :       5238 :                 req->cb_fn(req->cb_arg, NULL, lvolerrno);
          -  +  -  +  +  
                -  +  - ]
     404                 :       5238 :                 lvs_free(lvs);
     405                 :       5238 :                 free(req);
     406                 :       5238 :                 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                 :        302 : }
     414                 :            : 
     415                 :            : static void
     416                 :       5733 : lvs_bs_opts_init(struct spdk_bs_opts *opts)
     417                 :            : {
     418                 :       5733 :         spdk_bs_opts_init(opts, sizeof(*opts));
     419   [ +  -  +  - ]:       5733 :         opts->max_channel_ops = SPDK_LVOL_BLOB_OPTS_CHANNEL_OPS;
     420                 :       5733 : }
     421                 :            : 
     422                 :            : static void
     423                 :       5368 : 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                 :       5368 :         struct spdk_bs_opts bs_opts = {};
     428                 :       2638 :         struct spdk_lvs_opts lvs_opts;
     429                 :            : 
     430   [ +  +  #  # ]:       5368 :         assert(cb_fn != NULL);
     431                 :            : 
     432         [ +  + ]:       5368 :         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                 :       5368 :         spdk_lvs_opts_init(&lvs_opts);
     439         [ +  + ]:       5368 :         if (_lvs_opts != NULL) {
     440         [ +  + ]:       5312 :                 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                 :        288 :         }
     446                 :            : 
     447                 :       5364 :         req = calloc(1, sizeof(*req));
     448         [ +  + ]:       5364 :         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   [ +  -  +  - ]:       5364 :         req->lvol_store = lvs_alloc();
     455   [ +  +  +  -  :       5364 :         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   [ +  -  +  - ]:       5364 :         req->cb_fn = cb_fn;
     462   [ +  -  +  - ]:       5364 :         req->cb_arg = cb_arg;
     463   [ +  -  +  - ]:       5364 :         req->bs_dev = bs_dev;
     464                 :            : 
     465                 :       5364 :         lvs_bs_opts_init(&bs_opts);
     466         [ -  + ]:       5364 :         snprintf(bs_opts.bstype.bstype, sizeof(bs_opts.bstype.bstype), "LVOLSTORE");
     467                 :            : 
     468         [ +  + ]:       5364 :         if (lvs_opts.esnap_bs_dev_create != NULL) {
     469   [ +  -  +  -  :       5308 :                 req->lvol_store->esnap_bs_dev_create = lvs_opts.esnap_bs_dev_create;
             +  -  +  - ]
     470                 :       5308 :                 bs_opts.esnap_bs_dev_create = lvs_esnap_bs_dev_create;
     471   [ +  -  +  - ]:       5308 :                 bs_opts.esnap_ctx = req->lvol_store;
     472                 :        288 :         }
     473                 :            : 
     474                 :       5364 :         spdk_bs_load(bs_dev, &bs_opts, lvs_load_cb, req);
     475                 :        303 : }
     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                 :       5312 : 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                 :       5312 :         lvs_load(bs_dev, opts, cb_fn, cb_arg);
     488                 :       5312 : }
     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                 :      11408 : spdk_lvs_opts_init(struct spdk_lvs_opts *o)
     619                 :            : {
     620         [ +  + ]:      11408 :         memset(o, 0, sizeof(*o));
     621   [ +  -  +  - ]:      11408 :         o->cluster_sz = SPDK_LVS_OPTS_CLUSTER_SZ;
     622   [ +  -  +  - ]:      11408 :         o->clear_method = LVS_CLEAR_WITH_UNMAP;
     623   [ +  -  +  - ]:      11408 :         o->num_md_pages_per_cluster_ratio = 100;
     624   [ +  -  +  - ]:      11408 :         o->opts_size = sizeof(*o);
     625                 :      11408 : }
     626                 :            : 
     627                 :            : static inline int
     628                 :       5683 : lvs_opts_copy(const struct spdk_lvs_opts *src, struct spdk_lvs_opts *dst)
     629                 :            : {
     630   [ +  +  +  -  :       5683 :         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   [ +  +  +  -  :       5679 :         SET_FIELD(cluster_sz);
          -  +  +  -  +  
             -  +  -  +  
                      - ]
     643   [ +  +  +  -  :       5679 :         SET_FIELD(clear_method);
          -  +  +  -  +  
             -  +  -  +  
                      - ]
     644   [ +  +  +  -  :       5679 :         if (FIELD_OK(name)) {
                   -  + ]
     645   [ +  +  +  +  :       5679 :                 memcpy(&dst->name, &src->name, sizeof(dst->name));
             +  -  +  - ]
     646                 :        341 :         }
     647   [ +  +  +  -  :       5679 :         SET_FIELD(num_md_pages_per_cluster_ratio);
          -  +  +  -  +  
             -  +  -  +  
                      - ]
     648   [ +  +  +  -  :       5679 :         SET_FIELD(opts_size);
          -  +  +  -  +  
             -  +  -  +  
                      - ]
     649   [ +  +  +  -  :       5679 :         SET_FIELD(esnap_bs_dev_create);
          -  +  +  -  +  
             -  +  -  +  
                      - ]
     650   [ +  +  +  -  :       5679 :         SET_FIELD(md_page_size);
          -  +  +  -  +  
             -  +  -  +  
                      - ]
     651                 :            : 
     652   [ +  -  +  -  :       5679 :         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                 :       5679 :         return 0;
     662                 :        342 : }
     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;
     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 :         if (strnlen(lvs_opts.name, SPDK_LVS_NAME_MAX) == SPDK_LVS_NAME_MAX) {
     722                 :          4 :                 SPDK_ERRLOG("Name has no null terminator.\n");
     723                 :          4 :                 lvs_free(lvs);
     724                 :          4 :                 return -EINVAL;
     725                 :            :         }
     726                 :            : 
     727   [ +  +  #  # ]:        365 :         if (strnlen(lvs_opts.name, SPDK_LVS_NAME_MAX) == 0) {
     728                 :          4 :                 SPDK_ERRLOG("No name specified.\n");
     729                 :          4 :                 lvs_free(lvs);
     730                 :          4 :                 return -EINVAL;
     731                 :            :         }
     732                 :            : 
     733         [ #  # ]:        361 :         spdk_uuid_generate(&lvs->uuid);
     734         [ #  # ]:        361 :         snprintf(lvs->name, sizeof(lvs->name), "%s", lvs_opts.name);
     735                 :            : 
     736                 :        361 :         rc = add_lvs_to_list(lvs);
     737         [ +  + ]:        361 :         if (rc) {
     738         [ #  # ]:          5 :                 SPDK_ERRLOG("lvolstore with name %s already exists\n", lvs->name);
     739                 :          5 :                 lvs_free(lvs);
     740                 :          5 :                 return -EEXIST;
     741                 :            :         }
     742                 :            : 
     743                 :        356 :         lvs_req = calloc(1, sizeof(*lvs_req));
     744         [ +  + ]:        356 :         if (!lvs_req) {
     745                 :          0 :                 lvs_free(lvs);
     746                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol store request pointer\n");
     747                 :          0 :                 return -ENOMEM;
     748                 :            :         }
     749                 :            : 
     750   [ -  +  #  # ]:        356 :         assert(cb_fn != NULL);
     751   [ #  #  #  # ]:        356 :         lvs_req->cb_fn = cb_fn;
     752   [ #  #  #  # ]:        356 :         lvs_req->cb_arg = cb_arg;
     753   [ #  #  #  # ]:        356 :         lvs_req->lvol_store = lvs;
     754   [ #  #  #  # ]:        356 :         lvs->bs_dev = bs_dev;
     755                 :            : 
     756   [ +  +  -  +  :        356 :         SPDK_INFOLOG(lvol, "Initializing lvol store\n");
                   #  # ]
     757                 :        356 :         spdk_bs_init(bs_dev, &opts, lvs_init_cb, lvs_req);
     758                 :            : 
     759                 :        356 :         return 0;
     760                 :         54 : }
     761                 :            : 
     762                 :            : static void
     763                 :          9 : lvs_rename_cb(void *cb_arg, int lvolerrno)
     764                 :            : {
     765                 :          9 :         struct spdk_lvs_req *req = cb_arg;
     766                 :            : 
     767         [ +  + ]:          9 :         if (lvolerrno != 0) {
     768   [ #  #  #  # ]:          4 :                 req->lvserrno = lvolerrno;
     769                 :          1 :         }
     770   [ +  +  #  #  :          9 :         if (req->lvserrno != 0) {
                   #  # ]
     771                 :          4 :                 SPDK_ERRLOG("Lvol store rename operation failed\n");
     772                 :            :                 /* Lvs renaming failed, so we should 'clear' new_name.
     773                 :            :                  * Otherwise it could cause a failure on the next attempt to change the name to 'new_name'  */
     774   [ -  +  #  #  :          5 :                 snprintf(req->lvol_store->new_name,
                   #  # ]
     775                 :            :                          sizeof(req->lvol_store->new_name),
     776   [ #  #  #  #  :          4 :                          "%s", req->lvol_store->name);
                   #  # ]
     777                 :          1 :         } else {
     778                 :            :                 /* Update lvs name with new_name */
     779   [ -  +  #  #  :          6 :                 snprintf(req->lvol_store->name,
                   #  # ]
     780                 :            :                          sizeof(req->lvol_store->name),
     781   [ #  #  #  #  :          5 :                          "%s", req->lvol_store->new_name);
                   #  # ]
     782                 :            :         }
     783                 :            : 
     784   [ #  #  #  #  :          9 :         req->cb_fn(req->cb_arg, req->lvserrno);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     785                 :          9 :         free(req);
     786                 :          9 : }
     787                 :            : 
     788                 :            : static void
     789                 :          5 : lvs_rename_sync_cb(void *cb_arg, int lvolerrno)
     790                 :            : {
     791                 :          5 :         struct spdk_lvs_req *req = cb_arg;
     792   [ #  #  #  #  :          5 :         struct spdk_blob *blob = req->lvol_store->super_blob;
             #  #  #  # ]
     793                 :            : 
     794         [ -  + ]:          5 :         if (lvolerrno < 0) {
     795   [ #  #  #  # ]:          0 :                 req->lvserrno = lvolerrno;
     796                 :          0 :         }
     797                 :            : 
     798                 :          5 :         spdk_blob_close(blob, lvs_rename_cb, req);
     799                 :          5 : }
     800                 :            : 
     801                 :            : static void
     802                 :          9 : lvs_rename_open_cb(void *cb_arg, struct spdk_blob *blob, int lvolerrno)
     803                 :            : {
     804                 :          9 :         struct spdk_lvs_req *req = cb_arg;
     805                 :            :         int rc;
     806                 :            : 
     807         [ +  + ]:          9 :         if (lvolerrno < 0) {
     808                 :          4 :                 lvs_rename_cb(cb_arg, lvolerrno);
     809                 :          4 :                 return;
     810                 :            :         }
     811                 :            : 
     812   [ #  #  #  #  :          6 :         rc = spdk_blob_set_xattr(blob, "name", req->lvol_store->new_name,
                   #  # ]
     813   [ -  +  #  #  :          5 :                                  strlen(req->lvol_store->new_name) + 1);
             #  #  #  # ]
     814         [ -  + ]:          5 :         if (rc < 0) {
     815   [ #  #  #  # ]:          0 :                 req->lvserrno = rc;
     816                 :          0 :                 lvs_rename_sync_cb(req, rc);
     817                 :          0 :                 return;
     818                 :            :         }
     819                 :            : 
     820   [ #  #  #  #  :          5 :         req->lvol_store->super_blob = blob;
             #  #  #  # ]
     821                 :            : 
     822                 :          5 :         spdk_blob_sync_md(blob, lvs_rename_sync_cb, req);
     823                 :          2 : }
     824                 :            : 
     825                 :            : void
     826                 :         22 : spdk_lvs_rename(struct spdk_lvol_store *lvs, const char *new_name,
     827                 :            :                 spdk_lvs_op_complete cb_fn, void *cb_arg)
     828                 :            : {
     829                 :            :         struct spdk_lvs_req *req;
     830                 :            :         struct spdk_lvol_store *tmp;
     831                 :            : 
     832                 :            :         /* Check if new name is current lvs name.
     833                 :            :          * If so, return success immediately */
     834   [ +  +  -  +  :         22 :         if (strncmp(lvs->name, new_name, SPDK_LVS_NAME_MAX) == 0) {
             +  +  #  # ]
     835   [ #  #  #  # ]:          4 :                 cb_fn(cb_arg, 0);
     836                 :          4 :                 return;
     837                 :            :         }
     838                 :            : 
     839                 :            :         /* Check if new or new_name is already used in other lvs */
     840         [ #  # ]:         18 :         pthread_mutex_lock(&g_lvol_stores_mutex);
     841   [ +  +  #  #  :         40 :         TAILQ_FOREACH(tmp, &g_lvol_stores, link) {
             #  #  #  # ]
     842   [ +  +  +  +  :         31 :                 if (!strncmp(new_name, tmp->name, SPDK_LVS_NAME_MAX) ||
          +  +  #  #  #  
                      # ]
     843   [ +  +  -  +  :         26 :                     !strncmp(new_name, tmp->new_name, SPDK_LVS_NAME_MAX)) {
                   +  + ]
     844         [ #  # ]:          9 :                         pthread_mutex_unlock(&g_lvol_stores_mutex);
     845   [ #  #  #  # ]:          9 :                         cb_fn(cb_arg, -EEXIST);
     846                 :          9 :                         return;
     847                 :            :                 }
     848                 :          5 :         }
     849         [ #  # ]:          9 :         pthread_mutex_unlock(&g_lvol_stores_mutex);
     850                 :            : 
     851                 :          9 :         req = calloc(1, sizeof(*req));
     852         [ -  + ]:          9 :         if (!req) {
     853                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
     854   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, -ENOMEM);
     855                 :          0 :                 return;
     856                 :            :         }
     857         [ #  # ]:          9 :         snprintf(lvs->new_name, sizeof(lvs->new_name), "%s", new_name);
     858   [ #  #  #  # ]:          9 :         req->lvol_store = lvs;
     859   [ #  #  #  # ]:          9 :         req->cb_fn = cb_fn;
     860   [ #  #  #  # ]:          9 :         req->cb_arg = cb_arg;
     861                 :            : 
     862   [ #  #  #  #  :          9 :         spdk_bs_open_blob(lvs->blobstore, lvs->super_blob_id, lvs_rename_open_cb, req);
             #  #  #  # ]
     863                 :          5 : }
     864                 :            : 
     865                 :            : static void
     866                 :        225 : _lvs_unload_cb(void *cb_arg, int lvserrno)
     867                 :            : {
     868                 :        225 :         struct spdk_lvs_req *lvs_req = cb_arg;
     869                 :            : 
     870   [ +  +  -  +  :        225 :         SPDK_INFOLOG(lvol, "Lvol store unloaded\n");
                   #  # ]
     871   [ +  +  #  #  :        225 :         assert(lvs_req->cb_fn != NULL);
             #  #  #  # ]
     872   [ #  #  #  #  :        225 :         lvs_req->cb_fn(lvs_req->cb_arg, lvserrno);
          #  #  #  #  #  
                #  #  # ]
     873                 :        225 :         free(lvs_req);
     874                 :        225 : }
     875                 :            : 
     876                 :            : int
     877                 :        233 : spdk_lvs_unload(struct spdk_lvol_store *lvs, spdk_lvs_op_complete cb_fn,
     878                 :            :                 void *cb_arg)
     879                 :            : {
     880                 :            :         struct spdk_lvs_req *lvs_req;
     881                 :            :         struct spdk_lvol *lvol, *tmp;
     882                 :            : 
     883         [ +  + ]:        233 :         if (lvs == NULL) {
     884                 :          4 :                 SPDK_ERRLOG("Lvol store is NULL\n");
     885                 :          4 :                 return -ENODEV;
     886                 :            :         }
     887                 :            : 
     888   [ +  +  +  +  :        476 :         TAILQ_FOREACH_SAFE(lvol, &lvs->lvols, link, tmp) {
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     889   [ +  +  -  +  :        251 :                 if (lvol->action_in_progress == true) {
             #  #  #  # ]
     890                 :          0 :                         SPDK_ERRLOG("Cannot unload lvol store - operations on lvols pending\n");
     891   [ #  #  #  # ]:          0 :                         cb_fn(cb_arg, -EBUSY);
     892                 :          0 :                         return -EBUSY;
     893   [ +  +  #  #  :        251 :                 } else if (lvol->ref_count != 0) {
                   #  # ]
     894                 :          4 :                         SPDK_ERRLOG("Lvols still open on lvol store\n");
     895   [ #  #  #  # ]:          4 :                         cb_fn(cb_arg, -EBUSY);
     896                 :          4 :                         return -EBUSY;
     897                 :            :                 }
     898                 :         28 :         }
     899                 :            : 
     900   [ +  +  +  +  :        472 :         TAILQ_FOREACH_SAFE(lvol, &lvs->lvols, link, tmp) {
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     901                 :        247 :                 spdk_lvs_esnap_missing_remove(lvol);
     902   [ +  +  #  #  :        247 :                 TAILQ_REMOVE(&lvs->lvols, lvol, link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
     903                 :        247 :                 lvol_free(lvol);
     904                 :         28 :         }
     905                 :            : 
     906                 :        225 :         lvs_req = calloc(1, sizeof(*lvs_req));
     907         [ +  + ]:        225 :         if (!lvs_req) {
     908                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol store request pointer\n");
     909                 :          0 :                 return -ENOMEM;
     910                 :            :         }
     911                 :            : 
     912   [ #  #  #  # ]:        225 :         lvs_req->cb_fn = cb_fn;
     913   [ #  #  #  # ]:        225 :         lvs_req->cb_arg = cb_arg;
     914                 :            : 
     915   [ -  +  -  +  :        225 :         SPDK_INFOLOG(lvol, "Unloading lvol store\n");
                   #  # ]
     916   [ #  #  #  # ]:        225 :         spdk_bs_unload(lvs->blobstore, _lvs_unload_cb, lvs_req);
     917                 :        225 :         lvs_free(lvs);
     918                 :            : 
     919                 :        225 :         return 0;
     920                 :         30 : }
     921                 :            : 
     922                 :            : static void
     923                 :        225 : _lvs_destroy_cb(void *cb_arg, int lvserrno)
     924                 :            : {
     925                 :        225 :         struct spdk_lvs_destroy_req *lvs_req = cb_arg;
     926                 :            : 
     927   [ +  +  -  +  :        225 :         SPDK_INFOLOG(lvol, "Lvol store destroyed\n");
                   #  # ]
     928   [ +  +  #  #  :        225 :         assert(lvs_req->cb_fn != NULL);
             #  #  #  # ]
     929   [ #  #  #  #  :        225 :         lvs_req->cb_fn(lvs_req->cb_arg, lvserrno);
          #  #  #  #  #  
                #  #  # ]
     930                 :        225 :         free(lvs_req);
     931                 :        225 : }
     932                 :            : 
     933                 :            : static void
     934                 :        225 : _lvs_destroy_super_cb(void *cb_arg, int bserrno)
     935                 :            : {
     936                 :        225 :         struct spdk_lvs_destroy_req *lvs_req = cb_arg;
     937   [ #  #  #  # ]:        225 :         struct spdk_lvol_store *lvs = lvs_req->lvs;
     938                 :            : 
     939   [ +  +  #  # ]:        225 :         assert(lvs != NULL);
     940                 :            : 
     941   [ +  +  -  +  :        225 :         SPDK_INFOLOG(lvol, "Destroying lvol store\n");
                   #  # ]
     942   [ #  #  #  # ]:        225 :         spdk_bs_destroy(lvs->blobstore, _lvs_destroy_cb, lvs_req);
     943                 :        225 :         lvs_free(lvs);
     944                 :        225 : }
     945                 :            : 
     946                 :            : int
     947                 :        229 : spdk_lvs_destroy(struct spdk_lvol_store *lvs, spdk_lvs_op_complete cb_fn,
     948                 :            :                  void *cb_arg)
     949                 :            : {
     950                 :            :         struct spdk_lvs_destroy_req *lvs_req;
     951                 :            :         struct spdk_lvol *iter_lvol, *tmp;
     952                 :            : 
     953         [ +  + ]:        229 :         if (lvs == NULL) {
     954                 :          0 :                 SPDK_ERRLOG("Lvol store is NULL\n");
     955                 :          0 :                 return -ENODEV;
     956                 :            :         }
     957                 :            : 
     958   [ +  +  +  +  :        241 :         TAILQ_FOREACH_SAFE(iter_lvol, &lvs->lvols, link, tmp) {
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     959   [ +  +  -  +  :         16 :                 if (iter_lvol->action_in_progress == true) {
             #  #  #  # ]
     960                 :          0 :                         SPDK_ERRLOG("Cannot destroy lvol store - operations on lvols pending\n");
     961   [ #  #  #  # ]:          0 :                         cb_fn(cb_arg, -EBUSY);
     962                 :          0 :                         return -EBUSY;
     963   [ +  +  #  #  :         16 :                 } else if (iter_lvol->ref_count != 0) {
                   #  # ]
     964                 :          4 :                         SPDK_ERRLOG("Lvols still open on lvol store\n");
     965   [ #  #  #  # ]:          4 :                         cb_fn(cb_arg, -EBUSY);
     966                 :          4 :                         return -EBUSY;
     967                 :            :                 }
     968                 :          3 :         }
     969                 :            : 
     970   [ +  +  +  +  :        237 :         TAILQ_FOREACH_SAFE(iter_lvol, &lvs->lvols, link, tmp) {
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     971                 :         12 :                 free(iter_lvol);
     972                 :          3 :         }
     973                 :            : 
     974                 :        225 :         lvs_req = calloc(1, sizeof(*lvs_req));
     975         [ +  + ]:        225 :         if (!lvs_req) {
     976                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol store request pointer\n");
     977                 :          0 :                 return -ENOMEM;
     978                 :            :         }
     979                 :            : 
     980   [ #  #  #  # ]:        225 :         lvs_req->cb_fn = cb_fn;
     981   [ #  #  #  # ]:        225 :         lvs_req->cb_arg = cb_arg;
     982   [ #  #  #  # ]:        225 :         lvs_req->lvs = lvs;
     983                 :            : 
     984   [ -  +  -  +  :        225 :         SPDK_INFOLOG(lvol, "Deleting super blob\n");
                   #  # ]
     985   [ #  #  #  #  :        225 :         spdk_bs_delete_blob(lvs->blobstore, lvs->super_blob_id, _lvs_destroy_super_cb, lvs_req);
             #  #  #  # ]
     986                 :            : 
     987                 :        225 :         return 0;
     988                 :         30 : }
     989                 :            : 
     990                 :            : static void
     991                 :        749 : lvol_close_blob_cb(void *cb_arg, int lvolerrno)
     992                 :            : {
     993                 :        749 :         struct spdk_lvol_req *req = cb_arg;
     994   [ #  #  #  # ]:        749 :         struct spdk_lvol *lvol = req->lvol;
     995                 :            : 
     996         [ +  + ]:        749 :         if (lvolerrno < 0) {
     997                 :          4 :                 SPDK_ERRLOG("Could not close blob on lvol\n");
     998                 :          4 :                 goto end;
     999                 :            :         }
    1000                 :            : 
    1001   [ #  #  #  # ]:        745 :         lvol->ref_count--;
    1002   [ #  #  #  # ]:        745 :         lvol->blob = NULL;
    1003   [ +  +  +  -  :        745 :         SPDK_INFOLOG(lvol, "Lvol %s closed\n", lvol->unique_id);
             #  #  #  # ]
    1004                 :            : 
    1005                 :        658 : end:
    1006   [ #  #  #  # ]:        749 :         lvol->action_in_progress = false;
    1007   [ #  #  #  #  :        749 :         req->cb_fn(req->cb_arg, lvolerrno);
          #  #  #  #  #  
                #  #  # ]
    1008                 :        749 :         free(req);
    1009                 :        749 : }
    1010                 :            : 
    1011                 :            : bool
    1012                 :         74 : spdk_lvol_deletable(struct spdk_lvol *lvol)
    1013                 :            : {
    1014                 :         74 :         size_t count = 0;
    1015                 :            : 
    1016   [ #  #  #  #  :         74 :         spdk_blob_get_clones(lvol->lvol_store->blobstore, lvol->blob_id, NULL, &count);
          #  #  #  #  #  
                #  #  # ]
    1017                 :         74 :         return (count == 0);
    1018                 :            : }
    1019                 :            : 
    1020                 :            : static void
    1021                 :        502 : lvol_delete_blob_cb(void *cb_arg, int lvolerrno)
    1022                 :            : {
    1023                 :        502 :         struct spdk_lvol_req *req = cb_arg;
    1024   [ #  #  #  # ]:        502 :         struct spdk_lvol *lvol = req->lvol;
    1025   [ #  #  #  # ]:        502 :         struct spdk_lvol *clone_lvol = req->clone_lvol;
    1026                 :            : 
    1027         [ +  + ]:        502 :         if (lvolerrno < 0) {
    1028                 :          4 :                 SPDK_ERRLOG("Could not remove blob on lvol gracefully - forced removal\n");
    1029                 :          1 :         } else {
    1030   [ +  +  -  +  :        498 :                 SPDK_INFOLOG(lvol, "Lvol %s deleted\n", lvol->unique_id);
             #  #  #  # ]
    1031                 :            :         }
    1032                 :            : 
    1033   [ +  +  #  #  :        502 :         if (lvol->degraded_set != NULL) {
                   #  # ]
    1034         [ +  + ]:         51 :                 if (clone_lvol != NULL) {
    1035                 :            :                         /*
    1036                 :            :                          * A degraded esnap clone that has a blob clone has been deleted. clone_lvol
    1037                 :            :                          * becomes an esnap clone and needs to be associated with the
    1038                 :            :                          * spdk_lvs_degraded_lvol_set.
    1039                 :            :                          */
    1040   [ #  #  #  # ]:          5 :                         struct spdk_lvs_degraded_lvol_set *degraded_set = lvol->degraded_set;
    1041                 :            : 
    1042                 :          5 :                         lvs_degraded_lvol_set_remove(degraded_set, lvol);
    1043                 :          5 :                         lvs_degraded_lvol_set_add(degraded_set, clone_lvol);
    1044                 :          1 :                 } else {
    1045                 :         46 :                         spdk_lvs_esnap_missing_remove(lvol);
    1046                 :            :                 }
    1047                 :         12 :         }
    1048                 :            : 
    1049   [ +  +  #  #  :        502 :         TAILQ_REMOVE(&lvol->lvol_store->lvols, lvol, link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    1050                 :        502 :         lvol_free(lvol);
    1051   [ #  #  #  #  :        502 :         req->cb_fn(req->cb_arg, lvolerrno);
          #  #  #  #  #  
                #  #  # ]
    1052                 :        502 :         free(req);
    1053                 :        502 : }
    1054                 :            : 
    1055                 :            : static void
    1056                 :        630 : lvol_create_open_cb(void *cb_arg, struct spdk_blob *blob, int lvolerrno)
    1057                 :            : {
    1058                 :        630 :         struct spdk_lvol_with_handle_req *req = cb_arg;
    1059   [ #  #  #  # ]:        630 :         struct spdk_lvol *lvol = req->lvol;
    1060                 :            : 
    1061   [ -  +  #  #  :        630 :         TAILQ_REMOVE(&req->lvol->lvol_store->pending_lvols, req->lvol, link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1062                 :            : 
    1063         [ +  + ]:        630 :         if (lvolerrno < 0) {
    1064                 :          0 :                 lvol_free(lvol);
    1065   [ #  #  #  #  :          0 :                 req->cb_fn(req->cb_arg, NULL, lvolerrno);
          #  #  #  #  #  
                #  #  # ]
    1066                 :          0 :                 free(req);
    1067                 :          0 :                 return;
    1068                 :            :         }
    1069                 :            : 
    1070   [ #  #  #  # ]:        630 :         lvol->blob = blob;
    1071   [ #  #  #  # ]:        630 :         lvol->blob_id = spdk_blob_get_id(blob);
    1072                 :            : 
    1073   [ #  #  #  #  :        630 :         TAILQ_INSERT_TAIL(&lvol->lvol_store->lvols, lvol, link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
    1074                 :            : 
    1075   [ #  #  #  # ]:        630 :         lvol->ref_count++;
    1076                 :            : 
    1077   [ +  +  #  #  :        630 :         assert(req->cb_fn != NULL);
             #  #  #  # ]
    1078   [ #  #  #  #  :        630 :         req->cb_fn(req->cb_arg, req->lvol, lvolerrno);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    1079                 :        630 :         free(req);
    1080                 :         79 : }
    1081                 :            : 
    1082                 :            : static void
    1083                 :        639 : lvol_create_cb(void *cb_arg, spdk_blob_id blobid, int lvolerrno)
    1084                 :            : {
    1085                 :        639 :         struct spdk_lvol_with_handle_req *req = cb_arg;
    1086                 :            :         struct spdk_blob_store *bs;
    1087                 :        432 :         struct spdk_blob_open_opts opts;
    1088                 :            : 
    1089         [ +  + ]:        639 :         if (lvolerrno < 0) {
    1090   [ -  +  #  #  :          9 :                 TAILQ_REMOVE(&req->lvol->lvol_store->pending_lvols, req->lvol, link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1091   [ #  #  #  # ]:          9 :                 lvol_free(req->lvol);
    1092   [ -  +  #  #  :          9 :                 assert(req->cb_fn != NULL);
             #  #  #  # ]
    1093   [ #  #  #  #  :          9 :                 req->cb_fn(req->cb_arg, NULL, lvolerrno);
          #  #  #  #  #  
                #  #  # ]
    1094                 :          9 :                 free(req);
    1095                 :          9 :                 return;
    1096                 :            :         }
    1097                 :            : 
    1098                 :        630 :         spdk_blob_open_opts_init(&opts, sizeof(opts));
    1099   [ #  #  #  #  :        630 :         opts.clear_method = req->lvol->clear_method;
             #  #  #  # ]
    1100                 :            :         /*
    1101                 :            :          * If the lvol that is being created is an esnap clone, the blobstore needs to be able to
    1102                 :            :          * pass the lvol to the esnap_bs_dev_create callback. In order for that to happen, we need
    1103                 :            :          * to pass it here.
    1104                 :            :          *
    1105                 :            :          * This does set ensap_ctx in cases where it's not needed, but we don't know that it's not
    1106                 :            :          * needed until after the blob is open. When the blob is not an esnap clone, a reference to
    1107                 :            :          * the value stored in opts.esnap_ctx is not retained by the blobstore.
    1108                 :            :          */
    1109   [ #  #  #  #  :        630 :         opts.esnap_ctx = req->lvol;
                   #  # ]
    1110   [ #  #  #  #  :        630 :         bs = req->lvol->lvol_store->blobstore;
          #  #  #  #  #  
                #  #  # ]
    1111                 :            : 
    1112   [ +  +  +  +  :        630 :         if (req->origlvol != NULL && req->origlvol->degraded_set != NULL) {
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    1113                 :            :                 /*
    1114                 :            :                  * A snapshot was created from a degraded esnap clone. The new snapshot is now a
    1115                 :            :                  * degraded esnap clone. The previous clone is now a regular clone of a blob. Update
    1116                 :            :                  * the set of directly-related clones to the missing external snapshot.
    1117                 :            :                  */
    1118   [ #  #  #  #  :          4 :                 struct spdk_lvs_degraded_lvol_set *degraded_set = req->origlvol->degraded_set;
             #  #  #  # ]
    1119                 :            : 
    1120   [ #  #  #  # ]:          4 :                 lvs_degraded_lvol_set_remove(degraded_set, req->origlvol);
    1121   [ #  #  #  # ]:          4 :                 lvs_degraded_lvol_set_add(degraded_set, req->lvol);
    1122                 :          1 :         }
    1123                 :            : 
    1124                 :        630 :         spdk_bs_open_blob_ext(bs, blobid, &opts, lvol_create_open_cb, req);
    1125                 :         80 : }
    1126                 :            : 
    1127                 :            : static void
    1128                 :        672 : lvol_get_xattr_value(void *xattr_ctx, const char *name,
    1129                 :            :                      const void **value, size_t *value_len)
    1130                 :            : {
    1131                 :        672 :         struct spdk_lvol *lvol = xattr_ctx;
    1132                 :            : 
    1133   [ +  +  +  +  :        672 :         if (!strcmp(LVOL_NAME, name)) {
                   #  # ]
    1134   [ #  #  #  # ]:        336 :                 *value = lvol->name;
    1135         [ #  # ]:        336 :                 *value_len = SPDK_LVOL_NAME_MAX;
    1136                 :        336 :                 return;
    1137                 :            :         }
    1138   [ +  +  +  +  :        336 :         if (!strcmp("uuid", name)) {
                   #  # ]
    1139   [ #  #  #  # ]:        332 :                 *value = lvol->uuid_str;
    1140         [ #  # ]:        332 :                 *value_len = sizeof(lvol->uuid_str);
    1141                 :        332 :                 return;
    1142                 :            :         }
    1143         [ #  # ]:          4 :         *value = NULL;
    1144         [ #  # ]:          4 :         *value_len = 0;
    1145                 :         10 : }
    1146                 :            : 
    1147                 :            : static int
    1148                 :        716 : lvs_verify_lvol_name(struct spdk_lvol_store *lvs, const char *name)
    1149                 :            : {
    1150                 :            :         struct spdk_lvol *tmp;
    1151                 :            : 
    1152   [ +  +  +  +  :        716 :         if (name == NULL || strnlen(name, SPDK_LVOL_NAME_MAX) == 0) {
                   +  + ]
    1153   [ +  +  -  +  :         28 :                 SPDK_INFOLOG(lvol, "lvol name not provided.\n");
                   #  # ]
    1154                 :         28 :                 return -EINVAL;
    1155                 :            :         }
    1156                 :            : 
    1157   [ +  +  +  + ]:        688 :         if (strnlen(name, SPDK_LVOL_NAME_MAX) == SPDK_LVOL_NAME_MAX) {
    1158                 :          8 :                 SPDK_ERRLOG("Name has no null terminator.\n");
    1159                 :          8 :                 return -EINVAL;
    1160                 :            :         }
    1161                 :            : 
    1162   [ +  +  #  #  :       2001 :         TAILQ_FOREACH(tmp, &lvs->lvols, link) {
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1163   [ +  +  -  +  :       1354 :                 if (!strncmp(name, tmp->name, SPDK_LVOL_NAME_MAX)) {
             +  +  #  # ]
    1164                 :         33 :                         SPDK_ERRLOG("lvol with name %s already exists\n", name);
    1165                 :         33 :                         return -EEXIST;
    1166                 :            :                 }
    1167                 :         50 :         }
    1168                 :            : 
    1169   [ +  +  #  #  :        647 :         TAILQ_FOREACH(tmp, &lvs->pending_lvols, link) {
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1170   [ +  +  -  +  :          4 :                 if (!strncmp(name, tmp->name, SPDK_LVOL_NAME_MAX)) {
             +  -  #  # ]
    1171                 :          4 :                         SPDK_ERRLOG("lvol with name %s is being already created\n", name);
    1172                 :          4 :                         return -EEXIST;
    1173                 :            :                 }
    1174                 :          0 :         }
    1175                 :            : 
    1176                 :        643 :         return 0;
    1177                 :         99 : }
    1178                 :            : 
    1179                 :            : int
    1180                 :        428 : spdk_lvol_create(struct spdk_lvol_store *lvs, const char *name, uint64_t sz,
    1181                 :            :                  bool thin_provision, enum lvol_clear_method clear_method, spdk_lvol_op_with_handle_complete cb_fn,
    1182                 :            :                  void *cb_arg)
    1183                 :            : {
    1184                 :            :         struct spdk_lvol_with_handle_req *req;
    1185                 :            :         struct spdk_blob_store *bs;
    1186                 :            :         struct spdk_lvol *lvol;
    1187                 :        271 :         struct spdk_blob_opts opts;
    1188                 :        428 :         char *xattr_names[] = {LVOL_NAME, "uuid"};
    1189                 :            :         int rc;
    1190                 :            : 
    1191         [ +  + ]:        428 :         if (lvs == NULL) {
    1192                 :          4 :                 SPDK_ERRLOG("lvol store does not exist\n");
    1193                 :          4 :                 return -EINVAL;
    1194                 :            :         }
    1195                 :            : 
    1196                 :        424 :         rc = lvs_verify_lvol_name(lvs, name);
    1197         [ +  + ]:        424 :         if (rc < 0) {
    1198                 :         29 :                 return rc;
    1199                 :            :         }
    1200                 :            : 
    1201   [ #  #  #  # ]:        395 :         bs = lvs->blobstore;
    1202                 :            : 
    1203                 :        395 :         req = calloc(1, sizeof(*req));
    1204         [ +  + ]:        395 :         if (!req) {
    1205                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
    1206                 :          0 :                 return -ENOMEM;
    1207                 :            :         }
    1208   [ #  #  #  # ]:        395 :         req->cb_fn = cb_fn;
    1209   [ #  #  #  # ]:        395 :         req->cb_arg = cb_arg;
    1210                 :            : 
    1211         [ #  # ]:        395 :         lvol = lvol_alloc(lvs, name, thin_provision, clear_method);
    1212         [ -  + ]:        395 :         if (!lvol) {
    1213                 :          0 :                 free(req);
    1214                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol base pointer\n");
    1215                 :          0 :                 return -ENOMEM;
    1216                 :            :         }
    1217                 :            : 
    1218   [ #  #  #  # ]:        395 :         req->lvol = lvol;
    1219                 :        395 :         spdk_blob_opts_init(&opts, sizeof(opts));
    1220   [ #  #  #  # ]:        395 :         opts.thin_provision = thin_provision;
    1221                 :        395 :         opts.num_clusters = spdk_divide_round_up(sz, spdk_bs_get_cluster_size(bs));
    1222   [ #  #  #  #  :        395 :         opts.clear_method = lvol->clear_method;
                   #  # ]
    1223   [ #  #  #  # ]:        395 :         opts.xattrs.count = SPDK_COUNTOF(xattr_names);
    1224   [ #  #  #  # ]:        395 :         opts.xattrs.names = xattr_names;
    1225   [ #  #  #  # ]:        395 :         opts.xattrs.ctx = lvol;
    1226   [ #  #  #  # ]:        395 :         opts.xattrs.get_value = lvol_get_xattr_value;
    1227                 :            : 
    1228   [ #  #  #  # ]:        395 :         spdk_bs_create_blob_ext(lvs->blobstore, &opts, lvol_create_cb, req);
    1229                 :            : 
    1230                 :        395 :         return 0;
    1231                 :         44 : }
    1232                 :            : 
    1233                 :            : int
    1234                 :        162 : spdk_lvol_create_esnap_clone(const void *esnap_id, uint32_t id_len, uint64_t size_bytes,
    1235                 :            :                              struct spdk_lvol_store *lvs, const char *clone_name,
    1236                 :            :                              spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg)
    1237                 :            : {
    1238                 :            :         struct spdk_lvol_with_handle_req *req;
    1239                 :            :         struct spdk_blob_store *bs;
    1240                 :            :         struct spdk_lvol *lvol;
    1241                 :        124 :         struct spdk_blob_opts opts;
    1242                 :            :         uint64_t cluster_sz;
    1243                 :        162 :         char *xattr_names[] = {LVOL_NAME, "uuid"};
    1244                 :            :         int rc;
    1245                 :            : 
    1246         [ +  + ]:        162 :         if (lvs == NULL) {
    1247                 :          4 :                 SPDK_ERRLOG("lvol store does not exist\n");
    1248                 :          4 :                 return -EINVAL;
    1249                 :            :         }
    1250                 :            : 
    1251                 :        158 :         rc = lvs_verify_lvol_name(lvs, clone_name);
    1252         [ +  + ]:        158 :         if (rc < 0) {
    1253                 :         20 :                 return rc;
    1254                 :            :         }
    1255                 :            : 
    1256   [ #  #  #  # ]:        138 :         bs = lvs->blobstore;
    1257                 :            : 
    1258                 :        138 :         cluster_sz = spdk_bs_get_cluster_size(bs);
    1259   [ +  +  +  + ]:        138 :         if ((size_bytes % cluster_sz) != 0) {
    1260         [ #  # ]:          4 :                 SPDK_ERRLOG("Cannot create '%s/%s': size %" PRIu64 " is not an integer multiple of "
    1261                 :            :                             "cluster size %" PRIu64 "\n", lvs->name, clone_name, size_bytes,
    1262                 :            :                             cluster_sz);
    1263                 :          4 :                 return -EINVAL;
    1264                 :            :         }
    1265                 :            : 
    1266                 :        134 :         req = calloc(1, sizeof(*req));
    1267         [ +  + ]:        134 :         if (!req) {
    1268                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
    1269                 :          0 :                 return -ENOMEM;
    1270                 :            :         }
    1271   [ #  #  #  # ]:        134 :         req->cb_fn = cb_fn;
    1272   [ #  #  #  # ]:        134 :         req->cb_arg = cb_arg;
    1273                 :            : 
    1274                 :        134 :         lvol = lvol_alloc(lvs, clone_name, true, LVOL_CLEAR_WITH_DEFAULT);
    1275         [ -  + ]:        134 :         if (!lvol) {
    1276                 :          0 :                 free(req);
    1277                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol base pointer\n");
    1278                 :          0 :                 return -ENOMEM;
    1279                 :            :         }
    1280   [ #  #  #  # ]:        134 :         req->lvol = lvol;
    1281                 :            : 
    1282                 :        134 :         spdk_blob_opts_init(&opts, sizeof(opts));
    1283         [ #  # ]:        134 :         opts.esnap_id = esnap_id;
    1284         [ #  # ]:        134 :         opts.esnap_id_len = id_len;
    1285         [ #  # ]:        134 :         opts.thin_provision = true;
    1286                 :        134 :         opts.num_clusters = spdk_divide_round_up(size_bytes, cluster_sz);
    1287   [ #  #  #  #  :        134 :         opts.clear_method = lvol->clear_method;
                   #  # ]
    1288   [ #  #  #  # ]:        134 :         opts.xattrs.count = SPDK_COUNTOF(xattr_names);
    1289   [ #  #  #  # ]:        134 :         opts.xattrs.names = xattr_names;
    1290   [ #  #  #  # ]:        134 :         opts.xattrs.ctx = lvol;
    1291   [ #  #  #  # ]:        134 :         opts.xattrs.get_value = lvol_get_xattr_value;
    1292                 :            : 
    1293   [ #  #  #  # ]:        134 :         spdk_bs_create_blob_ext(lvs->blobstore, &opts, lvol_create_cb, req);
    1294                 :            : 
    1295                 :        134 :         return 0;
    1296                 :         38 : }
    1297                 :            : 
    1298                 :            : void
    1299                 :         84 : spdk_lvol_create_snapshot(struct spdk_lvol *origlvol, const char *snapshot_name,
    1300                 :            :                           spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg)
    1301                 :            : {
    1302                 :            :         struct spdk_lvol_store *lvs;
    1303                 :            :         struct spdk_lvol *newlvol;
    1304                 :            :         struct spdk_blob *origblob;
    1305                 :            :         struct spdk_lvol_with_handle_req *req;
    1306                 :         65 :         struct spdk_blob_xattr_opts snapshot_xattrs;
    1307                 :         84 :         char *xattr_names[] = {LVOL_NAME, "uuid"};
    1308                 :            :         int rc;
    1309                 :            : 
    1310         [ +  + ]:         84 :         if (origlvol == NULL) {
    1311   [ +  +  -  +  :          4 :                 SPDK_INFOLOG(lvol, "Lvol not provided.\n");
                   #  # ]
    1312   [ #  #  #  # ]:          4 :                 cb_fn(cb_arg, NULL, -EINVAL);
    1313                 :          4 :                 return;
    1314                 :            :         }
    1315                 :            : 
    1316   [ #  #  #  # ]:         80 :         origblob = origlvol->blob;
    1317   [ #  #  #  # ]:         80 :         lvs = origlvol->lvol_store;
    1318         [ +  + ]:         80 :         if (lvs == NULL) {
    1319                 :          0 :                 SPDK_ERRLOG("lvol store does not exist\n");
    1320   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, NULL, -EINVAL);
    1321                 :          0 :                 return;
    1322                 :            :         }
    1323                 :            : 
    1324                 :         80 :         rc = lvs_verify_lvol_name(lvs, snapshot_name);
    1325         [ +  + ]:         80 :         if (rc < 0) {
    1326   [ #  #  #  # ]:         12 :                 cb_fn(cb_arg, NULL, rc);
    1327                 :         12 :                 return;
    1328                 :            :         }
    1329                 :            : 
    1330                 :         68 :         req = calloc(1, sizeof(*req));
    1331         [ +  + ]:         68 :         if (!req) {
    1332                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
    1333   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, NULL, -ENOMEM);
    1334                 :          0 :                 return;
    1335                 :            :         }
    1336                 :            : 
    1337   [ #  #  #  # ]:         76 :         newlvol = lvol_alloc(origlvol->lvol_store, snapshot_name, true,
    1338   [ #  #  #  # ]:         68 :                              (enum lvol_clear_method)origlvol->clear_method);
    1339         [ -  + ]:         68 :         if (!newlvol) {
    1340                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol base pointer\n");
    1341                 :          0 :                 free(req);
    1342   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, NULL, -ENOMEM);
    1343                 :          0 :                 return;
    1344                 :            :         }
    1345                 :            : 
    1346                 :         68 :         snapshot_xattrs.count = SPDK_COUNTOF(xattr_names);
    1347         [ #  # ]:         68 :         snapshot_xattrs.ctx = newlvol;
    1348         [ #  # ]:         68 :         snapshot_xattrs.names = xattr_names;
    1349         [ #  # ]:         68 :         snapshot_xattrs.get_value = lvol_get_xattr_value;
    1350   [ #  #  #  # ]:         68 :         req->lvol = newlvol;
    1351   [ #  #  #  # ]:         68 :         req->origlvol = origlvol;
    1352   [ #  #  #  # ]:         68 :         req->cb_fn = cb_fn;
    1353   [ #  #  #  # ]:         68 :         req->cb_arg = cb_arg;
    1354                 :            : 
    1355   [ #  #  #  # ]:         76 :         spdk_bs_create_snapshot(lvs->blobstore, spdk_blob_get_id(origblob), &snapshot_xattrs,
    1356                 :          8 :                                 lvol_create_cb, req);
    1357                 :         12 : }
    1358                 :            : 
    1359                 :            : void
    1360                 :         58 : spdk_lvol_create_clone(struct spdk_lvol *origlvol, const char *clone_name,
    1361                 :            :                        spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg)
    1362                 :            : {
    1363                 :            :         struct spdk_lvol *newlvol;
    1364                 :            :         struct spdk_lvol_with_handle_req *req;
    1365                 :            :         struct spdk_lvol_store *lvs;
    1366                 :            :         struct spdk_blob *origblob;
    1367                 :         42 :         struct spdk_blob_xattr_opts clone_xattrs;
    1368                 :         58 :         char *xattr_names[] = {LVOL_NAME, "uuid"};
    1369                 :            :         int rc;
    1370                 :            : 
    1371         [ +  + ]:         58 :         if (origlvol == NULL) {
    1372   [ +  +  -  +  :          4 :                 SPDK_INFOLOG(lvol, "Lvol not provided.\n");
                   #  # ]
    1373   [ #  #  #  # ]:          4 :                 cb_fn(cb_arg, NULL, -EINVAL);
    1374                 :          4 :                 return;
    1375                 :            :         }
    1376                 :            : 
    1377   [ #  #  #  # ]:         54 :         origblob = origlvol->blob;
    1378   [ #  #  #  # ]:         54 :         lvs = origlvol->lvol_store;
    1379         [ +  + ]:         54 :         if (lvs == NULL) {
    1380                 :          0 :                 SPDK_ERRLOG("lvol store does not exist\n");
    1381   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, NULL, -EINVAL);
    1382                 :          0 :                 return;
    1383                 :            :         }
    1384                 :            : 
    1385                 :         54 :         rc = lvs_verify_lvol_name(lvs, clone_name);
    1386         [ +  + ]:         54 :         if (rc < 0) {
    1387   [ #  #  #  # ]:         12 :                 cb_fn(cb_arg, NULL, rc);
    1388                 :         12 :                 return;
    1389                 :            :         }
    1390                 :            : 
    1391                 :         42 :         req = calloc(1, sizeof(*req));
    1392         [ +  + ]:         42 :         if (!req) {
    1393                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
    1394   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, NULL, -ENOMEM);
    1395                 :          0 :                 return;
    1396                 :            :         }
    1397                 :            : 
    1398   [ #  #  #  # ]:         42 :         newlvol = lvol_alloc(lvs, clone_name, true, (enum lvol_clear_method)origlvol->clear_method);
    1399         [ -  + ]:         42 :         if (!newlvol) {
    1400                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol base pointer\n");
    1401                 :          0 :                 free(req);
    1402   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, NULL, -ENOMEM);
    1403                 :          0 :                 return;
    1404                 :            :         }
    1405                 :            : 
    1406                 :         42 :         clone_xattrs.count = SPDK_COUNTOF(xattr_names);
    1407         [ #  # ]:         42 :         clone_xattrs.ctx = newlvol;
    1408         [ #  # ]:         42 :         clone_xattrs.names = xattr_names;
    1409         [ #  # ]:         42 :         clone_xattrs.get_value = lvol_get_xattr_value;
    1410   [ #  #  #  # ]:         42 :         req->lvol = newlvol;
    1411   [ #  #  #  # ]:         42 :         req->cb_fn = cb_fn;
    1412   [ #  #  #  # ]:         42 :         req->cb_arg = cb_arg;
    1413                 :            : 
    1414   [ #  #  #  # ]:         47 :         spdk_bs_create_clone(lvs->blobstore, spdk_blob_get_id(origblob), &clone_xattrs,
    1415                 :            :                              lvol_create_cb,
    1416                 :          5 :                              req);
    1417                 :          9 : }
    1418                 :            : 
    1419                 :            : static void
    1420                 :         39 : lvol_resize_done(void *cb_arg, int lvolerrno)
    1421                 :            : {
    1422                 :         39 :         struct spdk_lvol_req *req = cb_arg;
    1423                 :            : 
    1424   [ #  #  #  #  :         39 :         req->cb_fn(req->cb_arg,  lvolerrno);
          #  #  #  #  #  
                #  #  # ]
    1425                 :         39 :         free(req);
    1426                 :         39 : }
    1427                 :            : 
    1428                 :            : static void
    1429                 :         48 : lvol_blob_resize_cb(void *cb_arg, int bserrno)
    1430                 :            : {
    1431                 :         48 :         struct spdk_lvol_req *req = cb_arg;
    1432   [ #  #  #  # ]:         48 :         struct spdk_lvol *lvol = req->lvol;
    1433                 :            : 
    1434         [ +  + ]:         48 :         if (bserrno != 0) {
    1435   [ #  #  #  #  :          9 :                 req->cb_fn(req->cb_arg, bserrno);
          #  #  #  #  #  
                #  #  # ]
    1436                 :          9 :                 free(req);
    1437                 :          9 :                 return;
    1438                 :            :         }
    1439                 :            : 
    1440   [ #  #  #  # ]:         39 :         spdk_blob_sync_md(lvol->blob, lvol_resize_done, req);
    1441                 :          6 : }
    1442                 :            : 
    1443                 :            : void
    1444                 :         48 : spdk_lvol_resize(struct spdk_lvol *lvol, uint64_t sz,
    1445                 :            :                  spdk_lvol_op_complete cb_fn, void *cb_arg)
    1446                 :            : {
    1447   [ #  #  #  # ]:         48 :         struct spdk_blob *blob = lvol->blob;
    1448   [ #  #  #  # ]:         48 :         struct spdk_lvol_store *lvs = lvol->lvol_store;
    1449                 :            :         struct spdk_lvol_req *req;
    1450   [ #  #  #  # ]:         48 :         uint64_t new_clusters = spdk_divide_round_up(sz, spdk_bs_get_cluster_size(lvs->blobstore));
    1451                 :            : 
    1452                 :         48 :         req = calloc(1, sizeof(*req));
    1453         [ -  + ]:         48 :         if (!req) {
    1454                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
    1455   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, -ENOMEM);
    1456                 :          0 :                 return;
    1457                 :            :         }
    1458   [ #  #  #  # ]:         48 :         req->cb_fn = cb_fn;
    1459   [ #  #  #  # ]:         48 :         req->cb_arg = cb_arg;
    1460   [ #  #  #  # ]:         48 :         req->lvol = lvol;
    1461                 :            : 
    1462                 :         48 :         spdk_blob_resize(blob, new_clusters, lvol_blob_resize_cb, req);
    1463                 :          6 : }
    1464                 :            : 
    1465                 :            : static void
    1466                 :          8 : lvol_set_read_only_cb(void *cb_arg, int lvolerrno)
    1467                 :            : {
    1468                 :          8 :         struct spdk_lvol_req *req = cb_arg;
    1469                 :            : 
    1470   [ #  #  #  #  :          8 :         req->cb_fn(req->cb_arg, lvolerrno);
          #  #  #  #  #  
                #  #  # ]
    1471                 :          8 :         free(req);
    1472                 :          8 : }
    1473                 :            : 
    1474                 :            : void
    1475                 :          8 : spdk_lvol_set_read_only(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_arg)
    1476                 :            : {
    1477                 :            :         struct spdk_lvol_req *req;
    1478                 :            : 
    1479                 :          8 :         req = calloc(1, sizeof(*req));
    1480         [ -  + ]:          8 :         if (!req) {
    1481                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
    1482   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, -ENOMEM);
    1483                 :          0 :                 return;
    1484                 :            :         }
    1485   [ #  #  #  # ]:          8 :         req->cb_fn = cb_fn;
    1486   [ #  #  #  # ]:          8 :         req->cb_arg = cb_arg;
    1487                 :            : 
    1488   [ #  #  #  # ]:          8 :         spdk_blob_set_read_only(lvol->blob);
    1489   [ #  #  #  # ]:          8 :         spdk_blob_sync_md(lvol->blob, lvol_set_read_only_cb, req);
    1490                 :          1 : }
    1491                 :            : 
    1492                 :            : static void
    1493                 :          8 : lvol_rename_cb(void *cb_arg, int lvolerrno)
    1494                 :            : {
    1495                 :          8 :         struct spdk_lvol_req *req = cb_arg;
    1496                 :            : 
    1497         [ -  + ]:          8 :         if (lvolerrno != 0) {
    1498                 :          0 :                 SPDK_ERRLOG("Lvol rename operation failed\n");
    1499                 :          0 :         } else {
    1500   [ -  +  #  #  :          8 :                 snprintf(req->lvol->name, sizeof(req->lvol->name), "%s", req->name);
             #  #  #  # ]
    1501                 :            :         }
    1502                 :            : 
    1503   [ #  #  #  #  :          8 :         req->cb_fn(req->cb_arg, lvolerrno);
          #  #  #  #  #  
                #  #  # ]
    1504                 :          8 :         free(req);
    1505                 :          8 : }
    1506                 :            : 
    1507                 :            : void
    1508                 :         12 : spdk_lvol_rename(struct spdk_lvol *lvol, const char *new_name,
    1509                 :            :                  spdk_lvol_op_complete cb_fn, void *cb_arg)
    1510                 :            : {
    1511                 :            :         struct spdk_lvol *tmp;
    1512   [ #  #  #  # ]:         12 :         struct spdk_blob *blob = lvol->blob;
    1513                 :            :         struct spdk_lvol_req *req;
    1514                 :            :         int rc;
    1515                 :            : 
    1516                 :            :         /* Check if new name is current lvol name.
    1517                 :            :          * If so, return success immediately */
    1518   [ +  +  -  +  :         12 :         if (strncmp(lvol->name, new_name, SPDK_LVOL_NAME_MAX) == 0) {
             -  +  #  # ]
    1519   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, 0);
    1520                 :          0 :                 return;
    1521                 :            :         }
    1522                 :            : 
    1523                 :            :         /* Check if lvol with 'new_name' already exists in lvolstore */
    1524   [ +  +  #  #  :         36 :         TAILQ_FOREACH(tmp, &lvol->lvol_store->lvols, link) {
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
    1525   [ +  +  -  +  :         28 :                 if (strncmp(tmp->name, new_name, SPDK_LVOL_NAME_MAX) == 0) {
             +  +  #  # ]
    1526   [ #  #  #  #  :          4 :                         SPDK_ERRLOG("Lvol %s already exists in lvol store %s\n", new_name, lvol->lvol_store->name);
                   #  # ]
    1527   [ #  #  #  # ]:          4 :                         cb_fn(cb_arg, -EEXIST);
    1528                 :          4 :                         return;
    1529                 :            :                 }
    1530                 :          2 :         }
    1531                 :            : 
    1532                 :          8 :         req = calloc(1, sizeof(*req));
    1533         [ +  + ]:          8 :         if (!req) {
    1534                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
    1535   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, -ENOMEM);
    1536                 :          0 :                 return;
    1537                 :            :         }
    1538   [ #  #  #  # ]:          8 :         req->cb_fn = cb_fn;
    1539   [ #  #  #  # ]:          8 :         req->cb_arg = cb_arg;
    1540   [ #  #  #  # ]:          8 :         req->lvol = lvol;
    1541         [ #  # ]:          8 :         snprintf(req->name, sizeof(req->name), "%s", new_name);
    1542                 :            : 
    1543         [ -  + ]:          8 :         rc = spdk_blob_set_xattr(blob, "name", new_name, strlen(new_name) + 1);
    1544         [ -  + ]:          8 :         if (rc < 0) {
    1545                 :          0 :                 free(req);
    1546   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, rc);
    1547                 :          0 :                 return;
    1548                 :            :         }
    1549                 :            : 
    1550                 :          8 :         spdk_blob_sync_md(blob, lvol_rename_cb, req);
    1551                 :          2 : }
    1552                 :            : 
    1553                 :            : void
    1554                 :        506 : spdk_lvol_destroy(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_arg)
    1555                 :            : {
    1556                 :            :         struct spdk_lvol_req *req;
    1557                 :            :         struct spdk_blob_store *bs;
    1558                 :            :         struct spdk_lvol_store  *lvs;
    1559                 :        335 :         spdk_blob_id    clone_id;
    1560                 :        506 :         size_t          count = 1;
    1561                 :            :         int             rc;
    1562                 :            : 
    1563   [ +  +  #  # ]:        506 :         assert(cb_fn != NULL);
    1564                 :            : 
    1565         [ +  + ]:        506 :         if (lvol == NULL) {
    1566                 :          0 :                 SPDK_ERRLOG("lvol does not exist\n");
    1567   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, -ENODEV);
    1568                 :          0 :                 return;
    1569                 :            :         }
    1570                 :            : 
    1571   [ #  #  #  # ]:        506 :         lvs = lvol->lvol_store;
    1572                 :            : 
    1573   [ +  +  #  #  :        506 :         if (lvol->ref_count != 0) {
                   #  # ]
    1574         [ #  # ]:          4 :                 SPDK_ERRLOG("Cannot destroy lvol %s because it is still open\n", lvol->unique_id);
    1575   [ #  #  #  # ]:          4 :                 cb_fn(cb_arg, -EBUSY);
    1576                 :          4 :                 return;
    1577                 :            :         }
    1578                 :            : 
    1579                 :        502 :         req = calloc(1, sizeof(*req));
    1580         [ +  + ]:        502 :         if (!req) {
    1581                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
    1582   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, -ENOMEM);
    1583                 :          0 :                 return;
    1584                 :            :         }
    1585                 :            : 
    1586   [ #  #  #  # ]:        502 :         req->cb_fn = cb_fn;
    1587   [ #  #  #  # ]:        502 :         req->cb_arg = cb_arg;
    1588   [ #  #  #  # ]:        502 :         req->lvol = lvol;
    1589   [ #  #  #  #  :        502 :         bs = lvol->lvol_store->blobstore;
             #  #  #  # ]
    1590                 :            : 
    1591   [ #  #  #  #  :        502 :         rc = spdk_blob_get_clones(lvs->blobstore, lvol->blob_id, &clone_id, &count);
             #  #  #  # ]
    1592   [ +  -  +  + ]:        502 :         if (rc == 0 && count == 1) {
    1593   [ #  #  #  # ]:         12 :                 req->clone_lvol = lvs_get_lvol_by_blob_id(lvs, clone_id);
    1594         [ -  + ]:        491 :         } else if (rc == -ENOMEM) {
    1595   [ #  #  #  #  :          0 :                 SPDK_INFOLOG(lvol, "lvol %s: cannot destroy: has %" PRIu64 " clones\n",
             #  #  #  # ]
    1596                 :            :                              lvol->unique_id, count);
    1597                 :          0 :                 free(req);
    1598   [ #  #  #  # ]:          0 :                 assert(count > 1);
    1599   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, -EBUSY);
    1600                 :          0 :                 return;
    1601                 :            :         }
    1602                 :            : 
    1603   [ #  #  #  # ]:        502 :         lvol->action_in_progress = true;
    1604                 :            : 
    1605   [ #  #  #  # ]:        502 :         spdk_bs_delete_blob(bs, lvol->blob_id, lvol_delete_blob_cb, req);
    1606                 :         61 : }
    1607                 :            : 
    1608                 :            : void
    1609                 :        765 : spdk_lvol_close(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_arg)
    1610                 :            : {
    1611                 :            :         struct spdk_lvol_req *req;
    1612                 :            : 
    1613   [ +  +  #  # ]:        765 :         assert(cb_fn != NULL);
    1614                 :            : 
    1615         [ +  + ]:        765 :         if (lvol == NULL) {
    1616                 :          4 :                 SPDK_ERRLOG("lvol does not exist\n");
    1617   [ #  #  #  # ]:          4 :                 cb_fn(cb_arg, -ENODEV);
    1618                 :          4 :                 return;
    1619                 :            :         }
    1620                 :            : 
    1621   [ +  +  #  #  :        761 :         if (lvol->ref_count > 1) {
                   #  # ]
    1622   [ #  #  #  # ]:          4 :                 lvol->ref_count--;
    1623   [ #  #  #  # ]:          4 :                 cb_fn(cb_arg, 0);
    1624                 :          4 :                 return;
    1625   [ +  +  #  #  :        757 :         } else if (lvol->ref_count == 0) {
                   #  # ]
    1626   [ #  #  #  # ]:          8 :                 cb_fn(cb_arg, -EINVAL);
    1627                 :          8 :                 return;
    1628                 :            :         }
    1629                 :            : 
    1630                 :        749 :         req = calloc(1, sizeof(*req));
    1631         [ +  + ]:        749 :         if (!req) {
    1632                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
    1633   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, -ENOMEM);
    1634                 :          0 :                 return;
    1635                 :            :         }
    1636                 :            : 
    1637   [ #  #  #  # ]:        749 :         req->cb_fn = cb_fn;
    1638   [ #  #  #  # ]:        749 :         req->cb_arg = cb_arg;
    1639   [ #  #  #  # ]:        749 :         req->lvol = lvol;
    1640                 :            : 
    1641   [ #  #  #  # ]:        749 :         lvol->action_in_progress = true;
    1642                 :            : 
    1643   [ #  #  #  # ]:        749 :         spdk_blob_close(lvol->blob, lvol_close_blob_cb, req);
    1644                 :         92 : }
    1645                 :            : 
    1646                 :            : struct spdk_io_channel *
    1647                 :        708 : spdk_lvol_get_io_channel(struct spdk_lvol *lvol)
    1648                 :            : {
    1649   [ #  #  #  #  :        708 :         return spdk_bs_alloc_io_channel(lvol->lvol_store->blobstore);
             #  #  #  # ]
    1650                 :            : }
    1651                 :            : 
    1652                 :            : static void
    1653                 :         26 : lvol_inflate_cb(void *cb_arg, int lvolerrno)
    1654                 :            : {
    1655                 :         26 :         struct spdk_lvol_req *req = cb_arg;
    1656                 :            : 
    1657   [ #  #  #  # ]:         26 :         spdk_bs_free_io_channel(req->channel);
    1658                 :            : 
    1659         [ +  + ]:         26 :         if (lvolerrno < 0) {
    1660                 :          9 :                 SPDK_ERRLOG("Could not inflate lvol\n");
    1661                 :          2 :         }
    1662                 :            : 
    1663   [ #  #  #  #  :         26 :         req->cb_fn(req->cb_arg, lvolerrno);
          #  #  #  #  #  
                #  #  # ]
    1664                 :         26 :         free(req);
    1665                 :         26 : }
    1666                 :            : 
    1667                 :            : void
    1668                 :         15 : spdk_lvol_inflate(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_arg)
    1669                 :            : {
    1670                 :            :         struct spdk_lvol_req *req;
    1671                 :            :         spdk_blob_id blob_id;
    1672                 :            : 
    1673   [ +  +  #  # ]:         15 :         assert(cb_fn != NULL);
    1674                 :            : 
    1675         [ +  + ]:         15 :         if (lvol == NULL) {
    1676                 :          0 :                 SPDK_ERRLOG("Lvol does not exist\n");
    1677   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, -ENODEV);
    1678                 :          0 :                 return;
    1679                 :            :         }
    1680                 :            : 
    1681                 :         15 :         req = calloc(1, sizeof(*req));
    1682         [ +  + ]:         15 :         if (!req) {
    1683                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
    1684   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, -ENOMEM);
    1685                 :          0 :                 return;
    1686                 :            :         }
    1687                 :            : 
    1688   [ #  #  #  # ]:         15 :         req->cb_fn = cb_fn;
    1689   [ #  #  #  # ]:         15 :         req->cb_arg = cb_arg;
    1690   [ #  #  #  #  :         15 :         req->channel = spdk_bs_alloc_io_channel(lvol->lvol_store->blobstore);
          #  #  #  #  #  
                #  #  # ]
    1691   [ +  +  #  #  :         15 :         if (req->channel == NULL) {
                   #  # ]
    1692                 :          0 :                 SPDK_ERRLOG("Cannot alloc io channel for lvol inflate request\n");
    1693                 :          0 :                 free(req);
    1694   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, -ENOMEM);
    1695                 :          0 :                 return;
    1696                 :            :         }
    1697                 :            : 
    1698   [ #  #  #  # ]:         15 :         blob_id = spdk_blob_get_id(lvol->blob);
    1699   [ #  #  #  #  :         17 :         spdk_bs_inflate_blob(lvol->lvol_store->blobstore, req->channel, blob_id, lvol_inflate_cb,
          #  #  #  #  #  
                #  #  # ]
    1700                 :          2 :                              req);
    1701                 :          2 : }
    1702                 :            : 
    1703                 :            : void
    1704                 :         11 : spdk_lvol_decouple_parent(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_arg)
    1705                 :            : {
    1706                 :            :         struct spdk_lvol_req *req;
    1707                 :            :         spdk_blob_id blob_id;
    1708                 :            : 
    1709   [ +  +  #  # ]:         11 :         assert(cb_fn != NULL);
    1710                 :            : 
    1711         [ +  + ]:         11 :         if (lvol == NULL) {
    1712                 :          0 :                 SPDK_ERRLOG("Lvol does not exist\n");
    1713   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, -ENODEV);
    1714                 :          0 :                 return;
    1715                 :            :         }
    1716                 :            : 
    1717                 :         11 :         req = calloc(1, sizeof(*req));
    1718         [ +  + ]:         11 :         if (!req) {
    1719                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
    1720   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, -ENOMEM);
    1721                 :          0 :                 return;
    1722                 :            :         }
    1723                 :            : 
    1724   [ #  #  #  # ]:         11 :         req->cb_fn = cb_fn;
    1725   [ #  #  #  # ]:         11 :         req->cb_arg = cb_arg;
    1726   [ #  #  #  #  :         11 :         req->channel = spdk_bs_alloc_io_channel(lvol->lvol_store->blobstore);
          #  #  #  #  #  
                #  #  # ]
    1727   [ +  +  #  #  :         11 :         if (req->channel == NULL) {
                   #  # ]
    1728                 :          0 :                 SPDK_ERRLOG("Cannot alloc io channel for lvol inflate request\n");
    1729                 :          0 :                 free(req);
    1730   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, -ENOMEM);
    1731                 :          0 :                 return;
    1732                 :            :         }
    1733                 :            : 
    1734   [ #  #  #  # ]:         11 :         blob_id = spdk_blob_get_id(lvol->blob);
    1735   [ #  #  #  #  :         13 :         spdk_bs_blob_decouple_parent(lvol->lvol_store->blobstore, req->channel, blob_id,
          #  #  #  #  #  
                #  #  # ]
    1736                 :          2 :                                      lvol_inflate_cb, req);
    1737                 :          2 : }
    1738                 :            : 
    1739                 :            : static void
    1740                 :          2 : lvs_grow_live_cb(void *cb_arg, int lvolerrno)
    1741                 :            : {
    1742                 :          2 :         struct spdk_lvs_req *req = (struct spdk_lvs_req *)cb_arg;
    1743                 :            : 
    1744   [ +  -  #  #  :          2 :         if (req->cb_fn) {
                   #  # ]
    1745   [ #  #  #  #  :          2 :                 req->cb_fn(req->cb_arg, lvolerrno);
          #  #  #  #  #  
                #  #  # ]
    1746                 :          0 :         }
    1747                 :          2 :         free(req);
    1748                 :          2 :         return;
    1749                 :            : }
    1750                 :            : 
    1751                 :            : void
    1752                 :          2 : spdk_lvs_grow_live(struct spdk_lvol_store *lvs, spdk_lvs_op_complete cb_fn, void *cb_arg)
    1753                 :            : {
    1754                 :            :         struct spdk_lvs_req *req;
    1755                 :            : 
    1756                 :          2 :         req = calloc(1, sizeof(*req));
    1757         [ -  + ]:          2 :         if (req == NULL) {
    1758                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for request structure\n");
    1759         [ #  # ]:          0 :                 if (cb_fn) {
    1760   [ #  #  #  # ]:          0 :                         cb_fn(cb_arg, -ENOMEM);
    1761                 :          0 :                 }
    1762                 :          0 :                 return;
    1763                 :            :         }
    1764                 :            : 
    1765   [ #  #  #  # ]:          2 :         req->cb_fn = cb_fn;
    1766   [ #  #  #  # ]:          2 :         req->cb_arg = cb_arg;
    1767   [ #  #  #  # ]:          2 :         req->lvol_store = lvs;
    1768                 :            : 
    1769   [ #  #  #  # ]:          2 :         spdk_bs_grow_live(lvs->blobstore, lvs_grow_live_cb, req);
    1770                 :          0 : }
    1771                 :            : 
    1772                 :            : void
    1773                 :          0 : spdk_lvs_grow(struct spdk_bs_dev *bs_dev, spdk_lvs_op_with_handle_complete cb_fn, void *cb_arg)
    1774                 :            : {
    1775                 :            :         struct spdk_lvs_with_handle_req *req;
    1776                 :          0 :         struct spdk_bs_opts opts = {};
    1777                 :            : 
    1778   [ #  #  #  # ]:          0 :         assert(cb_fn != NULL);
    1779                 :            : 
    1780         [ #  # ]:          0 :         if (bs_dev == NULL) {
    1781                 :          0 :                 SPDK_ERRLOG("Blobstore device does not exist\n");
    1782   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, NULL, -ENODEV);
    1783                 :          0 :                 return;
    1784                 :            :         }
    1785                 :            : 
    1786                 :          0 :         req = calloc(1, sizeof(*req));
    1787         [ #  # ]:          0 :         if (req == NULL) {
    1788                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for request structure\n");
    1789   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, NULL, -ENOMEM);
    1790                 :          0 :                 return;
    1791                 :            :         }
    1792                 :            : 
    1793   [ #  #  #  # ]:          0 :         req->lvol_store = lvs_alloc();
    1794   [ #  #  #  #  :          0 :         if (req->lvol_store == NULL) {
                   #  # ]
    1795                 :          0 :                 SPDK_ERRLOG("Cannot alloc memory for lvol store\n");
    1796                 :          0 :                 free(req);
    1797   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, NULL, -ENOMEM);
    1798                 :          0 :                 return;
    1799                 :            :         }
    1800   [ #  #  #  # ]:          0 :         req->cb_fn = cb_fn;
    1801   [ #  #  #  # ]:          0 :         req->cb_arg = cb_arg;
    1802   [ #  #  #  # ]:          0 :         req->bs_dev = bs_dev;
    1803                 :            : 
    1804                 :          0 :         lvs_bs_opts_init(&opts);
    1805         [ #  # ]:          0 :         snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "LVOLSTORE");
    1806                 :            : 
    1807                 :          0 :         spdk_bs_grow(bs_dev, &opts, lvs_load_cb, req);
    1808                 :          0 : }
    1809                 :            : 
    1810                 :            : static struct spdk_lvol *
    1811                 :         47 : lvs_get_lvol_by_blob_id(struct spdk_lvol_store *lvs, spdk_blob_id blob_id)
    1812                 :            : {
    1813                 :            :         struct spdk_lvol *lvol;
    1814                 :            : 
    1815   [ +  -  #  #  :         64 :         TAILQ_FOREACH(lvol, &lvs->lvols, link) {
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1816   [ +  +  #  #  :         64 :                 if (lvol->blob_id == blob_id) {
                   #  # ]
    1817                 :         47 :                         return lvol;
    1818                 :            :                 }
    1819                 :          2 :         }
    1820                 :          0 :         return NULL;
    1821                 :          5 : }
    1822                 :            : 
    1823                 :            : static int
    1824                 :         91 : lvs_esnap_bs_dev_create(void *bs_ctx, void *blob_ctx, struct spdk_blob *blob,
    1825                 :            :                         const void *esnap_id, uint32_t id_len,
    1826                 :            :                         struct spdk_bs_dev **bs_dev)
    1827                 :            : {
    1828                 :         91 :         struct spdk_lvol_store  *lvs = bs_ctx;
    1829                 :         91 :         struct spdk_lvol        *lvol = blob_ctx;
    1830                 :         91 :         spdk_blob_id            blob_id = spdk_blob_get_id(blob);
    1831                 :            : 
    1832         [ +  + ]:         91 :         if (lvs == NULL) {
    1833   [ +  +  -  +  :          8 :                 if (lvol == NULL || lvol->lvol_store == NULL) {
             #  #  #  # ]
    1834                 :          4 :                         SPDK_ERRLOG("Blob 0x%" PRIx64 ": no lvs context nor lvol context\n",
    1835                 :            :                                     blob_id);
    1836                 :          4 :                         return -EINVAL;
    1837                 :            :                 }
    1838   [ #  #  #  # ]:          4 :                 lvs = lvol->lvol_store;
    1839                 :          1 :         }
    1840                 :            : 
    1841                 :            :         /*
    1842                 :            :          * When spdk_lvs_load() is called, it iterates through all blobs in its blobstore building
    1843                 :            :          * up a list of lvols (lvs->lvols). During this initial iteration, each blob is opened,
    1844                 :            :          * passed to load_next_lvol(), then closed. There is no need to open the external snapshot
    1845                 :            :          * during this phase. Once the blobstore is loaded, lvs->load_esnaps is set to true so that
    1846                 :            :          * future lvol opens cause the external snapshot to be loaded.
    1847                 :            :          */
    1848   [ +  +  +  +  :         87 :         if (!lvs->load_esnaps) {
             #  #  #  # ]
    1849         [ #  # ]:         60 :                 *bs_dev = NULL;
    1850                 :         60 :                 return 0;
    1851                 :            :         }
    1852                 :            : 
    1853         [ +  + ]:         27 :         if (lvol == NULL) {
    1854                 :         17 :                 spdk_blob_id blob_id = spdk_blob_get_id(blob);
    1855                 :            : 
    1856                 :            :                 /*
    1857                 :            :                  * If spdk_bs_blob_open() is used instead of spdk_bs_blob_open_ext() the lvol will
    1858                 :            :                  * not have been passed in. The same is true if the open happens spontaneously due
    1859                 :            :                  * to blobstore activity.
    1860                 :            :                  */
    1861                 :         17 :                 lvol = lvs_get_lvol_by_blob_id(lvs, blob_id);
    1862         [ -  + ]:         17 :                 if (lvol == NULL) {
    1863         [ #  # ]:          0 :                         SPDK_ERRLOG("lvstore %s: no lvol for blob 0x%" PRIx64 "\n",
    1864                 :            :                                     lvs->name, blob_id);
    1865                 :          0 :                         return -ENODEV;
    1866                 :            :                 }
    1867                 :          0 :         }
    1868                 :            : 
    1869   [ #  #  #  #  :         27 :         return lvs->esnap_bs_dev_create(lvs, lvol, blob, esnap_id, id_len, bs_dev);
             #  #  #  # ]
    1870                 :          6 : }
    1871                 :            : 
    1872                 :            : /*
    1873                 :            :  * The theory of missing external snapshots
    1874                 :            :  *
    1875                 :            :  * The lvs->esnap_bs_dev_create() callback may be unable to create an external snapshot bs_dev when
    1876                 :            :  * it is called. This can happen, for instance, as when the device containing the lvolstore is
    1877                 :            :  * examined prior to spdk_bdev_register() being called on a bdev that acts as an external snapshot.
    1878                 :            :  * In such a case, the esnap_bs_dev_create() callback will call spdk_lvs_esnap_missing_add().
    1879                 :            :  *
    1880                 :            :  * Missing external snapshots are tracked in a per-lvolstore tree, lvs->degraded_lvol_sets_tree.
    1881                 :            :  * Each tree node (struct spdk_lvs_degraded_lvol_set) contains a tailq of lvols that are missing
    1882                 :            :  * that particular external snapshot.
    1883                 :            :  *
    1884                 :            :  * When a potential missing snapshot becomes available, spdk_lvs_notify_hotplug() may be called to
    1885                 :            :  * notify this library that it is available. It will then iterate through the active lvolstores and
    1886                 :            :  * search each lvs->degraded_lvol_sets_tree for a set of degraded lvols that are missing an external
    1887                 :            :  * snapshot matching the id passed in the notification. The lvols in the tailq on each matching tree
    1888                 :            :  * node are then asked to create an external snapshot bs_dev using the esnap_bs_dev_create()
    1889                 :            :  * callback that the consumer registered with the lvolstore. If lvs->esnap_bs_dev_create() returns
    1890                 :            :  * 0, the lvol is removed from the spdk_lvs_degraded_lvol_set's lvol tailq. When this tailq becomes
    1891                 :            :  * empty, the degraded lvol set node for this missing external snapshot is removed.
    1892                 :            :  */
    1893                 :            : static int
    1894                 :        375 : lvs_esnap_name_cmp(struct spdk_lvs_degraded_lvol_set *m1, struct spdk_lvs_degraded_lvol_set *m2)
    1895                 :            : {
    1896   [ +  -  #  #  :        375 :         if (m1->id_len == m2->id_len) {
          #  #  #  #  #  
                      # ]
    1897   [ -  +  -  +  :        375 :                 return memcmp(m1->esnap_id, m2->esnap_id, m1->id_len);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    1898                 :            :         }
    1899   [ #  #  #  #  :          0 :         return (m1->id_len > m2->id_len) ? 1 : -1;
             #  #  #  # ]
    1900                 :         93 : }
    1901                 :            : 
    1902   [ +  +  +  +  :       1664 : RB_GENERATE_STATIC(degraded_lvol_sets_tree, spdk_lvs_degraded_lvol_set, node, lvs_esnap_name_cmp)
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  -  
          +  -  -  -  -  
          -  +  +  +  +  
          -  +  +  +  +  
          +  +  +  +  +  
          -  -  -  -  -  
          -  -  +  +  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  +  -  
          +  -  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          +  -  -  +  -  
          +  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  +  +  -  
          +  +  +  +  -  
          +  +  -  +  +  
          +  +  +  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
    1903                 :            : 
    1904                 :            : static void
    1905                 :        160 : lvs_degraded_lvol_set_add(struct spdk_lvs_degraded_lvol_set *degraded_set, struct spdk_lvol *lvol)
    1906                 :            : {
    1907   [ +  +  #  #  :        160 :         assert(lvol->lvol_store->thread == spdk_get_thread());
          #  #  #  #  #  
                #  #  # ]
    1908                 :            : 
    1909   [ #  #  #  # ]:        160 :         lvol->degraded_set = degraded_set;
    1910   [ #  #  #  #  :        160 :         TAILQ_INSERT_TAIL(&degraded_set->lvols, lvol, degraded_link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    1911                 :        160 : }
    1912                 :            : 
    1913                 :            : static void
    1914                 :         57 : lvs_degraded_lvol_set_remove(struct spdk_lvs_degraded_lvol_set *degraded_set,
    1915                 :            :                              struct spdk_lvol *lvol)
    1916                 :            : {
    1917   [ +  +  #  #  :         57 :         assert(lvol->lvol_store->thread == spdk_get_thread());
          #  #  #  #  #  
                #  #  # ]
    1918                 :            : 
    1919   [ #  #  #  # ]:         57 :         lvol->degraded_set = NULL;
    1920   [ +  +  #  #  :         57 :         TAILQ_REMOVE(&degraded_set->lvols, lvol, degraded_link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
    1921                 :            :         /* degraded_set->lvols may be empty. Caller should check if not immediately adding a new
    1922                 :            :          * lvol. */
    1923                 :         57 : }
    1924                 :            : 
    1925                 :            : /*
    1926                 :            :  * Record in lvs->degraded_lvol_sets_tree that a bdev of the specified name is needed by the
    1927                 :            :  * specified lvol.
    1928                 :            :  */
    1929                 :            : int
    1930                 :        151 : spdk_lvs_esnap_missing_add(struct spdk_lvol_store *lvs, struct spdk_lvol *lvol,
    1931                 :            :                            const void *esnap_id, uint32_t id_len)
    1932                 :            : {
    1933                 :        115 :         struct spdk_lvs_degraded_lvol_set find, *degraded_set;
    1934                 :            : 
    1935   [ +  +  #  #  :        151 :         assert(lvs->thread == spdk_get_thread());
             #  #  #  # ]
    1936                 :            : 
    1937         [ #  # ]:        151 :         find.esnap_id = esnap_id;
    1938         [ #  # ]:        151 :         find.id_len = id_len;
    1939         [ #  # ]:        151 :         degraded_set = RB_FIND(degraded_lvol_sets_tree, &lvs->degraded_lvol_sets_tree, &find);
    1940         [ +  + ]:        151 :         if (degraded_set == NULL) {
    1941                 :         71 :                 degraded_set = calloc(1, sizeof(*degraded_set));
    1942         [ +  + ]:         71 :                 if (degraded_set == NULL) {
    1943         [ #  # ]:          0 :                         SPDK_ERRLOG("lvol %s: cannot create degraded_set node: out of memory\n",
    1944                 :            :                                     lvol->unique_id);
    1945                 :          0 :                         return -ENOMEM;
    1946                 :            :                 }
    1947   [ #  #  #  # ]:         71 :                 degraded_set->esnap_id = calloc(1, id_len);
    1948   [ +  +  #  #  :         71 :                 if (degraded_set->esnap_id == NULL) {
                   #  # ]
    1949                 :          0 :                         free(degraded_set);
    1950         [ #  # ]:          0 :                         SPDK_ERRLOG("lvol %s: cannot create degraded_set node: out of memory\n",
    1951                 :            :                                     lvol->unique_id);
    1952                 :          0 :                         return -ENOMEM;
    1953                 :            :                 }
    1954   [ -  +  -  +  :         71 :                 memcpy((void *)degraded_set->esnap_id, esnap_id, id_len);
             #  #  #  # ]
    1955   [ #  #  #  # ]:         71 :                 degraded_set->id_len = id_len;
    1956   [ #  #  #  # ]:         71 :                 degraded_set->lvol_store = lvs;
    1957   [ #  #  #  #  :         71 :                 TAILQ_INIT(&degraded_set->lvols);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    1958         [ #  # ]:         71 :                 RB_INSERT(degraded_lvol_sets_tree, &lvs->degraded_lvol_sets_tree, degraded_set);
    1959                 :         16 :         }
    1960                 :            : 
    1961                 :        151 :         lvs_degraded_lvol_set_add(degraded_set, lvol);
    1962                 :            : 
    1963                 :        151 :         return 0;
    1964                 :         36 : }
    1965                 :            : 
    1966                 :            : /*
    1967                 :            :  * Remove the record of the specified lvol needing a degraded_set bdev.
    1968                 :            :  */
    1969                 :            : void
    1970                 :        293 : spdk_lvs_esnap_missing_remove(struct spdk_lvol *lvol)
    1971                 :            : {
    1972   [ #  #  #  # ]:        293 :         struct spdk_lvol_store          *lvs = lvol->lvol_store;
    1973   [ #  #  #  # ]:        293 :         struct spdk_lvs_degraded_lvol_set       *degraded_set = lvol->degraded_set;
    1974                 :            : 
    1975   [ +  +  #  #  :        293 :         assert(lvs->thread == spdk_get_thread());
             #  #  #  # ]
    1976                 :            : 
    1977         [ +  + ]:        293 :         if (degraded_set == NULL) {
    1978                 :        245 :                 return;
    1979                 :            :         }
    1980                 :            : 
    1981                 :         48 :         lvs_degraded_lvol_set_remove(degraded_set, lvol);
    1982                 :            : 
    1983   [ +  +  #  #  :         48 :         if (!TAILQ_EMPTY(&degraded_set->lvols)) {
             #  #  #  # ]
    1984                 :          4 :                 return;
    1985                 :            :         }
    1986                 :            : 
    1987         [ #  # ]:         44 :         RB_REMOVE(degraded_lvol_sets_tree, &lvs->degraded_lvol_sets_tree, degraded_set);
    1988                 :            : 
    1989   [ #  #  #  # ]:         44 :         free((char *)degraded_set->esnap_id);
    1990                 :         44 :         free(degraded_set);
    1991                 :         39 : }
    1992                 :            : 
    1993                 :            : struct lvs_esnap_hotplug_req {
    1994                 :            :         struct spdk_lvol                        *lvol;
    1995                 :            :         spdk_lvol_op_with_handle_complete       cb_fn;
    1996                 :            :         void                                    *cb_arg;
    1997                 :            : };
    1998                 :            : 
    1999                 :            : static void
    2000                 :        103 : lvs_esnap_hotplug_done(void *cb_arg, int bserrno)
    2001                 :            : {
    2002                 :        103 :         struct lvs_esnap_hotplug_req *req = cb_arg;
    2003   [ #  #  #  # ]:        103 :         struct spdk_lvol        *lvol = req->lvol;
    2004   [ #  #  #  # ]:        103 :         struct spdk_lvol_store  *lvs = lvol->lvol_store;
    2005                 :            : 
    2006         [ -  + ]:        103 :         if (bserrno != 0) {
    2007   [ #  #  #  # ]:          0 :                 SPDK_ERRLOG("lvol %s/%s: failed to hotplug blob_bdev due to error %d\n",
    2008                 :            :                             lvs->name, lvol->name, bserrno);
    2009                 :          0 :         }
    2010   [ #  #  #  #  :        103 :         req->cb_fn(req->cb_arg, lvol, bserrno);
          #  #  #  #  #  
                #  #  # ]
    2011                 :        103 :         free(req);
    2012                 :        103 : }
    2013                 :            : 
    2014                 :            : static void
    2015                 :         63 : lvs_esnap_degraded_hotplug(struct spdk_lvs_degraded_lvol_set *degraded_set,
    2016                 :            :                            spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg)
    2017                 :            : {
    2018   [ #  #  #  # ]:         63 :         struct spdk_lvol_store  *lvs = degraded_set->lvol_store;
    2019                 :            :         struct spdk_lvol        *lvol, *tmp, *last_missing;
    2020                 :         48 :         struct spdk_bs_dev      *bs_dev;
    2021   [ #  #  #  # ]:         63 :         const void              *esnap_id = degraded_set->esnap_id;
    2022   [ #  #  #  # ]:         63 :         uint32_t                id_len = degraded_set->id_len;
    2023                 :            :         struct lvs_esnap_hotplug_req *req;
    2024                 :            :         int                     rc;
    2025                 :            : 
    2026   [ +  +  #  #  :         63 :         assert(lvs->thread == spdk_get_thread());
             #  #  #  # ]
    2027                 :            : 
    2028                 :            :         /*
    2029                 :            :          * When lvs->esnap_bs_bdev_create() tries to load an external snapshot, it can encounter
    2030                 :            :          * errors that lead it to calling spdk_lvs_esnap_missing_add(). This function needs to be
    2031                 :            :          * sure that such modifications do not lead to degraded_set->lvols tailqs or references
    2032                 :            :          * to memory that this function will free.
    2033                 :            :          *
    2034                 :            :          * While this function is running, no other thread can add items to degraded_set->lvols. If
    2035                 :            :          * the list is mutated, it must have been done by this function or something in its call
    2036                 :            :          * graph running on this thread.
    2037                 :            :          */
    2038                 :            : 
    2039                 :            :         /* Remember the last lvol on the list. Iteration will stop once it has been processed. */
    2040   [ #  #  #  #  :         63 :         last_missing = TAILQ_LAST(&degraded_set->lvols, degraded_lvols);
          #  #  #  #  #  
                #  #  # ]
    2041                 :            : 
    2042   [ +  +  -  +  :        115 :         TAILQ_FOREACH_SAFE(lvol, &degraded_set->lvols, degraded_link, tmp) {
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    2043                 :        115 :                 req = calloc(1, sizeof(*req));
    2044         [ +  + ]:        115 :                 if (req == NULL) {
    2045         [ #  # ]:          0 :                         SPDK_ERRLOG("lvol %s: failed to create esnap bs_dev: out of memory\n",
    2046                 :            :                                     lvol->unique_id);
    2047   [ #  #  #  # ]:          0 :                         cb_fn(cb_arg, lvol, -ENOMEM);
    2048                 :            :                         /* The next one likely won't succeed either, but keep going so that all the
    2049                 :            :                          * failed hotplugs are logged.
    2050                 :            :                          */
    2051                 :          0 :                         goto next;
    2052                 :            :                 }
    2053                 :            : 
    2054                 :            :                 /*
    2055                 :            :                  * Remove the lvol from the tailq so that tailq corruption is avoided if
    2056                 :            :                  * lvs->esnap_bs_dev_create() calls spdk_lvs_esnap_missing_add(lvol).
    2057                 :            :                  */
    2058   [ +  +  #  #  :        115 :                 TAILQ_REMOVE(&degraded_set->lvols, lvol, degraded_link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
    2059   [ #  #  #  # ]:        115 :                 lvol->degraded_set = NULL;
    2060                 :            : 
    2061                 :        115 :                 bs_dev = NULL;
    2062   [ #  #  #  #  :        115 :                 rc = lvs->esnap_bs_dev_create(lvs, lvol, lvol->blob, esnap_id, id_len, &bs_dev);
          #  #  #  #  #  
                #  #  # ]
    2063         [ +  + ]:        115 :                 if (rc != 0) {
    2064         [ #  # ]:         12 :                         SPDK_ERRLOG("lvol %s: failed to create esnap bs_dev: error %d\n",
    2065                 :            :                                     lvol->unique_id, rc);
    2066   [ #  #  #  # ]:         12 :                         lvol->degraded_set = degraded_set;
    2067   [ #  #  #  #  :         12 :                         TAILQ_INSERT_TAIL(&degraded_set->lvols, lvol, degraded_link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    2068   [ #  #  #  # ]:         12 :                         cb_fn(cb_arg, lvol, rc);
    2069                 :         12 :                         free(req);
    2070                 :         12 :                         goto next;
    2071                 :            :                 }
    2072                 :            : 
    2073   [ #  #  #  # ]:        103 :                 req->lvol = lvol;
    2074   [ #  #  #  # ]:        103 :                 req->cb_fn = cb_fn;
    2075   [ #  #  #  # ]:        103 :                 req->cb_arg = cb_arg;
    2076   [ #  #  #  # ]:        103 :                 spdk_blob_set_esnap_bs_dev(lvol->blob, bs_dev, lvs_esnap_hotplug_done, req);
    2077                 :            : 
    2078                 :         87 : next:
    2079         [ +  + ]:        115 :                 if (lvol == last_missing) {
    2080                 :            :                         /*
    2081                 :            :                          * Anything after last_missing was added due to some problem encountered
    2082                 :            :                          * while trying to create the esnap bs_dev.
    2083                 :            :                          */
    2084                 :         63 :                         break;
    2085                 :            :                 }
    2086                 :         13 :         }
    2087                 :            : 
    2088   [ +  +  #  #  :         63 :         if (TAILQ_EMPTY(&degraded_set->lvols)) {
             #  #  #  # ]
    2089         [ #  # ]:         27 :                 RB_REMOVE(degraded_lvol_sets_tree, &lvs->degraded_lvol_sets_tree, degraded_set);
    2090   [ #  #  #  # ]:         27 :                 free((void *)degraded_set->esnap_id);
    2091                 :         27 :                 free(degraded_set);
    2092                 :          6 :         }
    2093                 :         63 : }
    2094                 :            : 
    2095                 :            : /*
    2096                 :            :  * Notify each lvstore created on this thread that is missing a bdev by the specified name or uuid
    2097                 :            :  * that the bdev now exists.
    2098                 :            :  */
    2099                 :            : bool
    2100                 :       5779 : spdk_lvs_notify_hotplug(const void *esnap_id, uint32_t id_len,
    2101                 :            :                         spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg)
    2102                 :            : {
    2103                 :            :         struct spdk_lvs_degraded_lvol_set *found;
    2104                 :       5779 :         struct spdk_lvs_degraded_lvol_set find = { 0 };
    2105                 :            :         struct spdk_lvol_store  *lvs;
    2106                 :       5779 :         struct spdk_thread      *thread = spdk_get_thread();
    2107                 :       5779 :         bool                    ret = false;
    2108                 :            : 
    2109         [ +  - ]:       5779 :         find.esnap_id = esnap_id;
    2110         [ +  - ]:       5779 :         find.id_len = id_len;
    2111                 :            : 
    2112         [ +  + ]:       5779 :         pthread_mutex_lock(&g_lvol_stores_mutex);
    2113   [ +  +  #  #  :       6484 :         TAILQ_FOREACH(lvs, &g_lvol_stores, link) {
             #  #  #  # ]
    2114   [ -  +  #  #  :        705 :                 if (thread != lvs->thread) {
                   #  # ]
    2115                 :            :                         /*
    2116                 :            :                          * It is expected that this is called from vbdev_lvol's examine_config()
    2117                 :            :                          * callback. The lvstore was likely loaded do a creation happening as a
    2118                 :            :                          * result of an RPC call or opening of an existing lvstore via
    2119                 :            :                          * examine_disk() callback. RPC calls, examine_disk(), and examine_config()
    2120                 :            :                          * should all be happening only on the app thread. The "wrong thread"
    2121                 :            :                          * condition will only happen when an application is doing something weird.
    2122                 :            :                          */
    2123         [ #  # ]:          0 :                         SPDK_NOTICELOG("Discarded examine for lvstore %s: wrong thread\n",
    2124                 :            :                                        lvs->name);
    2125                 :          0 :                         continue;
    2126                 :            :                 }
    2127                 :            : 
    2128         [ #  # ]:        705 :                 found = RB_FIND(degraded_lvol_sets_tree, &lvs->degraded_lvol_sets_tree, &find);
    2129         [ +  + ]:        705 :                 if (found == NULL) {
    2130                 :        642 :                         continue;
    2131                 :            :                 }
    2132                 :            : 
    2133                 :         63 :                 ret = true;
    2134                 :         63 :                 lvs_esnap_degraded_hotplug(found, cb_fn, cb_arg);
    2135                 :         15 :         }
    2136         [ +  + ]:       5779 :         pthread_mutex_unlock(&g_lvol_stores_mutex);
    2137                 :            : 
    2138         [ +  - ]:       5779 :         return ret;
    2139                 :            : }
    2140                 :            : 
    2141                 :            : int
    2142                 :         21 : spdk_lvol_iter_immediate_clones(struct spdk_lvol *lvol, spdk_lvol_iter_cb cb_fn, void *cb_arg)
    2143                 :            : {
    2144   [ #  #  #  # ]:         21 :         struct spdk_lvol_store *lvs = lvol->lvol_store;
    2145   [ #  #  #  # ]:         21 :         struct spdk_blob_store *bs = lvs->blobstore;
    2146                 :            :         struct spdk_lvol *clone;
    2147                 :            :         spdk_blob_id *ids;
    2148                 :         21 :         size_t id_cnt = 0;
    2149                 :            :         size_t i;
    2150                 :            :         int rc;
    2151                 :            : 
    2152   [ #  #  #  # ]:         21 :         rc = spdk_blob_get_clones(bs, lvol->blob_id, NULL, &id_cnt);
    2153         [ +  + ]:         21 :         if (rc != -ENOMEM) {
    2154                 :            :                 /* -ENOMEM says id_cnt is valid, no other errors should be returned. */
    2155   [ -  +  #  # ]:          7 :                 assert(rc == 0);
    2156                 :          7 :                 return rc;
    2157                 :            :         }
    2158                 :            : 
    2159                 :         14 :         ids = calloc(id_cnt, sizeof(*ids));
    2160         [ +  + ]:         14 :         if (ids == NULL) {
    2161         [ #  # ]:          0 :                 SPDK_ERRLOG("lvol %s: out of memory while iterating clones\n", lvol->unique_id);
    2162                 :          0 :                 return -ENOMEM;
    2163                 :            :         }
    2164                 :            : 
    2165   [ #  #  #  # ]:         14 :         rc = spdk_blob_get_clones(bs, lvol->blob_id, ids, &id_cnt);
    2166         [ -  + ]:         14 :         if (rc != 0) {
    2167         [ #  # ]:          0 :                 SPDK_ERRLOG("lvol %s: unable to get clone blob IDs: %d\n", lvol->unique_id, rc);
    2168                 :          0 :                 free(ids);
    2169                 :          0 :                 return rc;
    2170                 :            :         }
    2171                 :            : 
    2172         [ +  + ]:         28 :         for (i = 0; i < id_cnt; i++) {
    2173   [ #  #  #  # ]:         18 :                 clone = lvs_get_lvol_by_blob_id(lvs, ids[i]);
    2174         [ +  + ]:         18 :                 if (clone == NULL) {
    2175   [ #  #  #  #  :          0 :                         SPDK_NOTICELOG("lvol %s: unable to find clone lvol with blob id 0x%"
                   #  # ]
    2176                 :            :                                        PRIx64 "\n", lvol->unique_id, ids[i]);
    2177                 :          0 :                         continue;
    2178                 :            :                 }
    2179   [ #  #  #  # ]:         18 :                 rc = cb_fn(cb_arg, clone);
    2180         [ +  + ]:         18 :                 if (rc != 0) {
    2181   [ +  +  -  +  :          4 :                         SPDK_DEBUGLOG(lvol, "lvol %s: iteration stopped when lvol %s (blob 0x%"
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    2182                 :            :                                       PRIx64 ") returned %d\n", lvol->unique_id, clone->unique_id,
    2183                 :            :                                       ids[i], rc);
    2184                 :          4 :                         break;
    2185                 :            :                 }
    2186                 :          3 :         }
    2187                 :            : 
    2188                 :         14 :         free(ids);
    2189                 :         14 :         return rc;
    2190                 :          4 : }
    2191                 :            : 
    2192                 :            : struct spdk_lvol *
    2193                 :         10 : spdk_lvol_get_by_uuid(const struct spdk_uuid *uuid)
    2194                 :            : {
    2195                 :            :         struct spdk_lvol_store *lvs;
    2196                 :            :         struct spdk_lvol *lvol;
    2197                 :            : 
    2198         [ -  + ]:         10 :         pthread_mutex_lock(&g_lvol_stores_mutex);
    2199                 :            : 
    2200   [ +  +  #  #  :         10 :         TAILQ_FOREACH(lvs, &g_lvol_stores, link) {
             #  #  #  # ]
    2201   [ +  -  #  #  :         11 :                 TAILQ_FOREACH(lvol, &lvs->lvols, link) {
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    2202   [ +  +  #  # ]:         11 :                         if (spdk_uuid_compare(uuid, &lvol->uuid) == 0) {
    2203         [ -  + ]:         10 :                                 pthread_mutex_unlock(&g_lvol_stores_mutex);
    2204                 :         10 :                                 return lvol;
    2205                 :            :                         }
    2206                 :          0 :                 }
    2207                 :          0 :         }
    2208                 :            : 
    2209         [ #  # ]:          0 :         pthread_mutex_unlock(&g_lvol_stores_mutex);
    2210                 :          0 :         return NULL;
    2211                 :          2 : }
    2212                 :            : 
    2213                 :            : struct spdk_lvol *
    2214                 :        224 : spdk_lvol_get_by_names(const char *lvs_name, const char *lvol_name)
    2215                 :            : {
    2216                 :            :         struct spdk_lvol_store *lvs;
    2217                 :            :         struct spdk_lvol *lvol;
    2218                 :            : 
    2219         [ #  # ]:        224 :         pthread_mutex_lock(&g_lvol_stores_mutex);
    2220                 :            : 
    2221   [ +  +  #  #  :        318 :         TAILQ_FOREACH(lvs, &g_lvol_stores, link) {
             #  #  #  # ]
    2222   [ +  +  -  +  :        188 :                 if (strcmp(lvs_name, lvs->name) != 0) {
             +  +  #  # ]
    2223                 :         12 :                         continue;
    2224                 :            :                 }
    2225   [ +  +  #  #  :        203 :                 TAILQ_FOREACH(lvol, &lvs->lvols, link) {
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    2226   [ +  +  -  +  :        121 :                         if (strcmp(lvol_name, lvol->name) == 0) {
             +  +  #  # ]
    2227         [ #  # ]:         94 :                                 pthread_mutex_unlock(&g_lvol_stores_mutex);
    2228                 :         94 :                                 return lvol;
    2229                 :            :                         }
    2230                 :          5 :                 }
    2231                 :          2 :         }
    2232                 :            : 
    2233         [ #  # ]:        130 :         pthread_mutex_unlock(&g_lvol_stores_mutex);
    2234                 :        130 :         return NULL;
    2235                 :         12 : }
    2236                 :            : 
    2237                 :            : bool
    2238                 :        712 : spdk_lvol_is_degraded(const struct spdk_lvol *lvol)
    2239                 :            : {
    2240   [ #  #  #  # ]:        712 :         struct spdk_blob *blob = lvol->blob;
    2241                 :            : 
    2242         [ -  + ]:        712 :         if (blob == NULL) {
    2243                 :          0 :                 return true;
    2244                 :            :         }
    2245                 :        712 :         return spdk_blob_is_degraded(blob);
    2246                 :         12 : }
    2247                 :            : 
    2248                 :            : static void
    2249                 :          5 : lvol_shallow_copy_cb(void *cb_arg, int lvolerrno)
    2250                 :            : {
    2251                 :          5 :         struct spdk_lvol_copy_req *req = cb_arg;
    2252   [ #  #  #  # ]:          5 :         struct spdk_lvol *lvol = req->lvol;
    2253                 :            : 
    2254   [ #  #  #  # ]:          5 :         spdk_bs_free_io_channel(req->channel);
    2255                 :            : 
    2256         [ -  + ]:          5 :         if (lvolerrno < 0) {
    2257         [ #  # ]:          0 :                 SPDK_ERRLOG("Could not make a shallow copy of lvol %s, error %d\n", lvol->unique_id, lvolerrno);
    2258                 :          0 :         }
    2259                 :            : 
    2260   [ #  #  #  #  :          5 :         req->cb_fn(req->cb_arg, lvolerrno);
          #  #  #  #  #  
                #  #  # ]
    2261                 :          5 :         free(req);
    2262                 :          5 : }
    2263                 :            : 
    2264                 :            : int
    2265                 :         13 : spdk_lvol_shallow_copy(struct spdk_lvol *lvol, struct spdk_bs_dev *ext_dev,
    2266                 :            :                        spdk_blob_shallow_copy_status status_cb_fn, void *status_cb_arg,
    2267                 :            :                        spdk_lvol_op_complete cb_fn, void *cb_arg)
    2268                 :            : {
    2269                 :            :         struct spdk_lvol_copy_req *req;
    2270                 :            :         spdk_blob_id blob_id;
    2271                 :            :         int rc;
    2272                 :            : 
    2273   [ +  +  #  # ]:         13 :         assert(cb_fn != NULL);
    2274                 :            : 
    2275         [ +  + ]:         13 :         if (lvol == NULL) {
    2276                 :          4 :                 SPDK_ERRLOG("lvol must not be NULL\n");
    2277                 :          4 :                 return -EINVAL;
    2278                 :            :         }
    2279                 :            : 
    2280   [ -  +  #  #  :          9 :         assert(lvol->lvol_store->thread == spdk_get_thread());
          #  #  #  #  #  
                #  #  # ]
    2281                 :            : 
    2282         [ +  + ]:          9 :         if (ext_dev == NULL) {
    2283         [ #  # ]:          4 :                 SPDK_ERRLOG("lvol %s shallow copy, ext_dev must not be NULL\n", lvol->unique_id);
    2284                 :          4 :                 return -EINVAL;
    2285                 :            :         }
    2286                 :            : 
    2287                 :          5 :         req = calloc(1, sizeof(*req));
    2288         [ -  + ]:          5 :         if (!req) {
    2289         [ #  # ]:          0 :                 SPDK_ERRLOG("lvol %s shallow copy, cannot alloc memory for lvol request\n", lvol->unique_id);
    2290                 :          0 :                 return -ENOMEM;
    2291                 :            :         }
    2292                 :            : 
    2293   [ #  #  #  # ]:          5 :         req->lvol = lvol;
    2294   [ #  #  #  # ]:          5 :         req->cb_fn = cb_fn;
    2295   [ #  #  #  # ]:          5 :         req->cb_arg = cb_arg;
    2296   [ #  #  #  #  :          5 :         req->channel = spdk_bs_alloc_io_channel(lvol->lvol_store->blobstore);
          #  #  #  #  #  
                #  #  # ]
    2297   [ +  +  #  #  :          5 :         if (req->channel == NULL) {
                   #  # ]
    2298         [ #  # ]:          0 :                 SPDK_ERRLOG("lvol %s shallow copy, cannot alloc io channel for lvol request\n", lvol->unique_id);
    2299                 :          0 :                 free(req);
    2300                 :          0 :                 return -ENOMEM;
    2301                 :            :         }
    2302                 :            : 
    2303   [ #  #  #  # ]:          5 :         blob_id = spdk_blob_get_id(lvol->blob);
    2304                 :            : 
    2305   [ #  #  #  #  :          6 :         rc = spdk_bs_blob_shallow_copy(lvol->lvol_store->blobstore, req->channel, blob_id, ext_dev,
          #  #  #  #  #  
                #  #  # ]
    2306                 :          1 :                                        status_cb_fn, status_cb_arg, lvol_shallow_copy_cb, req);
    2307                 :            : 
    2308         [ +  + ]:          5 :         if (rc < 0) {
    2309         [ #  # ]:          0 :                 SPDK_ERRLOG("Could not make a shallow copy of lvol %s\n", lvol->unique_id);
    2310   [ #  #  #  # ]:          0 :                 spdk_bs_free_io_channel(req->channel);
    2311                 :          0 :                 free(req);
    2312                 :          0 :         }
    2313                 :            : 
    2314                 :          5 :         return rc;
    2315                 :          3 : }
    2316                 :            : 
    2317                 :            : static void
    2318                 :         11 : lvol_set_parent_cb(void *cb_arg, int lvolerrno)
    2319                 :            : {
    2320                 :         11 :         struct spdk_lvol_req *req = cb_arg;
    2321                 :            : 
    2322         [ +  + ]:         11 :         if (lvolerrno < 0) {
    2323   [ #  #  #  #  :          4 :                 SPDK_ERRLOG("could not set parent of lvol %s, error %d\n", req->lvol->name, lvolerrno);
                   #  # ]
    2324                 :          0 :         }
    2325                 :            : 
    2326   [ #  #  #  #  :         11 :         req->cb_fn(req->cb_arg, lvolerrno);
          #  #  #  #  #  
                #  #  # ]
    2327                 :         11 :         free(req);
    2328                 :         11 : }
    2329                 :            : 
    2330                 :            : void
    2331                 :         19 : spdk_lvol_set_parent(struct spdk_lvol *lvol, struct spdk_lvol *snapshot,
    2332                 :            :                      spdk_lvol_op_complete cb_fn, void *cb_arg)
    2333                 :            : {
    2334                 :            :         struct spdk_lvol_req *req;
    2335                 :            :         spdk_blob_id blob_id, snapshot_id;
    2336                 :            : 
    2337   [ +  +  #  # ]:         19 :         assert(cb_fn != NULL);
    2338                 :            : 
    2339         [ +  + ]:         19 :         if (lvol == NULL) {
    2340                 :          4 :                 SPDK_ERRLOG("lvol must not be NULL\n");
    2341   [ #  #  #  # ]:          4 :                 cb_fn(cb_arg, -EINVAL);
    2342                 :          4 :                 return;
    2343                 :            :         }
    2344                 :            : 
    2345         [ +  + ]:         15 :         if (snapshot == NULL) {
    2346                 :          4 :                 SPDK_ERRLOG("snapshot must not be NULL\n");
    2347   [ #  #  #  # ]:          4 :                 cb_fn(cb_arg, -EINVAL);
    2348                 :          4 :                 return;
    2349                 :            :         }
    2350                 :            : 
    2351                 :         11 :         req = calloc(1, sizeof(*req));
    2352         [ +  + ]:         11 :         if (!req) {
    2353                 :          0 :                 SPDK_ERRLOG("cannot alloc memory for lvol request pointer\n");
    2354   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, -ENOMEM);
    2355                 :          0 :                 return;
    2356                 :            :         }
    2357                 :            : 
    2358   [ #  #  #  # ]:         11 :         req->lvol = lvol;
    2359   [ #  #  #  # ]:         11 :         req->cb_fn = cb_fn;
    2360   [ #  #  #  # ]:         11 :         req->cb_arg = cb_arg;
    2361                 :            : 
    2362   [ #  #  #  # ]:         11 :         blob_id = spdk_blob_get_id(lvol->blob);
    2363   [ #  #  #  # ]:         11 :         snapshot_id = spdk_blob_get_id(snapshot->blob);
    2364                 :            : 
    2365   [ #  #  #  #  :         12 :         spdk_bs_blob_set_parent(lvol->lvol_store->blobstore, blob_id, snapshot_id,
             #  #  #  # ]
    2366                 :          1 :                                 lvol_set_parent_cb, req);
    2367                 :          3 : }
    2368                 :            : 
    2369                 :            : static void
    2370                 :         10 : lvol_set_external_parent_cb(void *cb_arg, int lvolerrno)
    2371                 :            : {
    2372                 :         10 :         struct spdk_lvol_bs_dev_req *req = cb_arg;
    2373                 :            : 
    2374         [ +  + ]:         10 :         if (lvolerrno < 0) {
    2375   [ #  #  #  #  :          3 :                 SPDK_ERRLOG("could not set external parent of lvol %s, error %d\n", req->lvol->name, lvolerrno);
                   #  # ]
    2376   [ #  #  #  #  :          3 :                 req->bs_dev->destroy(req->bs_dev);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    2377                 :          0 :         }
    2378                 :            : 
    2379   [ #  #  #  #  :         10 :         req->cb_fn(req->cb_arg, lvolerrno);
          #  #  #  #  #  
                #  #  # ]
    2380                 :         10 :         free(req);
    2381                 :         10 : }
    2382                 :            : 
    2383                 :            : void
    2384                 :         22 : spdk_lvol_set_external_parent(struct spdk_lvol *lvol, const void *esnap_id, uint32_t esnap_id_len,
    2385                 :            :                               spdk_lvol_op_complete cb_fn, void *cb_arg)
    2386                 :            : {
    2387                 :            :         struct spdk_lvol_bs_dev_req *req;
    2388                 :         18 :         struct spdk_bs_dev *bs_dev;
    2389                 :            :         spdk_blob_id blob_id;
    2390                 :            :         int rc;
    2391                 :            : 
    2392   [ +  +  #  # ]:         22 :         assert(cb_fn != NULL);
    2393                 :            : 
    2394         [ +  + ]:         22 :         if (lvol == NULL) {
    2395                 :          4 :                 SPDK_ERRLOG("lvol must not be NULL\n");
    2396   [ #  #  #  # ]:          4 :                 cb_fn(cb_arg, -EINVAL);
    2397                 :          4 :                 return;
    2398                 :            :         }
    2399                 :            : 
    2400         [ +  + ]:         18 :         if (esnap_id == NULL) {
    2401                 :          4 :                 SPDK_ERRLOG("snapshot must not be NULL\n");
    2402   [ #  #  #  # ]:          4 :                 cb_fn(cb_arg, -EINVAL);
    2403                 :          4 :                 return;
    2404                 :            :         }
    2405                 :            : 
    2406   [ +  -  +  + ]:         14 :         if (esnap_id_len == sizeof(lvol->uuid_str) &&
    2407   [ +  +  -  +  :         14 :             memcmp(esnap_id, lvol->uuid_str, esnap_id_len) == 0) {
                   +  + ]
    2408         [ #  # ]:          4 :                 SPDK_ERRLOG("lvol %s and esnap have the same UUID\n", lvol->name);
    2409   [ #  #  #  # ]:          4 :                 cb_fn(cb_arg, -EINVAL);
    2410                 :          4 :                 return;
    2411                 :            :         }
    2412                 :            : 
    2413   [ #  #  #  #  :         10 :         rc = lvs_esnap_bs_dev_create(lvol->lvol_store, lvol, lvol->blob, esnap_id, esnap_id_len, &bs_dev);
             #  #  #  # ]
    2414         [ -  + ]:         10 :         if (rc < 0) {
    2415   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, rc);
    2416                 :          0 :                 return;
    2417                 :            :         }
    2418                 :            : 
    2419                 :         10 :         req = calloc(1, sizeof(*req));
    2420         [ +  + ]:         10 :         if (!req) {
    2421                 :          0 :                 SPDK_ERRLOG("cannot alloc memory for lvol request pointer\n");
    2422   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg, -ENOMEM);
    2423                 :          0 :                 return;
    2424                 :            :         }
    2425                 :            : 
    2426   [ #  #  #  # ]:         10 :         req->lvol = lvol;
    2427   [ #  #  #  # ]:         10 :         req->bs_dev = bs_dev;
    2428   [ #  #  #  # ]:         10 :         req->cb_fn = cb_fn;
    2429   [ #  #  #  # ]:         10 :         req->cb_arg = cb_arg;
    2430                 :            : 
    2431   [ #  #  #  # ]:         10 :         blob_id = spdk_blob_get_id(lvol->blob);
    2432                 :            : 
    2433   [ #  #  #  #  :         11 :         spdk_bs_blob_set_external_parent(lvol->lvol_store->blobstore, blob_id, bs_dev, esnap_id,
             #  #  #  # ]
    2434                 :          1 :                                          esnap_id_len, lvol_set_external_parent_cb, req);
    2435                 :          4 : }

Generated by: LCOV version 1.15