LCOV - code coverage report
Current view: top level - spdk/lib/ftl/utils - ftl_layout_tracker_bdev.c (source / functions) Hit Total Coverage
Test: Combined Lines: 233 255 91.4 %
Date: 2024-12-15 21:03:41 Functions: 14 14 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 555 1135 48.9 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright 2023 Solidigm All Rights Reserved
       3                 :            :  */
       4                 :            : 
       5                 :            : #include "ftl_layout_tracker_bdev.h"
       6                 :            : #include "spdk/util.h"
       7                 :            : 
       8                 :            : #define REG_VER_ANY     UINT32_MAX
       9                 :            : 
      10                 :            : struct layout_tracker_entry {
      11                 :            :         TAILQ_ENTRY(layout_tracker_entry) layout_entry;
      12                 :            :         struct ftl_layout_tracker_bdev_region_props reg;
      13                 :            : };
      14                 :            : 
      15                 :            : struct ftl_layout_tracker_bdev {
      16                 :            :         TAILQ_HEAD(layout_tracker, layout_tracker_entry) layout_head;
      17                 :            :         uint64_t bdev_blks;
      18                 :            :         uint32_t regs_cnt;
      19                 :            : };
      20                 :            : 
      21                 :            : struct layout_tracker_blob_entry {
      22                 :            :         /* Region type */
      23                 :            :         uint32_t type;
      24                 :            : 
      25                 :            :         /* Region version */
      26                 :            :         uint32_t ver;
      27                 :            : 
      28                 :            :         /* Region offset in blocks */
      29                 :            :         uint64_t blk_offs;
      30                 :            : 
      31                 :            :         /* Region size in blocks */
      32                 :            :         uint64_t blk_sz;
      33                 :            : } __attribute__((packed));
      34                 :            : 
      35                 :            : static int
      36                 :        222 : layout_tracker_init_entries(struct ftl_layout_tracker_bdev *tracker, uint64_t bdev_blks)
      37                 :            : {
      38                 :        222 :         struct layout_tracker_entry *entry_free = calloc(1, sizeof(*entry_free));
      39                 :            : 
      40         [ +  + ]:        222 :         if (!entry_free) {
      41                 :          0 :                 return -ENOMEM;
      42                 :            :         }
      43                 :            : 
      44   [ +  +  #  # ]:        222 :         assert(tracker);
      45   [ +  +  +  -  :        222 :         assert(tracker->regs_cnt == 0);
             +  -  #  # ]
      46                 :            : 
      47   [ +  -  +  - ]:        222 :         tracker->bdev_blks = bdev_blks;
      48   [ +  -  +  - ]:        222 :         tracker->regs_cnt = 1;
      49   [ +  -  +  -  :        222 :         TAILQ_INIT(&tracker->layout_head);
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
      50                 :            : 
      51   [ +  -  +  -  :        222 :         entry_free->reg.blk_sz = bdev_blks;
                   +  - ]
      52   [ +  -  +  -  :        222 :         entry_free->reg.type = FTL_LAYOUT_REGION_TYPE_FREE;
                   +  - ]
      53                 :            : 
      54   [ +  +  +  -  :        222 :         TAILQ_INSERT_HEAD(&tracker->layout_head, entry_free, layout_entry);
          +  -  +  -  +  
          -  +  -  -  +  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
      55                 :        222 :         return 0;
      56                 :         24 : }
      57                 :            : 
      58                 :            : struct ftl_layout_tracker_bdev *
      59                 :         68 : ftl_layout_tracker_bdev_init(uint64_t bdev_blks)
      60                 :            : {
      61                 :         68 :         struct ftl_layout_tracker_bdev *tracker = calloc(1, sizeof(*tracker));
      62                 :            : 
      63         [ +  + ]:         68 :         if (!tracker) {
      64                 :          0 :                 return NULL;
      65                 :            :         }
      66                 :            : 
      67         [ +  + ]:         68 :         if (layout_tracker_init_entries(tracker, bdev_blks)) {
      68                 :          0 :                 free(tracker);
      69                 :          0 :                 return NULL;
      70                 :            :         }
      71                 :            : 
      72                 :         68 :         return tracker;
      73                 :          4 : }
      74                 :            : 
      75                 :            : static void
      76                 :        222 : layout_tracker_free_entries(struct ftl_layout_tracker_bdev *tracker)
      77                 :            : {
      78                 :         24 :         struct layout_tracker_entry *entry;
      79                 :            : 
      80   [ +  +  +  -  :       2016 :         while ((entry = TAILQ_FIRST(&tracker->layout_head))) {
             +  -  +  + ]
      81   [ +  +  +  -  :       1794 :                 TAILQ_REMOVE(&tracker->layout_head, entry, layout_entry);
          +  -  +  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                -  +  - ]
      82                 :       1794 :                 free(entry);
      83                 :            :         }
      84   [ +  -  +  - ]:        222 :         tracker->regs_cnt = 0;
      85                 :        222 : }
      86                 :            : 
      87                 :            : void
      88                 :         68 : ftl_layout_tracker_bdev_fini(struct ftl_layout_tracker_bdev *tracker)
      89                 :            : {
      90   [ +  +  #  # ]:         68 :         assert(tracker);
      91                 :         68 :         layout_tracker_free_entries(tracker);
      92                 :         68 :         free(tracker);
      93                 :         68 : }
      94                 :            : 
      95                 :            : static struct layout_tracker_entry *
      96                 :        306 : layout_region_find_min_free(struct ftl_layout_tracker_bdev *tracker, uint64_t blk_sz,
      97                 :            :                             uint64_t blk_align)
      98                 :            : {
      99                 :        306 :         struct layout_tracker_entry *min_free_entry = NULL;
     100                 :         32 :         struct layout_tracker_entry *entry;
     101                 :            : 
     102   [ +  +  #  # ]:        306 :         assert(tracker);
     103                 :            : 
     104   [ +  +  +  -  :       1994 :         TAILQ_FOREACH(entry, &tracker->layout_head, layout_entry) {
          +  -  +  +  +  
             -  +  -  +  
                      - ]
     105                 :        194 :                 uint64_t align_offs, align_sz;
     106                 :            : 
     107   [ +  +  -  +  :       1688 :                 if (entry->reg.type != FTL_LAYOUT_REGION_TYPE_FREE) {
             -  +  +  + ]
     108                 :       1377 :                         continue;
     109                 :            :                 }
     110                 :            : 
     111   [ -  +  -  +  :        311 :                 align_offs = entry->reg.blk_offs;
                   -  + ]
     112   [ -  +  -  +  :        311 :                 align_sz = entry->reg.blk_sz;
                   -  + ]
     113         [ +  + ]:        311 :                 if (blk_align) {
     114                 :        229 :                         align_offs = SPDK_ALIGN_CEIL(align_offs, blk_align);
     115   [ +  -  +  -  :        229 :                         align_sz -= (align_offs - entry->reg.blk_offs);
                   +  - ]
     116                 :         32 :                 }
     117                 :            : 
     118         [ +  + ]:        311 :                 if (align_sz >= blk_sz) {
     119   [ -  +  -  -  :        306 :                         if (!min_free_entry || min_free_entry->reg.blk_sz > entry->reg.blk_sz) {
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     120                 :        306 :                                 min_free_entry = entry;
     121                 :         32 :                         }
     122                 :         32 :                 }
     123      [ -  +  + ]:        194 :         }
     124                 :            : 
     125                 :        338 :         return min_free_entry;
     126                 :         32 : }
     127                 :            : 
     128                 :            : static struct layout_tracker_entry *
     129                 :       4019 : layout_region_find_from(struct ftl_layout_tracker_bdev *tracker,
     130                 :            :                         enum ftl_layout_region_type reg_type,
     131                 :            :                         uint32_t reg_ver, struct layout_tracker_entry *entry)
     132                 :            : {
     133   [ +  +  #  # ]:       4019 :         assert(tracker);
     134                 :            : 
     135   [ +  +  +  +  :      22907 :         TAILQ_FOREACH_FROM(entry, &tracker->layout_head, layout_entry) {
          #  #  #  #  +  
          +  +  -  +  -  
                   +  - ]
     136   [ +  +  +  +  :      21377 :                 if ((entry->reg.type == reg_type || reg_type == FTL_LAYOUT_REGION_TYPE_INVALID)
             +  -  +  + ]
     137   [ +  +  +  +  :       4806 :                     && (entry->reg.ver == reg_ver || reg_ver == REG_VER_ANY)) {
          +  -  +  -  +  
                      + ]
     138                 :       2295 :                         return entry;
     139                 :            :                 }
     140                 :       2476 :         }
     141                 :            : 
     142                 :       1724 :         return NULL;
     143                 :        414 : }
     144                 :            : 
     145                 :            : static struct layout_tracker_entry *
     146                 :       3207 : layout_region_find_first(struct ftl_layout_tracker_bdev *tracker,
     147                 :            :                          enum ftl_layout_region_type reg_type,
     148                 :            :                          uint32_t reg_ver)
     149                 :            : {
     150   [ +  -  +  -  :       3207 :         return layout_region_find_from(tracker, reg_type, reg_ver, TAILQ_FIRST(&tracker->layout_head));
                   +  - ]
     151                 :            : }
     152                 :            : 
     153                 :            : static struct layout_tracker_entry *
     154                 :        907 : layout_region_find_next(struct ftl_layout_tracker_bdev *tracker,
     155                 :            :                         enum ftl_layout_region_type reg_type,
     156                 :            :                         uint32_t reg_ver, struct layout_tracker_entry *entry)
     157                 :            : {
     158   [ +  +  +  -  :        907 :         if ((entry = TAILQ_NEXT(entry, layout_entry))) {
             +  -  +  + ]
     159                 :        812 :                 return layout_region_find_from(tracker, reg_type, reg_ver, entry);
     160                 :            :         }
     161                 :         95 :         return NULL;
     162                 :         24 : }
     163                 :            : 
     164                 :            : const struct ftl_layout_tracker_bdev_region_props *
     165                 :        306 : ftl_layout_tracker_bdev_add_region(struct ftl_layout_tracker_bdev *tracker,
     166                 :            :                                    enum ftl_layout_region_type reg_type, uint32_t reg_ver, uint64_t blk_sz, uint64_t blk_align)
     167                 :            : {
     168                 :         32 :         struct layout_tracker_entry *entry_free;
     169                 :         32 :         struct layout_tracker_entry *entry_new;
     170                 :         32 :         uint64_t entry_free_blks_left;
     171                 :            : 
     172   [ +  +  #  # ]:        306 :         assert(tracker);
     173   [ +  +  #  # ]:        306 :         assert(reg_type < FTL_LAYOUT_REGION_TYPE_MAX);
     174                 :            : 
     175                 :        306 :         entry_new = layout_region_find_first(tracker, reg_type, reg_ver);
     176         [ -  + ]:        306 :         if (entry_new) {
     177                 :            :                 /* Region already exists */
     178                 :          0 :                 return NULL;
     179                 :            :         }
     180                 :            : 
     181                 :        306 :         entry_free = layout_region_find_min_free(tracker, blk_sz, blk_align);
     182         [ +  + ]:        306 :         if (!entry_free) {
     183                 :            :                 /* No free space */
     184                 :          0 :                 return NULL;
     185                 :            :         }
     186                 :            : 
     187                 :            :         /* Takce care of the alignment */
     188         [ +  + ]:        306 :         if (blk_align) {
     189                 :            :                 /* Calculate the aligned region's offs and size */
     190   [ +  -  +  -  :        224 :                 uint64_t align_offs = SPDK_ALIGN_CEIL(entry_free->reg.blk_offs, blk_align);
                   +  - ]
     191   [ +  +  +  -  :        224 :                 assert(align_offs >= entry_free->reg.blk_offs);
          +  -  +  -  #  
                      # ]
     192                 :            : 
     193                 :            :                 /* Subdivide the free region in two: unaligned free region, followed by the aligned free region */
     194   [ +  +  +  -  :        224 :                 if (align_offs > entry_free->reg.blk_offs) {
             +  -  +  - ]
     195   [ #  #  #  #  :          5 :                         uint64_t unaligned_sz = align_offs - entry_free->reg.blk_offs;
                   #  # ]
     196                 :            : 
     197                 :            :                         /* Setup the unaligned region */
     198                 :          5 :                         entry_new = calloc(1, sizeof(*entry_new));
     199         [ -  + ]:          5 :                         if (!entry_new) {
     200                 :          0 :                                 return NULL;
     201                 :            :                         }
     202   [ #  #  #  # ]:          5 :                         entry_new->reg = entry_free->reg;
     203   [ #  #  #  #  :          5 :                         entry_new->reg.blk_sz = unaligned_sz;
                   #  # ]
     204                 :            : 
     205                 :            :                         /* Setup the aligned region - shrink the free region found */
     206   [ #  #  #  #  :          5 :                         entry_free->reg.blk_offs = align_offs;
                   #  # ]
     207   [ #  #  #  #  :          5 :                         entry_free->reg.blk_sz -= unaligned_sz;
                   #  # ]
     208                 :            : 
     209                 :            :                         /* Add the unaligned region prev to the aligned one */
     210   [ #  #  #  #  :          5 :                         TAILQ_INSERT_BEFORE(entry_free, entry_new, layout_entry);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     211         [ #  # ]:          5 :                         tracker->regs_cnt++;
     212         [ #  # ]:          0 :                 }
     213         [ -  + ]:         32 :         }
     214                 :            : 
     215   [ +  -  +  -  :        306 :         entry_free_blks_left = entry_free->reg.blk_sz - blk_sz;
                   +  - ]
     216                 :            : 
     217         [ +  - ]:        306 :         if (entry_free_blks_left) {
     218                 :            :                 /* Subdivide the free region */
     219                 :        306 :                 entry_new = calloc(1, sizeof(*entry_new));
     220         [ +  + ]:        306 :                 if (!entry_new) {
     221                 :          0 :                         return NULL;
     222                 :            :                 }
     223                 :            : 
     224                 :            :                 /* Setup the new region at the beginning of the free region found */
     225   [ +  -  +  -  :        306 :                 entry_new->reg.type = reg_type;
                   +  - ]
     226   [ +  -  +  -  :        306 :                 entry_new->reg.ver = reg_ver;
                   +  - ]
     227   [ +  -  +  -  :        306 :                 entry_new->reg.blk_offs = entry_free->reg.blk_offs;
          +  -  +  -  +  
                -  +  - ]
     228   [ +  -  +  -  :        306 :                 entry_new->reg.blk_sz = blk_sz;
                   +  - ]
     229                 :            : 
     230                 :            :                 /* Shrink the free region found */
     231   [ +  -  +  -  :        306 :                 entry_free->reg.blk_offs += blk_sz;
                   +  - ]
     232   [ +  -  +  -  :        306 :                 entry_free->reg.blk_sz = entry_free_blks_left;
                   +  - ]
     233                 :            : 
     234                 :            :                 /* Add the new region */
     235   [ +  -  +  -  :        306 :                 TAILQ_INSERT_BEFORE(entry_free, entry_new, layout_entry);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
     236         [ +  - ]:        306 :                 tracker->regs_cnt++;
     237                 :         32 :         } else {
     238                 :            :                 /* Setup the new region in place */
     239                 :          0 :                 entry_new = entry_free;
     240   [ #  #  #  #  :          0 :                 entry_new->reg.type = reg_type;
                   #  # ]
     241   [ #  #  #  #  :          0 :                 entry_new->reg.ver = reg_ver;
                   #  # ]
     242                 :            :         }
     243                 :            : 
     244         [ +  - ]:        306 :         return &entry_new->reg;
     245                 :         32 : }
     246                 :            : 
     247                 :            : const struct ftl_layout_tracker_bdev_region_props *
     248                 :       1256 : ftl_layout_tracker_bdev_insert_region(struct ftl_layout_tracker_bdev *tracker,
     249                 :            :                                       enum ftl_layout_region_type reg_type, uint32_t reg_ver,
     250                 :            :                                       uint64_t blk_offs, uint64_t blk_sz)
     251                 :            : {
     252                 :        164 :         struct layout_tracker_entry *entry_free;
     253                 :        164 :         struct layout_tracker_entry *entry_new;
     254                 :        164 :         uint64_t entry_free_blks_left;
     255                 :            : 
     256   [ +  +  #  # ]:       1256 :         assert(tracker);
     257                 :            : 
     258   [ +  +  +  + ]:       1256 :         if (reg_type >= FTL_LAYOUT_REGION_TYPE_MAX && reg_type != FTL_LAYOUT_REGION_TYPE_INVALID) {
     259                 :            :                 /* Invalid region type */
     260                 :         12 :                 return NULL;
     261                 :            :         }
     262                 :            : 
     263                 :       1244 :         entry_new = layout_region_find_first(tracker, reg_type, reg_ver);
     264         [ +  + ]:       1244 :         if (entry_new) {
     265                 :            :                 /* Region already exists */
     266                 :          6 :                 return NULL;
     267                 :            :         }
     268                 :            : 
     269                 :            :         /* Look up for the free region corresponding to the blk_offs */
     270         [ +  + ]:       1241 :         for (entry_free = layout_region_find_first(tracker, FTL_LAYOUT_REGION_TYPE_FREE, REG_VER_ANY);
     271         [ +  + ]:       1273 :              entry_free;
     272                 :         38 :              entry_free = layout_region_find_next(tracker, FTL_LAYOUT_REGION_TYPE_FREE, REG_VER_ANY,
     273                 :          3 :                              entry_free)) {
     274                 :            :                 /* Test if the region being added fits into the free region */
     275   [ +  +  +  -  :       1421 :                 if (entry_free->reg.blk_offs <= blk_offs
             +  -  +  + ]
     276   [ +  +  +  -  :       1251 :                     && blk_offs + blk_sz <= entry_free->reg.blk_offs + entry_free->reg.blk_sz) {
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     277                 :       1226 :                         break;
     278                 :            :                 }
     279                 :          3 :         }
     280                 :            : 
     281         [ +  + ]:       1238 :         if (!entry_free) {
     282                 :            :                 /* Did not found the corresponding free region */
     283                 :         12 :                 return NULL;
     284                 :            :         }
     285                 :            : 
     286   [ +  -  +  -  :       1226 :         entry_free_blks_left = blk_offs - entry_free->reg.blk_offs;
                   +  - ]
     287         [ +  + ]:       1226 :         if (entry_free_blks_left) {
     288                 :            :                 /* Subdivide the free region */
     289                 :         53 :                 entry_new = calloc(1, sizeof(*entry_new));
     290         [ +  + ]:         53 :                 if (!entry_new) {
     291                 :          0 :                         return NULL;
     292                 :            :                 }
     293                 :            : 
     294                 :            :                 /* Setup another free region at the beginning of the free region found */
     295   [ +  -  +  -  :         53 :                 entry_new->reg.type = FTL_LAYOUT_REGION_TYPE_FREE;
                   +  - ]
     296   [ +  -  +  -  :         53 :                 entry_new->reg.blk_offs = entry_free->reg.blk_offs;
          +  -  +  -  +  
                -  +  - ]
     297   [ +  -  +  -  :         53 :                 entry_new->reg.blk_sz = entry_free_blks_left;
                   +  - ]
     298                 :            : 
     299                 :            :                 /* Shrink the free region found */
     300   [ +  -  +  -  :         53 :                 entry_free->reg.blk_offs += entry_free_blks_left;
                   +  - ]
     301   [ +  +  +  -  :         53 :                 assert(entry_free->reg.blk_sz > entry_free_blks_left);
          +  -  +  -  #  
                      # ]
     302   [ +  -  +  -  :         53 :                 entry_free->reg.blk_sz -= entry_free_blks_left;
                   +  - ]
     303                 :            : 
     304                 :            :                 /* Add the new free region */
     305   [ +  -  +  -  :         53 :                 TAILQ_INSERT_BEFORE(entry_free, entry_new, layout_entry);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
     306         [ +  - ]:         53 :                 tracker->regs_cnt++;
     307                 :          6 :         }
     308                 :            : 
     309   [ +  +  +  -  :       1226 :         assert(entry_free->reg.blk_offs == blk_offs);
          +  -  +  -  #  
                      # ]
     310   [ +  +  +  -  :       1226 :         assert(blk_sz <= entry_free->reg.blk_sz);
          +  -  +  -  #  
                      # ]
     311                 :            : 
     312   [ +  -  +  -  :       1226 :         entry_free_blks_left = entry_free->reg.blk_sz - blk_sz;
                   +  - ]
     313         [ +  + ]:       1226 :         if (entry_free_blks_left) {
     314                 :            :                 /* Subdivide the free region */
     315                 :       1220 :                 entry_new = calloc(1, sizeof(*entry_new));
     316         [ +  + ]:       1220 :                 if (!entry_new) {
     317                 :          0 :                         return NULL;
     318                 :            :                 }
     319                 :            : 
     320                 :            :                 /* Setup the new region at the beginning of the free region found */
     321   [ +  -  +  -  :       1220 :                 entry_new->reg.type = reg_type;
                   +  - ]
     322   [ +  -  +  -  :       1220 :                 entry_new->reg.ver = reg_ver;
                   +  - ]
     323   [ +  -  +  -  :       1220 :                 entry_new->reg.blk_offs = entry_free->reg.blk_offs;
          +  -  +  -  +  
                -  +  - ]
     324   [ +  -  +  -  :       1220 :                 entry_new->reg.blk_sz = blk_sz;
                   +  - ]
     325                 :            : 
     326                 :            :                 /* Shrink the free region found */
     327   [ +  -  +  -  :       1220 :                 entry_free->reg.blk_offs += blk_sz;
                   +  - ]
     328   [ +  -  +  -  :       1220 :                 entry_free->reg.blk_sz = entry_free_blks_left;
                   +  - ]
     329                 :            : 
     330                 :            :                 /* Add the new region */
     331   [ +  -  +  -  :       1220 :                 TAILQ_INSERT_BEFORE(entry_free, entry_new, layout_entry);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
     332         [ +  - ]:       1220 :                 tracker->regs_cnt++;
     333                 :        158 :         } else {
     334                 :            :                 /* Setup the new region in place */
     335                 :          6 :                 entry_new = entry_free;
     336   [ +  -  +  -  :          6 :                 entry_new->reg.type = reg_type;
                   +  - ]
     337   [ +  -  +  -  :          6 :                 entry_new->reg.ver = reg_ver;
                   +  - ]
     338                 :            :         }
     339                 :            : 
     340         [ +  - ]:       1226 :         return &entry_new->reg;
     341                 :        164 : }
     342                 :            : 
     343                 :            : int
     344                 :         18 : ftl_layout_tracker_bdev_rm_region(struct ftl_layout_tracker_bdev *tracker,
     345                 :            :                                   enum ftl_layout_region_type reg_type, uint32_t reg_ver)
     346                 :            : {
     347                 :          3 :         struct layout_tracker_entry *entry_rm, *entry_check __attribute__((unused));
     348                 :         18 :         struct layout_tracker_entry *entry = layout_region_find_first(tracker, reg_type, reg_ver);
     349                 :            : 
     350         [ +  + ]:         18 :         if (!entry) {
     351                 :          0 :                 return -1;
     352                 :            :         }
     353                 :            : 
     354                 :            :         /* Free the region */
     355   [ +  -  +  -  :         18 :         entry->reg.type = FTL_LAYOUT_REGION_TYPE_FREE;
                   +  - ]
     356   [ +  -  +  -  :         18 :         entry->reg.ver = 0;
                   +  - ]
     357                 :            : 
     358                 :            :         /* Join with the adjacent free region prev to the current region */
     359   [ +  -  +  -  :         18 :         entry_rm = TAILQ_PREV(entry, layout_tracker, layout_entry);
          +  -  +  -  +  
                -  +  - ]
     360   [ +  -  +  +  :         18 :         if (entry_rm && entry_rm->reg.type == FTL_LAYOUT_REGION_TYPE_FREE) {
          +  -  +  -  +  
                      + ]
     361   [ +  -  +  -  :          6 :                 TAILQ_REMOVE(&tracker->layout_head, entry_rm, layout_entry);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  #  #  #  
          #  #  #  #  #  
          #  #  #  #  +  
          -  +  -  +  -  
          +  -  +  -  +  
                -  +  - ]
     362   [ +  -  +  -  :          6 :                 entry->reg.blk_offs = entry_rm->reg.blk_offs;
          +  -  +  -  +  
                -  +  - ]
     363   [ +  -  +  -  :          6 :                 entry->reg.blk_sz += entry_rm->reg.blk_sz;
          +  -  +  -  +  
                -  +  - ]
     364                 :            : 
     365                 :            : #if defined(DEBUG)
     366   [ +  -  +  -  :          6 :                 entry_check = TAILQ_PREV(entry, layout_tracker, layout_entry);
          +  -  +  -  +  
                -  +  - ]
     367         [ +  + ]:          6 :                 if (entry_check) {
     368   [ +  +  +  -  :          6 :                         assert(entry_check->reg.type != FTL_LAYOUT_REGION_TYPE_FREE);
          +  -  +  -  #  
                      # ]
     369                 :          1 :                 }
     370                 :            : #endif
     371                 :            : 
     372                 :          6 :                 free(entry_rm);
     373         [ +  - ]:          6 :                 tracker->regs_cnt--;
     374                 :          1 :         }
     375                 :            : 
     376                 :            :         /* Join with the adjacent free region next to the current region */
     377   [ +  -  +  -  :         18 :         entry_rm = TAILQ_NEXT(entry, layout_entry);
                   +  - ]
     378   [ +  -  +  +  :         18 :         if (entry_rm && entry_rm->reg.type == FTL_LAYOUT_REGION_TYPE_FREE) {
          +  -  +  -  +  
                      + ]
     379   [ +  +  +  -  :          6 :                 TAILQ_REMOVE(&tracker->layout_head, entry_rm, layout_entry);
          +  -  -  +  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                -  +  - ]
     380   [ +  -  +  -  :          6 :                 entry->reg.blk_sz += entry_rm->reg.blk_sz;
          +  -  +  -  +  
                -  +  - ]
     381                 :            : 
     382                 :            : #if defined(DEBUG)
     383   [ +  -  +  -  :          6 :                 entry_check = TAILQ_NEXT(entry, layout_entry);
                   +  - ]
     384         [ +  + ]:          6 :                 if (entry_check) {
     385   [ #  #  #  #  :          0 :                         assert(entry_check->reg.type != FTL_LAYOUT_REGION_TYPE_FREE);
          #  #  #  #  #  
                      # ]
     386                 :          0 :                 }
     387                 :            : #endif
     388                 :          6 :                 free(entry_rm);
     389         [ +  - ]:          6 :                 tracker->regs_cnt--;
     390                 :          1 :         }
     391                 :            : 
     392                 :         18 :         return 0;
     393                 :          3 : }
     394                 :            : 
     395                 :            : void
     396                 :       1273 : ftl_layout_tracker_bdev_find_next_region(struct ftl_layout_tracker_bdev *tracker,
     397                 :            :                 enum ftl_layout_region_type reg_type,
     398                 :            :                 const struct ftl_layout_tracker_bdev_region_props **search_ctx)
     399                 :            : {
     400                 :         55 :         struct layout_tracker_entry *entry;
     401                 :            : 
     402         [ +  + ]:       1273 :         if (!search_ctx) {
     403                 :          0 :                 return;
     404                 :            :         }
     405                 :            : 
     406   [ +  +  +  + ]:       1273 :         if (*search_ctx == NULL) {
     407                 :            :                 /* Return the first region found */
     408                 :        401 :                 entry = layout_region_find_first(tracker, reg_type, REG_VER_ANY);
     409                 :         34 :         } else {
     410                 :            :                 /* Find the next region */
     411         [ +  - ]:        872 :                 entry = SPDK_CONTAINEROF(*search_ctx, struct layout_tracker_entry, reg);
     412                 :        872 :                 entry = layout_region_find_next(tracker, reg_type, REG_VER_ANY, entry);
     413                 :            :         }
     414   [ +  +  +  -  :       1273 :         *search_ctx = entry ? &entry->reg : NULL;
                   +  - ]
     415         [ -  + ]:         55 : }
     416                 :            : 
     417                 :            : size_t
     418                 :         68 : ftl_layout_tracker_bdev_blob_store(struct ftl_layout_tracker_bdev *tracker, void *blob_buf,
     419                 :            :                                    size_t blob_buf_sz)
     420                 :            : {
     421                 :         68 :         struct layout_tracker_blob_entry *blob_entry = blob_buf;
     422                 :          4 :         struct layout_tracker_entry *entry;
     423                 :         68 :         size_t blob_sz = 0;
     424                 :            : 
     425   [ +  +  #  # ]:         68 :         assert(tracker);
     426                 :            : 
     427   [ +  +  +  -  :        702 :         TAILQ_FOREACH(entry, &tracker->layout_head, layout_entry) {
          +  -  +  +  +  
             -  +  -  +  
                      - ]
     428         [ +  + ]:        634 :                 if (blob_sz + sizeof(*blob_entry) > blob_buf_sz) {
     429                 :            :                         /* Ran out of buf space */
     430         [ #  # ]:          0 :                         assert(false);
     431                 :            :                         return 0;
     432                 :            :                 }
     433                 :            : 
     434                 :            :                 /* Skip the free space entries */
     435   [ +  +  +  -  :        634 :                 if (entry->reg.type == FTL_LAYOUT_REGION_TYPE_FREE) {
             +  -  +  + ]
     436                 :         90 :                         continue;
     437                 :            :                 }
     438                 :            : 
     439                 :            :                 /* Store the entry */
     440   [ +  -  +  -  :        544 :                 blob_entry->type = entry->reg.type;
          +  -  +  -  +  
                      - ]
     441   [ +  -  +  -  :        544 :                 blob_entry->ver = entry->reg.ver;
          +  -  +  -  +  
                      - ]
     442   [ +  -  +  -  :        544 :                 blob_entry->blk_offs = entry->reg.blk_offs;
          +  -  +  -  +  
                      - ]
     443   [ +  -  +  -  :        544 :                 blob_entry->blk_sz = entry->reg.blk_sz;
          +  -  +  -  +  
                      - ]
     444                 :            : 
     445                 :            :                 /* Move to the next entry */
     446         [ +  - ]:        544 :                 blob_entry++;
     447                 :        544 :                 blob_sz += sizeof(*blob_entry);
     448                 :         32 :         }
     449                 :            : 
     450                 :         72 :         return blob_sz;
     451                 :          4 : }
     452                 :            : 
     453                 :            : int
     454                 :        154 : ftl_layout_tracker_bdev_blob_load(struct ftl_layout_tracker_bdev *tracker, void *blob_buf,
     455                 :            :                                   size_t blob_sz)
     456                 :            : {
     457                 :        154 :         struct layout_tracker_blob_entry *blob_entry = blob_buf;
     458         [ +  - ]:        154 :         size_t blob_entry_num = blob_sz / sizeof(*blob_entry);
     459         [ +  - ]:        154 :         struct layout_tracker_blob_entry *blob_entry_end = blob_entry + blob_entry_num;
     460                 :            : 
     461   [ +  +  -  + ]:        154 :         if (blob_sz % sizeof(*blob_entry) != 0) {
     462                 :            :                 /* Invalid blob size */
     463                 :          0 :                 return -1;
     464                 :            :         }
     465                 :            : 
     466                 :            :         /* Free the current MD layout tracking info */
     467                 :        154 :         layout_tracker_free_entries(tracker);
     468                 :            : 
     469                 :            :         /* Reinit MD layout tracking info */
     470   [ +  +  +  -  :        154 :         if (layout_tracker_init_entries(tracker, tracker->bdev_blks)) {
                   -  + ]
     471                 :          0 :                 return -1;
     472                 :            :         }
     473                 :            : 
     474   [ +  +  +  - ]:       1368 :         for (; blob_entry < blob_entry_end; blob_entry++) {
     475                 :            :                 /* Verify the type */
     476   [ +  +  +  -  :       1244 :                 if (blob_entry->type == FTL_LAYOUT_REGION_TYPE_FREE) {
                   +  - ]
     477                 :          0 :                         return -1;
     478                 :            :                 }
     479                 :            : 
     480                 :            :                 /* Load the entry */
     481   [ +  +  +  -  :       1406 :                 if (!ftl_layout_tracker_bdev_insert_region(tracker, blob_entry->type, blob_entry->ver,
          +  -  +  -  +  
                      + ]
     482   [ +  -  +  -  :        162 :                                 blob_entry->blk_offs, blob_entry->blk_sz)) {
             +  -  +  - ]
     483                 :         30 :                         return -1;
     484                 :            :                 }
     485                 :        157 :         }
     486                 :            : 
     487                 :        124 :         return 0;
     488                 :         20 : }

Generated by: LCOV version 1.15