LCOV - code coverage report
Current view: top level - spdk/lib/ftl/utils - ftl_md.c (source / functions) Hit Total Coverage
Test: Combined Lines: 415 690 60.1 %
Date: 2024-12-15 01:15:42 Functions: 52 60 86.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 201 2144 9.4 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright 2023 Solidigm All Rights Reserved
       3                 :            :  *   Copyright (C) 2022 Intel Corporation.
       4                 :            :  *   All rights reserved.
       5                 :            :  */
       6                 :            : 
       7                 :            : #include "spdk/env.h"
       8                 :            : #include "spdk/bdev_module.h"
       9                 :            : 
      10                 :            : #include "ftl_core.h"
      11                 :            : #include "ftl_md.h"
      12                 :            : #include "ftl_nv_cache_io.h"
      13                 :            : 
      14                 :            : struct ftl_md;
      15                 :            : static void io_submit(struct ftl_md *md);
      16                 :            : static void io_done(struct ftl_md *md);
      17                 :            : 
      18                 :            : static bool
      19                 :       7102 : has_mirror(struct ftl_md *md)
      20                 :            : {
      21   [ +  -  #  #  :       7102 :         if (md->region) {
                   #  # ]
      22   [ +  +  #  #  :       7102 :                 if (md->region->mirror_type != FTL_LAYOUT_REGION_TYPE_INVALID) {
          #  #  #  #  #  
                      # ]
      23   [ -  +  #  #  :        645 :                         return md->mirror_enabled;
                   #  # ]
      24                 :            :                 }
      25                 :          0 :         }
      26                 :            : 
      27                 :       6457 :         return false;
      28                 :          0 : }
      29                 :            : 
      30                 :            : static struct ftl_md *
      31                 :        320 : ftl_md_get_mirror(struct ftl_md *md)
      32                 :            : {
      33         [ +  - ]:        320 :         if (has_mirror(md)) {
      34   [ #  #  #  #  :        320 :                 return md->dev->layout.md[md->region->mirror_type];
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
      35                 :            :         }
      36                 :            : 
      37                 :          0 :         return NULL;
      38                 :          0 : }
      39                 :            : 
      40                 :            : uint64_t
      41                 :      22751 : ftl_md_xfer_blocks(struct spdk_ftl_dev *dev)
      42                 :            : {
      43   [ #  #  #  # ]:      22751 :         return 4ULL * dev->xfer_size;
      44                 :            : }
      45                 :            : 
      46                 :            : static uint64_t
      47                 :        528 : xfer_size(struct ftl_md *md)
      48                 :            : {
      49   [ #  #  #  # ]:        528 :         return ftl_md_xfer_blocks(md->dev) * FTL_BLOCK_SIZE;
      50                 :            : }
      51                 :            : 
      52                 :            : static void
      53                 :         88 : ftl_md_create_heap(struct ftl_md *md, uint64_t vss_blksz)
      54                 :            : {
      55   [ #  #  #  # ]:         88 :         md->shm_fd = -1;
      56   [ #  #  #  # ]:         88 :         md->vss_data = NULL;
      57   [ #  #  #  #  :         88 :         md->data = calloc(md->data_blocks, FTL_BLOCK_SIZE + vss_blksz);
             #  #  #  # ]
      58                 :            : 
      59   [ +  -  +  -  :         88 :         if (md->data && vss_blksz) {
             #  #  #  # ]
      60   [ #  #  #  #  :         88 :                 md->vss_data = ((char *)md->data) + md->data_blocks * FTL_BLOCK_SIZE;
          #  #  #  #  #  
             #  #  #  #  
                      # ]
      61                 :          0 :         }
      62                 :         88 : }
      63                 :            : 
      64                 :            : static void
      65                 :        176 : ftl_md_destroy_heap(struct ftl_md *md)
      66                 :            : {
      67   [ +  +  #  #  :        176 :         if (md->data) {
                   #  # ]
      68   [ #  #  #  # ]:         88 :                 free(md->data);
      69   [ #  #  #  # ]:         88 :                 md->data = NULL;
      70   [ #  #  #  # ]:         88 :                 md->vss_data = NULL;
      71                 :          0 :         }
      72                 :        176 : }
      73                 :            : 
      74                 :            : static int
      75                 :        258 : ftl_wrapper_open(const char *name, int of, mode_t m)
      76                 :            : {
      77         [ -  + ]:        258 :         return open(name, of, m);
      78                 :            : }
      79                 :            : 
      80                 :            : static void
      81                 :        258 : ftl_md_setup_obj(struct ftl_md *md, int flags,
      82                 :            :                  const char *name)
      83                 :            : {
      84                 :        258 :         char uuid_str[SPDK_UUID_STRING_LEN];
      85                 :          0 :         const char *fmt;
      86                 :            : 
      87         [ -  + ]:        258 :         if (!(flags & FTL_MD_CREATE_SHM)) {
      88         [ #  # ]:          0 :                 assert(false);
      89                 :            :                 return;
      90                 :            :         }
      91                 :            : 
      92                 :            :         /* TODO: temporary, define a proper hugetlbfs mountpoint */
      93                 :        258 :         fmt = "/dev/hugepages/ftl_%s_%s";
      94   [ #  #  #  # ]:        258 :         md->shm_mmap_flags = MAP_SHARED;
      95   [ #  #  #  # ]:        258 :         md->shm_open = ftl_wrapper_open;
      96   [ #  #  #  # ]:        258 :         md->shm_unlink = unlink;
      97                 :            : 
      98   [ +  -  +  - ]:        516 :         if (name == NULL ||
      99   [ #  #  #  #  :        258 :             spdk_uuid_fmt_lower(uuid_str, SPDK_UUID_STRING_LEN, &md->dev->conf.uuid) ||
          #  #  #  #  #  
                      # ]
     100   [ -  +  -  + ]:        258 :             snprintf(md->name, sizeof(md->name) / sizeof(md->name[0]),
     101                 :          0 :                      fmt, uuid_str, name) <= 0) {
     102   [ #  #  #  #  :          0 :                 md->name[0] = 0;
             #  #  #  # ]
     103                 :          0 :         }
     104                 :          0 : }
     105                 :            : 
     106                 :            : static void
     107                 :         16 : ftl_md_invalidate_shm(struct ftl_md *md)
     108                 :            : {
     109   [ -  +  -  -  :         16 :         if (md->dev->sb_shm && md->dev->sb_shm->shm_ready) {
          -  -  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     110   [ #  #  #  #  :          0 :                 md->dev->init_retry = true;
             #  #  #  # ]
     111   [ #  #  #  #  :          0 :                 md->dev->sb_shm->shm_ready = false;
          #  #  #  #  #  
                #  #  # ]
     112                 :          0 :         }
     113                 :         16 : }
     114                 :            : 
     115                 :            : static void
     116                 :        258 : ftl_md_create_shm(struct ftl_md *md, uint64_t vss_blksz, int flags)
     117                 :            : {
     118                 :        258 :         struct stat shm_stat;
     119                 :          0 :         size_t vss_blk_offs;
     120                 :          0 :         void *shm_ptr;
     121                 :        258 :         int open_flags = O_RDWR;
     122                 :        258 :         mode_t open_mode = S_IRUSR | S_IWUSR;
     123                 :            : 
     124   [ +  -  +  -  :        258 :         assert(md->shm_open && md->shm_unlink);
          #  #  #  #  #  
                #  #  # ]
     125   [ #  #  #  # ]:        258 :         md->data = NULL;
     126   [ #  #  #  # ]:        258 :         md->vss_data = NULL;
     127   [ #  #  #  # ]:        258 :         md->shm_sz = 0;
     128                 :            : 
     129                 :            :         /* Must have an object name */
     130   [ -  +  #  #  :        258 :         if (md->name[0] == 0) {
          #  #  #  #  #  
                      # ]
     131         [ #  # ]:          0 :                 assert(false);
     132                 :          0 :                 return;
     133                 :            :         }
     134                 :            : 
     135                 :            :         /* If specified, unlink before create a new SHM object */
     136         [ +  + ]:        258 :         if (flags & FTL_MD_CREATE_SHM_NEW) {
     137   [ +  +  -  +  :        233 :                 if (md->shm_unlink(md->name) < 0 && errno != ENOENT) {
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     138                 :          0 :                         ftl_md_invalidate_shm(md);
     139                 :          0 :                         return;
     140                 :            :                 }
     141         [ #  # ]:        233 :                 open_flags += O_CREAT | O_TRUNC;
     142                 :          0 :         }
     143                 :            : 
     144                 :            :         /* Open existing or create a new SHM object, then query its props */
     145   [ #  #  #  #  :        258 :         md->shm_fd = md->shm_open(md->name, open_flags, open_mode);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     146   [ +  +  -  +  :        258 :         if (md->shm_fd < 0 || fstat(md->shm_fd, &shm_stat) < 0) {
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     147                 :         16 :                 goto err_shm;
     148                 :            :         }
     149                 :            : 
     150                 :            :         /* Verify open mode hasn't changed */
     151   [ -  +  #  #  :        242 :         if ((shm_stat.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) != open_mode) {
          #  #  #  #  #  
                      # ]
     152                 :          0 :                 goto err_shm;
     153                 :            :         }
     154                 :            : 
     155                 :            :         /* Round up the SHM obj size to the nearest blk size (i.e. page size) */
     156   [ #  #  #  #  :        242 :         md->shm_sz = spdk_divide_round_up(md->data_blocks * FTL_BLOCK_SIZE, shm_stat.st_blksize);
          #  #  #  #  #  
                      # ]
     157                 :            : 
     158                 :            :         /* Add some blks for VSS metadata */
     159   [ #  #  #  # ]:        242 :         vss_blk_offs = md->shm_sz;
     160                 :            : 
     161         [ +  + ]:        242 :         if (vss_blksz) {
     162   [ #  #  #  #  :         88 :                 md->shm_sz += spdk_divide_round_up(md->data_blocks * vss_blksz,
             #  #  #  # ]
     163         [ #  # ]:         88 :                                                    shm_stat.st_blksize);
     164                 :          0 :         }
     165                 :            : 
     166                 :            :         /* Total SHM obj size */
     167   [ #  #  #  #  :        242 :         md->shm_sz *= shm_stat.st_blksize;
                   #  # ]
     168                 :            : 
     169                 :            :         /* Set or check the object size - zero init`d in case of set (FTL_MD_CREATE_SHM_NEW) */
     170   [ +  +  +  -  :        242 :         if ((shm_stat.st_size == 0 && (ftruncate(md->shm_fd, md->shm_sz) < 0 ||
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     171         [ +  - ]:        233 :                                        (flags & FTL_MD_CREATE_SHM_NEW) == 0))
     172   [ +  +  -  +  :        242 :             || (shm_stat.st_size > 0 && (size_t)shm_stat.st_size != md->shm_sz)) {
          #  #  #  #  #  
                      # ]
     173                 :          0 :                 goto err_shm;
     174                 :            :         }
     175                 :            : 
     176                 :            :         /* Create a virtual memory mapping for the object */
     177   [ #  #  #  #  :        242 :         shm_ptr = mmap(NULL, md->shm_sz, PROT_READ | PROT_WRITE, md->shm_mmap_flags,
             #  #  #  # ]
     178   [ #  #  #  # ]:          0 :                        md->shm_fd, 0);
     179         [ -  + ]:        242 :         if (shm_ptr == MAP_FAILED) {
     180                 :          0 :                 goto err_shm;
     181                 :            :         }
     182                 :            : 
     183   [ #  #  #  # ]:        242 :         md->data = shm_ptr;
     184         [ +  + ]:        242 :         if (vss_blksz) {
     185   [ #  #  #  #  :         88 :                 md->vss_data = ((char *)shm_ptr) + vss_blk_offs * shm_stat.st_blksize;
             #  #  #  # ]
     186                 :          0 :         }
     187                 :            : 
     188                 :            :         /* Lock the pages in memory (i.e. prevent the pages to be paged out) */
     189   [ -  +  #  #  :        242 :         if (mlock(md->data, md->shm_sz) < 0) {
          #  #  #  #  #  
                      # ]
     190                 :          0 :                 goto err_map;
     191                 :            :         }
     192                 :            : 
     193   [ -  +  #  #  :        242 :         if (spdk_mem_register(md->data, md->shm_sz)) {
          #  #  #  #  #  
                      # ]
     194                 :          0 :                 goto err_mlock;
     195                 :            :         }
     196   [ #  #  #  # ]:        242 :         md->mem_reg = true;
     197                 :            : 
     198                 :        242 :         return;
     199                 :            : 
     200                 :            :         /* Cleanup upon fault */
     201                 :          0 : err_mlock:
     202   [ #  #  #  #  :          0 :         munlock(md->data, md->shm_sz);
             #  #  #  # ]
     203                 :            : 
     204                 :          0 : err_map:
     205   [ #  #  #  #  :          0 :         munmap(md->data, md->shm_sz);
             #  #  #  # ]
     206   [ #  #  #  # ]:          0 :         md->data = NULL;
     207   [ #  #  #  # ]:          0 :         md->vss_data = NULL;
     208   [ #  #  #  # ]:          0 :         md->shm_sz = 0;
     209                 :            : 
     210                 :         16 : err_shm:
     211   [ -  +  #  #  :         16 :         if (md->shm_fd >= 0) {
                   #  # ]
     212   [ #  #  #  # ]:          0 :                 close(md->shm_fd);
     213   [ #  #  #  #  :          0 :                 md->shm_unlink(md->name);
          #  #  #  #  #  
                      # ]
     214   [ #  #  #  # ]:          0 :                 md->shm_fd = -1;
     215                 :          0 :         }
     216                 :         16 :         ftl_md_invalidate_shm(md);
     217         [ #  # ]:          0 : }
     218                 :            : 
     219                 :            : static void
     220                 :        308 : ftl_md_destroy_shm(struct ftl_md *md, int flags)
     221                 :            : {
     222   [ +  +  #  #  :        308 :         if (!md->data) {
                   #  # ]
     223                 :         66 :                 return;
     224                 :            :         }
     225                 :            : 
     226   [ -  +  #  #  :        242 :         assert(md->shm_sz > 0);
             #  #  #  # ]
     227   [ -  +  +  -  :        242 :         if (md->mem_reg) {
             #  #  #  # ]
     228   [ #  #  #  #  :        242 :                 spdk_mem_unregister(md->data, md->shm_sz);
             #  #  #  # ]
     229   [ #  #  #  # ]:        242 :                 md->mem_reg = false;
     230                 :          0 :         }
     231                 :            : 
     232                 :            :         /* Unlock the pages in memory */
     233   [ #  #  #  #  :        242 :         munlock(md->data, md->shm_sz);
             #  #  #  # ]
     234                 :            : 
     235                 :            :         /* Remove the virtual memory mapping for the object */
     236   [ #  #  #  #  :        242 :         munmap(md->data, md->shm_sz);
             #  #  #  # ]
     237                 :            : 
     238                 :            :         /* Close SHM object fd */
     239   [ #  #  #  # ]:        242 :         close(md->shm_fd);
     240                 :            : 
     241   [ #  #  #  # ]:        242 :         md->data = NULL;
     242   [ #  #  #  # ]:        242 :         md->vss_data = NULL;
     243                 :            : 
     244                 :            :         /* If specified, keep the object in SHM */
     245         [ -  + ]:        242 :         if (flags & FTL_MD_DESTROY_SHM_KEEP) {
     246                 :          0 :                 return;
     247                 :            :         }
     248                 :            : 
     249                 :            :         /* Otherwise destroy/unlink the object */
     250   [ +  -  +  -  :        242 :         assert(md->name[0] != 0 && md->shm_unlink != NULL);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     251   [ #  #  #  #  :        242 :         md->shm_unlink(md->name);
          #  #  #  #  #  
                      # ]
     252                 :          0 : }
     253                 :            : 
     254                 :        500 : struct ftl_md *ftl_md_create(struct spdk_ftl_dev *dev, uint64_t blocks,
     255                 :            :                              uint64_t vss_blksz, const char *name, int flags,
     256                 :            :                              const struct ftl_layout_region *region)
     257                 :            : {
     258                 :          0 :         struct ftl_md *md;
     259                 :            : 
     260                 :        500 :         md = calloc(1, sizeof(*md));
     261         [ -  + ]:        500 :         if (!md) {
     262                 :          0 :                 return NULL;
     263                 :            :         }
     264   [ #  #  #  # ]:        500 :         md->dev = dev;
     265   [ #  #  #  # ]:        500 :         md->data_blocks = blocks;
     266   [ #  #  #  # ]:        500 :         md->mirror_enabled = true;
     267                 :            : 
     268         [ +  + ]:        500 :         if (flags != FTL_MD_CREATE_NO_MEM) {
     269         [ +  + ]:        346 :                 if (flags & FTL_MD_CREATE_SHM) {
     270                 :        258 :                         ftl_md_setup_obj(md, flags, name);
     271                 :        258 :                         ftl_md_create_shm(md, vss_blksz, flags);
     272                 :          0 :                 } else {
     273   [ -  +  #  # ]:         88 :                         assert((flags & FTL_MD_CREATE_HEAP) == FTL_MD_CREATE_HEAP);
     274                 :         88 :                         ftl_md_create_heap(md, vss_blksz);
     275                 :            :                 }
     276                 :            : 
     277   [ +  +  #  #  :        346 :                 if (!md->data) {
                   #  # ]
     278                 :         16 :                         free(md);
     279                 :         16 :                         return NULL;
     280                 :            :                 }
     281                 :          0 :         }
     282                 :            : 
     283         [ +  + ]:        484 :         if (region) {
     284   [ #  #  #  # ]:        352 :                 size_t entry_vss_buf_size = vss_blksz * region->entry_size;
     285                 :            : 
     286         [ +  + ]:        352 :                 if (entry_vss_buf_size) {
     287   [ #  #  #  # ]:        242 :                         md->entry_vss_dma_buf = spdk_malloc(entry_vss_buf_size, FTL_BLOCK_SIZE,
     288                 :            :                                                             NULL, SPDK_ENV_LCORE_ID_ANY,
     289                 :            :                                                             SPDK_MALLOC_DMA);
     290   [ -  +  #  #  :        242 :                         if (!md->entry_vss_dma_buf) {
                   #  # ]
     291                 :          0 :                                 goto err;
     292                 :            :                         }
     293                 :          0 :                 }
     294                 :            : 
     295                 :        352 :                 ftl_md_set_region(md, region);
     296      [ #  #  # ]:          0 :         }
     297                 :            : 
     298                 :        484 :         return md;
     299                 :          0 : err:
     300   [ #  #  #  # ]:          0 :         ftl_md_destroy(md, ftl_md_destroy_region_flags(dev, region->type));
     301                 :          0 :         return NULL;
     302                 :          0 : }
     303                 :            : 
     304                 :            : int
     305                 :          0 : ftl_md_unlink(struct spdk_ftl_dev *dev, const char *name, int flags)
     306                 :            : {
     307                 :          0 :         struct ftl_md md = { 0 };
     308                 :            : 
     309         [ #  # ]:          0 :         if (0 == (flags & FTL_MD_CREATE_SHM)) {
     310                 :            :                 /* Unlink can be called for shared memory only */
     311                 :          0 :                 return -EINVAL;
     312                 :            :         }
     313                 :            : 
     314         [ #  # ]:          0 :         md.dev = dev;
     315                 :          0 :         ftl_md_setup_obj(&md, flags, name);
     316                 :            : 
     317   [ #  #  #  #  :          0 :         return md.shm_unlink(md.name);
                   #  # ]
     318                 :          0 : }
     319                 :            : 
     320                 :            : void
     321                 :        485 : ftl_md_destroy(struct ftl_md *md, int flags)
     322                 :            : {
     323         [ +  + ]:        485 :         if (!md) {
     324                 :          1 :                 return;
     325                 :            :         }
     326                 :            : 
     327   [ -  +  +  +  :        484 :         if (!md->is_mirror) {
             #  #  #  # ]
     328                 :        396 :                 ftl_md_free_buf(md, flags);
     329   [ #  #  #  # ]:        396 :                 spdk_free(md->entry_vss_dma_buf);
     330                 :          0 :         }
     331                 :        484 :         free(md);
     332                 :          0 : }
     333                 :            : 
     334                 :            : void
     335                 :        484 : ftl_md_free_buf(struct ftl_md *md, int flags)
     336                 :            : {
     337         [ -  + ]:        484 :         if (!md) {
     338                 :          0 :                 return;
     339                 :            :         }
     340                 :            : 
     341   [ +  +  #  #  :        484 :         if (md->shm_fd < 0) {
                   #  # ]
     342   [ -  +  #  # ]:        176 :                 assert(flags == 0);
     343                 :        176 :                 ftl_md_destroy_heap(md);
     344                 :          0 :         } else {
     345                 :        308 :                 ftl_md_destroy_shm(md, flags);
     346                 :            :         }
     347                 :          0 : }
     348                 :            : 
     349                 :            : void *
     350                 :    1861801 : ftl_md_get_buffer(struct ftl_md *md)
     351                 :            : {
     352   [ #  #  #  # ]:    1861801 :         return md->data;
     353                 :            : }
     354                 :            : 
     355                 :            : uint64_t
     356                 :        329 : ftl_md_get_buffer_size(struct ftl_md *md)
     357                 :            : {
     358   [ #  #  #  # ]:        329 :         return md->data_blocks * FTL_BLOCK_SIZE;
     359                 :            : }
     360                 :            : 
     361                 :            : static void
     362                 :        438 : ftl_md_vss_buf_init(union ftl_md_vss *buf, uint32_t count,
     363                 :            :                     const union ftl_md_vss *vss_pattern)
     364                 :            : {
     365         [ +  + ]:     207354 :         while (count) {
     366                 :     206916 :                 count--;
     367         [ #  # ]:     206916 :                 buf[count] = *vss_pattern;
     368                 :            :         }
     369                 :        438 : }
     370                 :            : 
     371                 :         88 : union ftl_md_vss *ftl_md_vss_buf_alloc(struct ftl_layout_region *region, uint32_t count)
     372                 :            : {
     373                 :         88 :         union ftl_md_vss *buf = spdk_zmalloc(count * FTL_MD_VSS_SZ, FTL_BLOCK_SIZE, NULL,
     374                 :            :                                                      SPDK_ENV_LCORE_ID_ANY,
     375                 :            :                                                      SPDK_MALLOC_DMA);
     376                 :            : 
     377         [ -  + ]:         88 :         if (!buf) {
     378                 :          0 :                 return NULL;
     379                 :            :         }
     380                 :            : 
     381                 :         88 :         union ftl_md_vss vss_buf = {0};
     382   [ #  #  #  #  :         88 :         vss_buf.version.md_version = region->current.version;
             #  #  #  # ]
     383                 :         88 :         ftl_md_vss_buf_init(buf, count, &vss_buf);
     384                 :         88 :         return buf;
     385                 :          0 : }
     386                 :            : 
     387                 :         11 : union ftl_md_vss *ftl_md_get_vss_buffer(struct ftl_md *md)
     388                 :            : {
     389   [ #  #  #  # ]:         11 :         return md->vss_data;
     390                 :            : }
     391                 :            : 
     392                 :            : static void
     393                 :        508 : io_cleanup(struct ftl_md *md)
     394                 :            : {
     395   [ #  #  #  #  :        508 :         spdk_dma_free(md->io.data);
                   #  # ]
     396   [ #  #  #  #  :        508 :         md->io.data = NULL;
                   #  # ]
     397                 :            : 
     398   [ #  #  #  #  :        508 :         spdk_dma_free(md->io.md);
                   #  # ]
     399   [ #  #  #  #  :        508 :         md->io.md = NULL;
                   #  # ]
     400                 :        508 : }
     401                 :            : 
     402                 :            : static void
     403                 :          0 : exception(void *arg)
     404                 :            : {
     405                 :          0 :         struct ftl_md *md = arg;
     406                 :            : 
     407   [ #  #  #  #  :          0 :         md->cb(md->dev, md, -EINVAL);
          #  #  #  #  #  
                #  #  # ]
     408                 :          0 :         io_cleanup(md);
     409                 :          0 : }
     410                 :            : 
     411                 :            : static inline enum ftl_stats_type
     412                 :      11854 : get_bdev_io_ftl_stats_type(struct spdk_ftl_dev *dev, struct spdk_bdev_io *bdev_io) {
     413   [ #  #  #  #  :      11854 :         struct spdk_bdev *nvc = spdk_bdev_desc_get_bdev(dev->nv_cache.bdev_desc);
                   #  # ]
     414                 :            : 
     415   [ +  +  #  #  :      11854 :         if (bdev_io->bdev == nvc)
                   #  # ]
     416                 :            :         {
     417                 :      11750 :                 return FTL_STATS_TYPE_MD_NV_CACHE;
     418                 :            :         } else
     419                 :            :         {
     420                 :        104 :                 return FTL_STATS_TYPE_MD_BASE;
     421                 :            :         }
     422                 :          0 : }
     423                 :            : 
     424                 :            : static void
     425                 :       5601 : audit_md_vss_version(struct ftl_md *md, uint64_t blocks)
     426                 :            : {
     427                 :            : #if defined(DEBUG)
     428   [ #  #  #  #  :       5601 :         union ftl_md_vss *vss = md->io.md;
                   #  # ]
     429                 :            :         /* Need to load the superblock regardless of its version */
     430   [ +  +  #  #  :       5601 :         if (md->region->type == FTL_LAYOUT_REGION_TYPE_SB) {
          #  #  #  #  #  
                      # ]
     431                 :         82 :                 return;
     432                 :            :         }
     433         [ +  + ]:    5442319 :         while (blocks) {
     434                 :    5436800 :                 blocks--;
     435   [ -  +  #  #  :    5436800 :                 assert(vss[blocks].version.md_version == md->region->current.version);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
     436                 :            :         }
     437                 :            : #endif
     438         [ #  # ]:          0 : }
     439                 :            : 
     440                 :            : static void
     441                 :       5705 : read_write_blocks_cb(struct spdk_bdev_io *bdev_io, bool success, void *arg)
     442                 :            : {
     443                 :       5705 :         struct ftl_md *md = arg;
     444                 :            : 
     445   [ #  #  #  #  :       5705 :         ftl_stats_bdev_io_completed(md->dev, get_bdev_io_ftl_stats_type(md->dev, bdev_io), bdev_io);
             #  #  #  # ]
     446                 :            : 
     447   [ -  +  #  # ]:       5705 :         if (spdk_unlikely(!success)) {
     448   [ #  #  #  #  :          0 :                 if (md->io.op == FTL_MD_OP_RESTORE && has_mirror(md)) {
          #  #  #  #  #  
                      # ]
     449   [ #  #  #  #  :          0 :                         md->io.status = -EAGAIN;
                   #  # ]
     450                 :          0 :                 } else {
     451   [ #  #  #  #  :          0 :                         md->io.status = -EIO;
                   #  # ]
     452                 :            :                 }
     453                 :          0 :         } else {
     454   [ #  #  #  #  :       5705 :                 uint64_t blocks = bdev_io->u.bdev.num_blocks;
             #  #  #  # ]
     455                 :       5705 :                 uint64_t size = blocks * FTL_BLOCK_SIZE;
     456                 :            : 
     457   [ +  +  #  #  :       5705 :                 if (md->io.op == FTL_MD_OP_RESTORE) {
             #  #  #  # ]
     458   [ -  +  -  +  :        151 :                         memcpy(md->data + md->io.data_offset, md->io.data, size);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     459                 :            : 
     460   [ +  +  #  #  :        151 :                         if (md->vss_data) {
                   #  # ]
     461   [ #  #  #  #  :        135 :                                 uint64_t vss_offset = md->io.data_offset / FTL_BLOCK_SIZE;
             #  #  #  # ]
     462                 :        135 :                                 vss_offset *= FTL_MD_VSS_SZ;
     463                 :        135 :                                 audit_md_vss_version(md, blocks);
     464   [ -  +  -  +  :        135 :                                 memcpy(md->vss_data + vss_offset, md->io.md, blocks * FTL_MD_VSS_SZ);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     465                 :          0 :                         }
     466                 :          0 :                 }
     467                 :            : 
     468   [ #  #  #  #  :       5705 :                 md->io.address += blocks;
                   #  # ]
     469   [ #  #  #  #  :       5705 :                 md->io.remaining -= blocks;
                   #  # ]
     470   [ #  #  #  #  :       5705 :                 md->io.data_offset += size;
                   #  # ]
     471                 :          0 :         }
     472                 :            : 
     473                 :       5705 :         spdk_bdev_free_io(bdev_io);
     474                 :            : 
     475                 :       5705 :         io_submit(md);
     476                 :       5705 : }
     477                 :            : 
     478                 :            : static inline int
     479                 :        151 : read_blocks(struct spdk_ftl_dev *dev, struct spdk_bdev_desc *desc,
     480                 :            :             struct spdk_io_channel *ch,
     481                 :            :             void *buf, void *md_buf,
     482                 :            :             uint64_t offset_blocks, uint64_t num_blocks,
     483                 :            :             spdk_bdev_io_completion_cb cb, void *cb_arg)
     484                 :            : {
     485   [ +  +  #  #  :        151 :         if (desc == dev->nv_cache.bdev_desc) {
             #  #  #  # ]
     486                 :        135 :                 return ftl_nv_cache_bdev_read_blocks_with_md(dev, desc, ch, buf, md_buf,
     487                 :          0 :                                 offset_blocks, num_blocks,
     488                 :          0 :                                 cb, cb_arg);
     489         [ -  + ]:         16 :         } else if (md_buf) {
     490                 :          0 :                 return spdk_bdev_read_blocks_with_md(desc, ch, buf, md_buf,
     491                 :          0 :                                                      offset_blocks, num_blocks,
     492                 :          0 :                                                      cb, cb_arg);
     493                 :            :         } else {
     494                 :         16 :                 return spdk_bdev_read_blocks(desc, ch, buf,
     495                 :          0 :                                              offset_blocks, num_blocks,
     496                 :          0 :                                              cb, cb_arg);
     497                 :            :         }
     498                 :          0 : }
     499                 :            : 
     500                 :            : static inline int
     501                 :      11703 : write_blocks(struct spdk_ftl_dev *dev, struct spdk_bdev_desc *desc,
     502                 :            :              struct spdk_io_channel *ch,
     503                 :            :              void *buf, void *md_buf,
     504                 :            :              uint64_t offset_blocks, uint64_t num_blocks,
     505                 :            :              spdk_bdev_io_completion_cb cb, void *cb_arg)
     506                 :            : {
     507   [ +  +  #  #  :      11703 :         if (desc == dev->nv_cache.bdev_desc) {
             #  #  #  # ]
     508                 :      11615 :                 return ftl_nv_cache_bdev_write_blocks_with_md(dev, desc, ch, buf, md_buf,
     509                 :          0 :                                 offset_blocks, num_blocks,
     510                 :          0 :                                 cb, cb_arg);
     511         [ -  + ]:         88 :         } else if (md_buf) {
     512                 :          0 :                 return spdk_bdev_write_blocks_with_md(desc, ch, buf, md_buf, offset_blocks,
     513                 :          0 :                                                       num_blocks, cb, cb_arg);
     514                 :            :         } else {
     515                 :         88 :                 return spdk_bdev_write_blocks(desc, ch, buf, offset_blocks, num_blocks, cb, cb_arg);
     516                 :            :         }
     517                 :          0 : }
     518                 :            : 
     519                 :            : static void
     520                 :       5705 : read_write_blocks(void *_md)
     521                 :            : {
     522                 :       5705 :         struct ftl_md *md = _md;
     523   [ #  #  #  # ]:       5705 :         const struct ftl_layout_region *region = md->region;
     524                 :          0 :         uint64_t blocks;
     525                 :       5705 :         int rc = 0;
     526                 :            : 
     527   [ +  +  #  #  :       5705 :         blocks = spdk_min(md->io.remaining, ftl_md_xfer_blocks(md->dev));
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
     528                 :            : 
     529   [ +  +  -  #  :       5705 :         switch (md->io.op) {
             #  #  #  #  
                      # ]
     530                 :        151 :         case FTL_MD_OP_RESTORE:
     531   [ #  #  #  #  :        151 :                 rc = read_blocks(md->dev, region->bdev_desc, region->ioch,
          #  #  #  #  #  
                #  #  # ]
     532   [ #  #  #  #  :          0 :                                  md->io.data, md->io.md,
          #  #  #  #  #  
                #  #  # ]
     533   [ #  #  #  #  :          0 :                                  md->io.address, blocks,
                   #  # ]
     534                 :          0 :                                  read_write_blocks_cb, md);
     535                 :        151 :                 break;
     536                 :       5554 :         case FTL_MD_OP_PERSIST:
     537                 :            :         case FTL_MD_OP_CLEAR:
     538   [ #  #  #  #  :       5554 :                 rc = write_blocks(md->dev, region->bdev_desc, region->ioch,
          #  #  #  #  #  
                #  #  # ]
     539   [ #  #  #  #  :          0 :                                   md->io.data, md->io.md,
          #  #  #  #  #  
                #  #  # ]
     540   [ #  #  #  #  :          0 :                                   md->io.address, blocks,
                   #  # ]
     541                 :          0 :                                   read_write_blocks_cb, md);
     542                 :       5554 :                 break;
     543                 :          0 :         default:
     544         [ #  # ]:          0 :                 ftl_abort();
     545                 :          0 :         }
     546                 :            : 
     547         [ -  + ]:       5705 :         if (spdk_unlikely(rc)) {
     548         [ #  # ]:          0 :                 if (rc == -ENOMEM) {
     549   [ #  #  #  # ]:          0 :                         struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(region->bdev_desc);
     550   [ #  #  #  #  :          0 :                         md->io.bdev_io_wait.bdev = bdev;
             #  #  #  # ]
     551   [ #  #  #  #  :          0 :                         md->io.bdev_io_wait.cb_fn = read_write_blocks;
             #  #  #  # ]
     552   [ #  #  #  #  :          0 :                         md->io.bdev_io_wait.cb_arg = md;
             #  #  #  # ]
     553   [ #  #  #  #  :          0 :                         spdk_bdev_queue_io_wait(bdev, region->ioch, &md->io.bdev_io_wait);
             #  #  #  # ]
     554                 :          0 :                 } else {
     555         [ #  # ]:          0 :                         ftl_abort();
     556                 :            :                 }
     557                 :          0 :         }
     558                 :       5705 : }
     559                 :            : 
     560                 :            : static void
     561                 :       6213 : io_submit(struct ftl_md *md)
     562                 :            : {
     563   [ +  +  -  +  :       6213 :         if (!md->io.remaining || md->io.status) {
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     564                 :        508 :                 io_done(md);
     565                 :        508 :                 return;
     566                 :            :         }
     567                 :            : 
     568   [ +  +  #  #  :       5705 :         if (md->io.op == FTL_MD_OP_PERSIST) {
             #  #  #  # ]
     569   [ +  +  #  #  :        337 :                 uint64_t blocks = spdk_min(md->io.remaining, ftl_md_xfer_blocks(md->dev));
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
     570                 :            : 
     571   [ -  +  -  +  :        337 :                 memcpy(md->io.data, md->data + md->io.data_offset, FTL_BLOCK_SIZE * blocks);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     572                 :            : 
     573   [ +  +  #  #  :        337 :                 if (md->vss_data) {
                   #  # ]
     574   [ #  #  #  #  :        249 :                         uint64_t vss_offset = md->io.data_offset / FTL_BLOCK_SIZE;
             #  #  #  # ]
     575                 :        249 :                         vss_offset *= FTL_MD_VSS_SZ;
     576   [ -  +  #  #  :        249 :                         assert(md->io.md);
          #  #  #  #  #  
                      # ]
     577   [ -  +  -  +  :        249 :                         memcpy(md->io.md, md->vss_data + vss_offset, FTL_MD_VSS_SZ * blocks);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     578                 :        249 :                         audit_md_vss_version(md, blocks);
     579                 :          0 :                 }
     580                 :          0 :         }
     581                 :            : #if defined(DEBUG)
     582   [ +  +  +  +  :       5705 :         if (md->io.md && md->io.op == FTL_MD_OP_CLEAR) {
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     583   [ +  +  #  #  :       5217 :                 uint64_t blocks = spdk_min(md->io.remaining, ftl_md_xfer_blocks(md->dev));
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
     584                 :       5217 :                 audit_md_vss_version(md, blocks);
     585                 :          0 :         }
     586                 :            : #endif
     587                 :            : 
     588                 :       5705 :         read_write_blocks(md);
     589                 :          0 : }
     590                 :            : 
     591                 :            : static int
     592                 :        508 : io_can_start(struct ftl_md *md)
     593                 :            : {
     594   [ -  +  #  #  :        508 :         assert(NULL == md->io.data);
          #  #  #  #  #  
                      # ]
     595   [ -  +  #  #  :        508 :         if (NULL != md->io.data) {
             #  #  #  # ]
     596                 :            :                 /* Outgoing IO on metadata */
     597                 :          0 :                 return -EINVAL;
     598                 :            :         }
     599                 :            : 
     600   [ -  +  #  #  :        508 :         if (!md->region) {
                   #  # ]
     601                 :            :                 /* No device region to process data */
     602                 :          0 :                 return -EINVAL;
     603                 :            :         }
     604                 :            : 
     605   [ -  +  #  #  :        508 :         if (md->region->current.blocks > md->data_blocks) {
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     606                 :            :                 /* No device region to process data */
     607   [ #  #  #  #  :          0 :                 FTL_ERRLOG(md->dev, "Blocks number mismatch between metadata object and"
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     608                 :            :                            "device region\n");
     609                 :          0 :                 return -EINVAL;
     610                 :            :         }
     611                 :            : 
     612                 :        508 :         return 0;
     613                 :          0 : }
     614                 :            : 
     615                 :            : static int
     616                 :        508 : io_prepare(struct ftl_md *md, enum ftl_md_ops op)
     617                 :            : {
     618   [ #  #  #  # ]:        508 :         const struct ftl_layout_region *region = md->region;
     619                 :        508 :         uint64_t data_size, meta_size = 0;
     620                 :            : 
     621                 :            :         /* Allocates buffer for IO */
     622                 :        508 :         data_size = xfer_size(md);
     623   [ #  #  #  #  :        508 :         md->io.data = spdk_zmalloc(data_size, FTL_BLOCK_SIZE, NULL,
                   #  # ]
     624                 :            :                                    SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA);
     625   [ -  +  #  #  :        508 :         if (!md->io.data) {
             #  #  #  # ]
     626                 :          0 :                 return -ENOMEM;
     627                 :            :         }
     628                 :            : 
     629   [ +  +  +  +  :        508 :         if (md->vss_data || md->region->vss_blksz) {
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     630   [ #  #  #  # ]:        404 :                 meta_size = ftl_md_xfer_blocks(md->dev) * FTL_MD_VSS_SZ;
     631   [ #  #  #  #  :        404 :                 md->io.md = spdk_zmalloc(meta_size, FTL_BLOCK_SIZE, NULL,
                   #  # ]
     632                 :            :                                          SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA);
     633   [ -  +  #  #  :        404 :                 if (!md->io.md) {
             #  #  #  # ]
     634   [ #  #  #  #  :          0 :                         spdk_dma_free(md->io.data);
                   #  # ]
     635   [ #  #  #  #  :          0 :                         md->io.data = NULL;
                   #  # ]
     636                 :          0 :                         return -ENOMEM;
     637                 :            :                 }
     638                 :          0 :         }
     639                 :            : 
     640   [ #  #  #  #  :        508 :         md->io.address = region->current.offset;
          #  #  #  #  #  
                #  #  # ]
     641   [ #  #  #  #  :        508 :         md->io.remaining = region->current.blocks;
          #  #  #  #  #  
                #  #  # ]
     642   [ #  #  #  #  :        508 :         md->io.data_offset = 0;
                   #  # ]
     643   [ #  #  #  #  :        508 :         md->io.status = 0;
                   #  # ]
     644   [ #  #  #  #  :        508 :         md->io.op = op;
                   #  # ]
     645                 :            : 
     646                 :        508 :         return 0;
     647                 :          0 : }
     648                 :            : 
     649                 :            : static int
     650                 :        508 : io_init(struct ftl_md *md, enum ftl_md_ops op)
     651                 :            : {
     652         [ -  + ]:        508 :         if (io_can_start(md)) {
     653                 :          0 :                 return -EINVAL;
     654                 :            :         }
     655                 :            : 
     656         [ -  + ]:        508 :         if (io_prepare(md, op)) {
     657                 :          0 :                 return -ENOMEM;
     658                 :            :         }
     659                 :            : 
     660                 :        508 :         return 0;
     661                 :          0 : }
     662                 :            : 
     663                 :            : static uint64_t
     664                 :       6149 : persist_entry_lba(struct ftl_md *md, uint64_t start_entry)
     665                 :            : {
     666   [ #  #  #  #  :       6149 :         return md->region->current.offset + start_entry * md->region->entry_size;
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     667                 :            : }
     668                 :            : 
     669                 :            : static void
     670                 :       6149 : persist_entry_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
     671                 :            : {
     672                 :       6149 :         struct ftl_md_io_entry_ctx *ctx = cb_arg;
     673   [ #  #  #  # ]:       6149 :         struct ftl_md *md = ctx->md;
     674                 :            : 
     675   [ #  #  #  #  :       6149 :         ftl_stats_bdev_io_completed(md->dev, get_bdev_io_ftl_stats_type(md->dev, bdev_io), bdev_io);
             #  #  #  # ]
     676                 :            : 
     677                 :       6149 :         spdk_bdev_free_io(bdev_io);
     678                 :            : 
     679   [ -  +  #  #  :       6149 :         assert(ctx->remaining > 0);
             #  #  #  # ]
     680         [ #  # ]:       6149 :         ctx->remaining--;
     681                 :            : 
     682   [ -  +  #  # ]:       6149 :         if (!success) {
     683   [ #  #  #  # ]:          0 :                 ctx->status = -EIO;
     684                 :          0 :         }
     685                 :            : 
     686   [ +  +  #  #  :       6149 :         if (!ctx->remaining) {
                   #  # ]
     687   [ #  #  #  #  :       6066 :                 ctx->cb(ctx->status, ctx->cb_arg);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     688                 :          0 :         }
     689                 :       6149 : }
     690                 :            : 
     691                 :            : static int
     692                 :       6149 : ftl_md_persist_entry_write_blocks(struct ftl_md_io_entry_ctx *ctx, struct ftl_md *md,
     693                 :            :                                   spdk_bdev_io_wait_cb retry_fn)
     694                 :            : {
     695                 :          0 :         int rc;
     696                 :            : 
     697   [ #  #  #  #  :       6149 :         rc = write_blocks(md->dev, md->region->bdev_desc, md->region->ioch,
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     698   [ #  #  #  #  :          0 :                           ctx->buffer, ctx->vss_buffer,
             #  #  #  # ]
     699   [ #  #  #  #  :       6149 :                           persist_entry_lba(md, ctx->start_entry), md->region->entry_size,
          #  #  #  #  #  
                #  #  # ]
     700                 :          0 :                           persist_entry_cb, ctx);
     701         [ -  + ]:       6149 :         if (spdk_unlikely(rc)) {
     702         [ #  # ]:          0 :                 if (rc == -ENOMEM) {
     703   [ #  #  #  #  :          0 :                         struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(md->region->bdev_desc);
             #  #  #  # ]
     704   [ #  #  #  #  :          0 :                         ctx->bdev_io_wait.bdev = bdev;
                   #  # ]
     705   [ #  #  #  #  :          0 :                         ctx->bdev_io_wait.cb_fn = retry_fn;
                   #  # ]
     706   [ #  #  #  #  :          0 :                         ctx->bdev_io_wait.cb_arg = ctx;
                   #  # ]
     707   [ #  #  #  #  :          0 :                         spdk_bdev_queue_io_wait(bdev, md->region->ioch, &ctx->bdev_io_wait);
          #  #  #  #  #  
                      # ]
     708                 :          0 :                 } else {
     709         [ #  # ]:          0 :                         ftl_abort();
     710                 :            :                 }
     711                 :          0 :         }
     712                 :            : 
     713                 :       6149 :         return rc;
     714                 :          0 : }
     715                 :            : 
     716                 :            : static void
     717                 :         83 : ftl_md_persist_entry_mirror(void *_ctx)
     718                 :            : {
     719                 :         83 :         struct ftl_md_io_entry_ctx *ctx = _ctx;
     720   [ #  #  #  # ]:         83 :         struct ftl_md *md_mirror = ftl_md_get_mirror(ctx->md);
     721                 :            : 
     722                 :         83 :         ftl_md_persist_entry_write_blocks(ctx, md_mirror, ftl_md_persist_entry_mirror);
     723                 :         83 : }
     724                 :            : 
     725                 :            : static void
     726                 :       6066 : ftl_md_persist_entry_primary(void *_ctx)
     727                 :            : {
     728                 :       6066 :         struct ftl_md_io_entry_ctx *ctx = _ctx;
     729   [ #  #  #  # ]:       6066 :         struct ftl_md *md = ctx->md;
     730                 :          0 :         int rc;
     731                 :            : 
     732                 :       6066 :         rc = ftl_md_persist_entry_write_blocks(ctx, md, ftl_md_persist_entry_primary);
     733                 :            : 
     734   [ +  -  +  + ]:       6066 :         if (!rc && has_mirror(md)) {
     735   [ -  +  #  #  :         83 :                 assert(md->region->entry_size == (ftl_md_get_mirror(md))->region->entry_size);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     736                 :            : 
     737                 :            :                 /* The MD object has mirror so execute persist on it too */
     738                 :         83 :                 ftl_md_persist_entry_mirror(ctx);
     739         [ #  # ]:         83 :                 ctx->remaining++;
     740                 :          0 :         }
     741                 :       6066 : }
     742                 :            : 
     743                 :            : static void
     744                 :       6066 : _ftl_md_persist_entry(struct ftl_md_io_entry_ctx *ctx)
     745                 :            : {
     746   [ #  #  #  # ]:       6066 :         ctx->status = 0;
     747   [ #  #  #  # ]:       6066 :         ctx->remaining = 1;
     748                 :            : 
     749                 :            :         /* First execute an IO to the primary region */
     750                 :       6066 :         ftl_md_persist_entry_primary(ctx);
     751                 :       6066 : }
     752                 :            : 
     753                 :            : void
     754                 :       6066 : ftl_md_persist_entry(struct ftl_md *md, uint64_t start_entry, void *buffer, void *vss_buffer,
     755                 :            :                      ftl_md_io_entry_cb cb, void *cb_arg,
     756                 :            :                      struct ftl_md_io_entry_ctx *ctx)
     757                 :            : {
     758   [ -  +  #  #  :       6066 :         if (spdk_unlikely(0 == md->region->entry_size)) {
          #  #  #  #  #  
                      # ]
     759                 :            :                 /* This MD has not been configured to support persist entry call */
     760         [ #  # ]:          0 :                 ftl_abort();
     761                 :          0 :         }
     762                 :            : 
     763                 :            :         /* Initialize persist entry context */
     764   [ #  #  #  # ]:       6066 :         ctx->cb = cb;
     765   [ #  #  #  # ]:       6066 :         ctx->cb_arg = cb_arg;
     766   [ #  #  #  # ]:       6066 :         ctx->md = md;
     767   [ #  #  #  # ]:       6066 :         ctx->start_entry = start_entry;
     768   [ #  #  #  # ]:       6066 :         ctx->buffer = buffer;
     769   [ +  +  #  #  :       6066 :         ctx->vss_buffer = vss_buffer ? : md->entry_vss_dma_buf;
          #  #  #  #  #  
                      # ]
     770                 :            : 
     771                 :       6066 :         _ftl_md_persist_entry(ctx);
     772                 :       6066 : }
     773                 :            : 
     774                 :            : static void
     775                 :          0 : read_entry_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
     776                 :            : {
     777                 :          0 :         struct ftl_md_io_entry_ctx *ctx = cb_arg;
     778   [ #  #  #  # ]:          0 :         struct ftl_md *md = ctx->md;
     779                 :            : 
     780   [ #  #  #  #  :          0 :         ftl_stats_bdev_io_completed(md->dev, get_bdev_io_ftl_stats_type(md->dev, bdev_io), bdev_io);
             #  #  #  # ]
     781                 :            : 
     782                 :          0 :         spdk_bdev_free_io(bdev_io);
     783                 :            : 
     784   [ #  #  #  # ]:          0 :         if (!success) {
     785         [ #  # ]:          0 :                 if (has_mirror(md)) {
     786   [ #  #  #  # ]:          0 :                         md->mirror_enabled = true;
     787                 :            : 
     788                 :            :                         /* First read from the mirror */
     789   [ #  #  #  #  :          0 :                         ftl_md_read_entry(ftl_md_get_mirror(md), ctx->start_entry, ctx->buffer,
             #  #  #  # ]
     790   [ #  #  #  # ]:          0 :                                           ctx->vss_buffer,
     791   [ #  #  #  #  :          0 :                                           ctx->cb, ctx->cb_arg,
             #  #  #  # ]
     792                 :          0 :                                           ctx);
     793                 :          0 :                         return;
     794                 :            :                 } else {
     795   [ #  #  #  # ]:          0 :                         ctx->status = -EIO;
     796                 :          0 :                         goto finish_io;
     797                 :            :                 }
     798                 :            :         }
     799                 :            : 
     800                 :          0 : finish_io:
     801   [ #  #  #  #  :          0 :         ctx->cb(ctx->status, ctx->cb_arg);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     802         [ #  # ]:          0 : }
     803                 :            : 
     804                 :            : static void
     805                 :          0 : ftl_md_read_entry_read_blocks(struct ftl_md_io_entry_ctx *ctx, struct ftl_md *md,
     806                 :            :                               spdk_bdev_io_wait_cb retry_fn)
     807                 :            : {
     808                 :          0 :         int rc;
     809                 :            : 
     810   [ #  #  #  #  :          0 :         rc = read_blocks(md->dev, md->region->bdev_desc, md->region->ioch,
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     811   [ #  #  #  #  :          0 :                          ctx->buffer, ctx->vss_buffer,
             #  #  #  # ]
     812   [ #  #  #  #  :          0 :                          persist_entry_lba(md, ctx->start_entry), md->region->entry_size,
          #  #  #  #  #  
                #  #  # ]
     813                 :          0 :                          read_entry_cb, ctx);
     814                 :            : 
     815         [ #  # ]:          0 :         if (spdk_unlikely(rc)) {
     816         [ #  # ]:          0 :                 if (rc == -ENOMEM) {
     817   [ #  #  #  #  :          0 :                         struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(md->region->bdev_desc);
             #  #  #  # ]
     818   [ #  #  #  #  :          0 :                         ctx->bdev_io_wait.bdev = bdev;
                   #  # ]
     819   [ #  #  #  #  :          0 :                         ctx->bdev_io_wait.cb_fn = retry_fn;
                   #  # ]
     820   [ #  #  #  #  :          0 :                         ctx->bdev_io_wait.cb_arg = ctx;
                   #  # ]
     821   [ #  #  #  #  :          0 :                         spdk_bdev_queue_io_wait(bdev, md->region->ioch, &ctx->bdev_io_wait);
          #  #  #  #  #  
                      # ]
     822                 :          0 :                 } else {
     823         [ #  # ]:          0 :                         ftl_abort();
     824                 :            :                 }
     825                 :          0 :         }
     826                 :          0 : }
     827                 :            : 
     828                 :            : static void
     829                 :          0 : _ftl_md_read_entry(void *_ctx)
     830                 :            : {
     831                 :          0 :         struct ftl_md_io_entry_ctx *ctx = _ctx;
     832                 :            : 
     833   [ #  #  #  # ]:          0 :         ftl_md_read_entry_read_blocks(ctx, ctx->md, _ftl_md_read_entry);
     834                 :          0 : }
     835                 :            : 
     836                 :            : void
     837                 :          0 : ftl_md_read_entry(struct ftl_md *md, uint64_t start_entry, void *buffer, void *vss_buffer,
     838                 :            :                   ftl_md_io_entry_cb cb, void *cb_arg,
     839                 :            :                   struct ftl_md_io_entry_ctx *ctx)
     840                 :            : {
     841   [ #  #  #  #  :          0 :         if (spdk_unlikely(0 == md->region->entry_size)) {
          #  #  #  #  #  
                      # ]
     842                 :            :                 /* This MD has not been configured to support read entry call */
     843         [ #  # ]:          0 :                 ftl_abort();
     844                 :          0 :         }
     845                 :            : 
     846   [ #  #  #  # ]:          0 :         ctx->cb = cb;
     847   [ #  #  #  # ]:          0 :         ctx->cb_arg = cb_arg;
     848   [ #  #  #  # ]:          0 :         ctx->md = md;
     849   [ #  #  #  # ]:          0 :         ctx->start_entry = start_entry;
     850   [ #  #  #  # ]:          0 :         ctx->buffer = buffer;
     851   [ #  #  #  # ]:          0 :         ctx->vss_buffer = vss_buffer;
     852                 :            : 
     853                 :          0 :         _ftl_md_read_entry(ctx);
     854                 :          0 : }
     855                 :            : 
     856                 :            : void
     857                 :          0 : ftl_md_persist_entry_retry(struct ftl_md_io_entry_ctx *ctx)
     858                 :            : {
     859                 :          0 :         _ftl_md_persist_entry(ctx);
     860                 :          0 : }
     861                 :            : 
     862                 :            : static void
     863                 :        146 : persist_mirror_cb(struct spdk_ftl_dev *dev, struct ftl_md *md, int status)
     864                 :            : {
     865   [ #  #  #  #  :        146 :         struct ftl_md *primary = md->owner.private;
                   #  # ]
     866                 :            : 
     867         [ -  + ]:        146 :         if (status) {
     868                 :            :                 /* We got an error, stop persist procedure immediately */
     869   [ #  #  #  #  :          0 :                 primary->io.status = status;
                   #  # ]
     870                 :          0 :                 io_done(primary);
     871                 :          0 :         } else {
     872                 :            :                 /* Now continue the persist procedure on the primary MD object */
     873         [ +  - ]:        146 :                 if (0 == io_init(primary, FTL_MD_OP_PERSIST)) {
     874                 :        146 :                         io_submit(primary);
     875                 :          0 :                 } else {
     876                 :          0 :                         spdk_thread_send_msg(spdk_get_thread(), exception, primary);
     877                 :            :                 }
     878                 :            :         }
     879                 :        146 : }
     880                 :            : 
     881                 :            : void
     882                 :        337 : ftl_md_persist(struct ftl_md *md)
     883                 :            : {
     884         [ +  + ]:        337 :         if (has_mirror(md)) {
     885                 :        146 :                 struct ftl_md *md_mirror = ftl_md_get_mirror(md);
     886                 :            : 
     887   [ #  #  #  # ]:        146 :                 md->mirror_enabled = true;
     888                 :            : 
     889                 :            :                 /* Set callback and context in mirror */
     890   [ #  #  #  # ]:        146 :                 md_mirror->cb = persist_mirror_cb;
     891   [ #  #  #  #  :        146 :                 md_mirror->owner.private = md;
                   #  # ]
     892                 :            : 
     893                 :            :                 /* First persist the mirror */
     894                 :        146 :                 ftl_md_persist(md_mirror);
     895                 :        146 :                 return;
     896                 :          0 :         }
     897                 :            : 
     898         [ +  - ]:        191 :         if (0 == io_init(md, FTL_MD_OP_PERSIST)) {
     899                 :        191 :                 io_submit(md);
     900                 :          0 :         } else {
     901                 :          0 :                 spdk_thread_send_msg(spdk_get_thread(), exception, md);
     902                 :            :         }
     903                 :          0 : }
     904                 :            : 
     905                 :            : static void
     906                 :          0 : restore_mirror_cb(struct spdk_ftl_dev *dev, struct ftl_md *md, int status)
     907                 :            : {
     908   [ #  #  #  #  :          0 :         struct ftl_md *primary = md->owner.private;
                   #  # ]
     909                 :            : 
     910         [ #  # ]:          0 :         if (status) {
     911                 :            :                 /* Cannot restore the object from the mirror too, mark error and fail */
     912   [ #  #  #  #  :          0 :                 primary->io.status = -EIO;
                   #  # ]
     913                 :          0 :                 io_done(primary);
     914                 :          0 :         } else {
     915                 :            :                 /*
     916                 :            :                  * Restoring from the mirror successful. Synchronize mirror to the primary.
     917                 :            :                  * Because we read MD content from the mirror, we can disable it, only the primary
     918                 :            :                  * requires persisting.
     919                 :            :                  */
     920   [ #  #  #  #  :          0 :                 primary->io.status = 0;
                   #  # ]
     921   [ #  #  #  # ]:          0 :                 primary->mirror_enabled = false;
     922                 :          0 :                 io_cleanup(primary);
     923                 :          0 :                 ftl_md_persist(primary);
     924   [ #  #  #  # ]:          0 :                 primary->mirror_enabled = true;
     925                 :            :         }
     926                 :          0 : }
     927                 :            : 
     928                 :            : static void
     929                 :          3 : restore_sync_cb(struct spdk_ftl_dev *dev, struct ftl_md *md, int status)
     930                 :            : {
     931   [ #  #  #  #  :          3 :         struct ftl_md *primary = md->owner.private;
                   #  # ]
     932                 :            : 
     933         [ -  + ]:          3 :         if (status) {
     934                 :            :                 /* Cannot sync the object from the primary to the mirror, mark error and fail */
     935   [ #  #  #  #  :          0 :                 primary->io.status = -EIO;
                   #  # ]
     936                 :          0 :                 io_done(primary);
     937                 :          0 :         } else {
     938   [ #  #  #  #  :          3 :                 primary->cb(dev, primary, primary->io.status);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     939                 :          3 :                 io_cleanup(primary);
     940                 :            :         }
     941                 :          3 : }
     942                 :            : 
     943                 :            : static int
     944                 :        151 : restore_done(struct ftl_md *md)
     945                 :            : {
     946   [ -  +  #  #  :        151 :         if (-EAGAIN == md->io.status) {
             #  #  #  # ]
     947                 :            :                 /* Failed to read MD from primary region, try it from mirror.
     948                 :            :                  * At the moment read the mirror entirely, (TODO) in the
     949                 :            :                  * feature we can restore from primary and mirror region
     950                 :            :                  * with finer granularity.
     951                 :            :                  */
     952                 :            : 
     953         [ #  # ]:          0 :                 if (has_mirror(md)) {
     954                 :          0 :                         struct ftl_md *md_mirror = ftl_md_get_mirror(md);
     955                 :            : 
     956   [ #  #  #  # ]:          0 :                         md->mirror_enabled = true;
     957                 :            : 
     958                 :            :                         /* Set callback and context in mirror */
     959   [ #  #  #  # ]:          0 :                         md_mirror->cb = restore_mirror_cb;
     960   [ #  #  #  #  :          0 :                         md_mirror->owner.private = md;
                   #  # ]
     961                 :            : 
     962                 :            :                         /* First persist the mirror */
     963                 :          0 :                         ftl_md_restore(md_mirror);
     964                 :          0 :                         return -EAGAIN;
     965                 :          0 :                 } else {
     966                 :          0 :                         return -EIO;
     967                 :            :                 }
     968   [ +  -  +  +  :        151 :         } else if (0 == md->io.status && false == md->dev->sb->clean) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
     969         [ +  + ]:          7 :                 if (has_mirror(md)) {
     970                 :          3 :                         struct ftl_md *md_mirror = ftl_md_get_mirror(md);
     971                 :            :                         /* There was a dirty shutdown, synchronize primary to mirror */
     972                 :            : 
     973                 :            :                         /* Set callback and context in the mirror */
     974   [ #  #  #  # ]:          3 :                         md_mirror->cb = restore_sync_cb;
     975   [ #  #  #  #  :          3 :                         md_mirror->owner.private = md;
                   #  # ]
     976                 :            : 
     977                 :            :                         /* First persist the mirror */
     978                 :          3 :                         ftl_md_persist(md_mirror);
     979                 :          3 :                         return -EAGAIN;
     980                 :          0 :                 }
     981                 :          0 :         }
     982                 :            : 
     983   [ #  #  #  #  :        148 :         return md->io.status;
                   #  # ]
     984                 :          0 : }
     985                 :            : 
     986                 :            : static void
     987                 :        508 : io_done(struct ftl_md *md)
     988                 :            : {
     989                 :          0 :         int status;
     990                 :            : 
     991   [ +  +  #  #  :        508 :         if (md->io.op == FTL_MD_OP_RESTORE) {
             #  #  #  # ]
     992                 :        151 :                 status = restore_done(md);
     993                 :          0 :         } else {
     994   [ #  #  #  #  :        357 :                 status = md->io.status;
                   #  # ]
     995                 :            :         }
     996                 :            : 
     997         [ +  + ]:        508 :         if (status != -EAGAIN) {
     998                 :            :                 /* The MD instance may be destroyed in ctx of md->cb(), e.g. upon region upgrade. */
     999                 :            :                 /* Need to cleanup DMA bufs first. */
    1000                 :        505 :                 io_cleanup(md);
    1001   [ #  #  #  #  :        505 :                 md->cb(md->dev, md, status);
          #  #  #  #  #  
                #  #  # ]
    1002                 :          0 :         }
    1003                 :        508 : }
    1004                 :            : 
    1005                 :            : void
    1006                 :        151 : ftl_md_restore(struct ftl_md *md)
    1007                 :            : {
    1008         [ +  - ]:        151 :         if (0 == io_init(md, FTL_MD_OP_RESTORE)) {
    1009                 :        151 :                 io_submit(md);
    1010                 :          0 :         } else {
    1011                 :          0 :                 spdk_thread_send_msg(spdk_get_thread(), exception, md);
    1012                 :            :         }
    1013                 :        151 : }
    1014                 :            : 
    1015                 :            : static int
    1016                 :         20 : pattern_prepare(struct ftl_md *md,
    1017                 :            :                 int data_pattern, union ftl_md_vss *vss_pattern)
    1018                 :            : {
    1019   [ #  #  #  #  :         20 :         void *data = md->io.data;
                   #  # ]
    1020                 :         20 :         uint64_t data_size = xfer_size(md);
    1021                 :            : 
    1022         [ -  + ]:         20 :         memset(data, data_pattern, data_size);
    1023                 :            : 
    1024   [ +  -  #  #  :         20 :         if (md->io.md) {
             #  #  #  # ]
    1025         [ +  + ]:         20 :                 if (vss_pattern) {
    1026                 :            :                         /* store the VSS pattern... */
    1027   [ #  #  #  #  :          5 :                         ftl_md_vss_buf_init(md->io.md, ftl_md_xfer_blocks(md->dev), vss_pattern);
          #  #  #  #  #  
                      # ]
    1028                 :          0 :                 } else {
    1029                 :            :                         /* ...or default init VSS to 0 */
    1030                 :         15 :                         union ftl_md_vss vss = {0};
    1031                 :            : 
    1032   [ #  #  #  #  :         15 :                         vss.version.md_version = md->region->current.version;
          #  #  #  #  #  
                #  #  # ]
    1033   [ #  #  #  #  :         15 :                         ftl_md_vss_buf_init(md->io.md, ftl_md_xfer_blocks(md->dev), &vss);
          #  #  #  #  #  
                      # ]
    1034                 :          0 :                 }
    1035                 :          0 :         }
    1036                 :            : 
    1037                 :         20 :         return 0;
    1038                 :          0 : }
    1039                 :            : 
    1040                 :            : static void
    1041                 :          5 : clear_mirror_cb(struct spdk_ftl_dev *dev, struct ftl_md *secondary, int status)
    1042                 :            : {
    1043   [ #  #  #  #  :          5 :         struct ftl_md *primary = secondary->owner.private;
                   #  # ]
    1044                 :            : 
    1045         [ -  + ]:          5 :         if (status) {
    1046                 :            :                 /* We got an error, stop persist procedure immediately */
    1047   [ #  #  #  #  :          0 :                 primary->io.status = status;
                   #  # ]
    1048                 :          0 :                 io_done(primary);
    1049                 :          0 :         } else {
    1050                 :            :                 /* Now continue the persist procedure on the primary MD object */
    1051                 :          5 :                 io_submit(primary);
    1052                 :            :         }
    1053                 :          5 : }
    1054                 :            : 
    1055                 :            : void
    1056                 :         20 : ftl_md_clear(struct ftl_md *md, int data_pattern, union ftl_md_vss *vss_pattern)
    1057                 :            : {
    1058         [ +  + ]:         20 :         if (has_mirror(md)) {
    1059                 :          5 :                 struct ftl_md *md_mirror = ftl_md_get_mirror(md);
    1060                 :            : 
    1061   [ #  #  #  # ]:          5 :                 md->mirror_enabled = true;
    1062                 :            : 
    1063                 :            :                 /* Set callback and context in mirror */
    1064   [ #  #  #  # ]:          5 :                 md_mirror->cb = clear_mirror_cb;
    1065   [ #  #  #  #  :          5 :                 md_mirror->owner.private = md;
                   #  # ]
    1066                 :            : 
    1067                 :            :                 /* The pattern bufs will not be available outside of this fn context */
    1068                 :            :                 /* Configure the IO for the primary region now */
    1069   [ +  -  +  - ]:          5 :                 if (0 == io_init(md, FTL_MD_OP_CLEAR) && 0 == pattern_prepare(md, data_pattern, vss_pattern)) {
    1070                 :            :                         /* First persist the mirror */
    1071                 :          5 :                         ftl_md_clear(md_mirror, data_pattern, vss_pattern);
    1072                 :          0 :                 } else {
    1073                 :          0 :                         spdk_thread_send_msg(spdk_get_thread(), exception, md);
    1074                 :            :                 }
    1075                 :          5 :                 return;
    1076                 :          0 :         }
    1077                 :            : 
    1078   [ +  -  +  - ]:         15 :         if (0 == io_init(md, FTL_MD_OP_CLEAR) && 0 == pattern_prepare(md, data_pattern, vss_pattern)) {
    1079                 :         15 :                 io_submit(md);
    1080                 :          0 :         } else {
    1081                 :          0 :                 spdk_thread_send_msg(spdk_get_thread(), exception, md);
    1082                 :            :         }
    1083                 :          0 : }
    1084                 :            : 
    1085                 :            : const struct ftl_layout_region *
    1086                 :         81 : ftl_md_get_region(struct ftl_md *md)
    1087                 :            : {
    1088   [ #  #  #  # ]:         81 :         return md->region;
    1089                 :            : }
    1090                 :            : 
    1091                 :            : void
    1092                 :        352 : ftl_md_set_region(struct ftl_md *md,
    1093                 :            :                   const struct ftl_layout_region *region)
    1094                 :            : {
    1095   [ -  +  #  #  :        352 :         assert(region->current.blocks <= md->data_blocks);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1096   [ #  #  #  # ]:        352 :         md->region = region;
    1097                 :            : 
    1098   [ +  +  #  #  :        352 :         if (md->vss_data) {
                   #  # ]
    1099                 :        176 :                 union ftl_md_vss vss = {0};
    1100   [ #  #  #  #  :        176 :                 vss.version.md_version = region->current.version;
             #  #  #  # ]
    1101   [ #  #  #  #  :        176 :                 ftl_md_vss_buf_init(md->vss_data, md->data_blocks, &vss);
             #  #  #  # ]
    1102   [ +  +  #  #  :        176 :                 if (region->entry_size) {
                   #  # ]
    1103   [ -  +  #  #  :        154 :                         assert(md->entry_vss_dma_buf);
             #  #  #  # ]
    1104   [ #  #  #  #  :        154 :                         ftl_md_vss_buf_init(md->entry_vss_dma_buf, region->entry_size, &vss);
             #  #  #  # ]
    1105                 :          0 :                 }
    1106                 :          0 :         }
    1107                 :            : 
    1108         [ +  + ]:        352 :         if (has_mirror(md)) {
    1109   [ #  #  #  # ]:         88 :                 md->mirror_enabled = true;
    1110                 :          0 :         }
    1111                 :        352 : }
    1112                 :            : 
    1113                 :            : int
    1114                 :        198 : ftl_md_create_region_flags(struct spdk_ftl_dev *dev, int region_type)
    1115                 :            : {
    1116                 :        198 :         int flags = FTL_MD_CREATE_SHM;
    1117                 :            : 
    1118   [ +  +  +  + ]:        198 :         switch (region_type) {
    1119                 :         22 :         case FTL_LAYOUT_REGION_TYPE_SB:
    1120   [ +  +  #  #  :         22 :                 if (dev->conf.mode & SPDK_FTL_MODE_CREATE) {
             #  #  #  # ]
    1121                 :          5 :                         flags |= FTL_MD_CREATE_SHM_NEW;
    1122                 :          0 :                 }
    1123                 :         22 :                 break;
    1124                 :            : 
    1125                 :         44 :         case FTL_LAYOUT_REGION_TYPE_BAND_MD:
    1126                 :            :         case FTL_LAYOUT_REGION_TYPE_NVC_MD:
    1127         [ +  - ]:         44 :                 if (!ftl_fast_startup(dev)) {
    1128                 :         44 :                         flags |= FTL_MD_CREATE_SHM_NEW;
    1129                 :          0 :                 }
    1130                 :         44 :                 break;
    1131                 :         44 :         case FTL_LAYOUT_REGION_TYPE_VALID_MAP:
    1132                 :            :         case FTL_LAYOUT_REGION_TYPE_TRIM_MD:
    1133   [ +  -  +  + ]:         44 :                 if (!ftl_fast_startup(dev) && !ftl_fast_recovery(dev)) {
    1134                 :         42 :                         flags |= FTL_MD_CREATE_SHM_NEW;
    1135                 :          0 :                 }
    1136                 :         44 :                 break;
    1137                 :         88 :         default:
    1138                 :         88 :                 return FTL_MD_CREATE_HEAP;
    1139                 :            :         }
    1140                 :            : 
    1141                 :        110 :         return flags;
    1142                 :          0 : }
    1143                 :            : 
    1144                 :            : int
    1145                 :        440 : ftl_md_destroy_region_flags(struct spdk_ftl_dev *dev, int region_type)
    1146                 :            : {
    1147         [ +  + ]:        440 :         switch (region_type) {
    1148                 :        110 :         case FTL_LAYOUT_REGION_TYPE_SB:
    1149                 :            :         case FTL_LAYOUT_REGION_TYPE_BAND_MD:
    1150                 :            :         case FTL_LAYOUT_REGION_TYPE_VALID_MAP:
    1151                 :            :         case FTL_LAYOUT_REGION_TYPE_NVC_MD:
    1152                 :            :         case FTL_LAYOUT_REGION_TYPE_TRIM_MD:
    1153   [ -  +  -  +  :        110 :                 if (dev->conf.fast_shutdown) {
          #  #  #  #  #  
                      # ]
    1154                 :          0 :                         return FTL_MD_DESTROY_SHM_KEEP;
    1155                 :            :                 }
    1156                 :        110 :                 break;
    1157                 :            : 
    1158                 :        330 :         default:
    1159                 :        330 :                 break;
    1160                 :            :         }
    1161                 :        440 :         return 0;
    1162                 :          0 : }
    1163                 :            : 
    1164                 :            : int
    1165                 :        110 : ftl_md_create_shm_flags(struct spdk_ftl_dev *dev)
    1166                 :            : {
    1167                 :        110 :         int flags = FTL_MD_CREATE_SHM;
    1168                 :            : 
    1169   [ +  -  +  + ]:        110 :         if (!ftl_fast_startup(dev) && !ftl_fast_recovery(dev)) {
    1170                 :        105 :                 flags |= FTL_MD_CREATE_SHM_NEW;
    1171                 :          0 :         }
    1172                 :        110 :         return flags;
    1173                 :          0 : }
    1174                 :            : 
    1175                 :            : int
    1176                 :        132 : ftl_md_destroy_shm_flags(struct spdk_ftl_dev *dev)
    1177                 :            : {
    1178   [ -  +  #  #  :        132 :         return (dev->conf.fast_shutdown) ? FTL_MD_DESTROY_SHM_KEEP : 0;
             #  #  #  # ]
    1179                 :            : }

Generated by: LCOV version 1.14