LCOV - code coverage report
Current view: top level - spdk/lib/ftl - ftl_band.c (source / functions) Hit Total Coverage
Test: Combined Lines: 215 342 62.9 %
Date: 2024-07-15 14:57:06 Functions: 33 43 76.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 65 186 34.9 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (C) 2018 Intel Corporation.
       3                 :            :  *   All rights reserved.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include "spdk/stdinc.h"
       7                 :            : #include "spdk/crc32.h"
       8                 :            : #include "spdk/likely.h"
       9                 :            : #include "spdk/util.h"
      10                 :            : #include "spdk/ftl.h"
      11                 :            : 
      12                 :            : #include "ftl_band.h"
      13                 :            : #include "ftl_io.h"
      14                 :            : #include "ftl_core.h"
      15                 :            : #include "ftl_debug.h"
      16                 :            : #include "ftl_internal.h"
      17                 :            : #include "utils/ftl_md.h"
      18                 :            : #include "utils/ftl_defs.h"
      19                 :            : 
      20                 :            : static uint64_t
      21                 :       8693 : ftl_band_tail_md_offset(const struct ftl_band *band)
      22                 :            : {
      23                 :      17386 :         return ftl_get_num_blocks_in_band(band->dev) -
      24                 :       8693 :                ftl_tail_md_num_blocks(band->dev);
      25                 :            : }
      26                 :            : 
      27                 :            : int
      28                 :       4621 : ftl_band_filled(struct ftl_band *band, size_t offset)
      29                 :            : {
      30                 :       4621 :         return offset == ftl_band_tail_md_offset(band);
      31                 :            : }
      32                 :            : 
      33                 :            : static void
      34                 :         34 : ftl_band_free_p2l_map(struct ftl_band *band)
      35                 :            : {
      36                 :         34 :         struct spdk_ftl_dev *dev = band->dev;
      37                 :         34 :         struct ftl_p2l_map *p2l_map = &band->p2l_map;
      38                 :            : 
      39   [ -  +  -  - ]:         34 :         assert(band->md->state == FTL_BAND_STATE_CLOSED ||
      40                 :            :                band->md->state == FTL_BAND_STATE_FREE);
      41         [ -  + ]:         34 :         assert(p2l_map->ref_cnt == 0);
      42         [ -  + ]:         34 :         assert(p2l_map->band_map != NULL);
      43                 :            : 
      44                 :         34 :         band->md->df_p2l_map = FTL_DF_OBJ_ID_INVALID;
      45                 :         34 :         ftl_mempool_put(dev->p2l_pool, p2l_map->band_map);
      46                 :         34 :         p2l_map->band_map = NULL;
      47                 :         34 : }
      48                 :            : 
      49                 :            : 
      50                 :            : static void
      51                 :         34 : ftl_band_free_md_entry(struct ftl_band *band)
      52                 :            : {
      53                 :         34 :         struct spdk_ftl_dev *dev = band->dev;
      54                 :         34 :         struct ftl_p2l_map *p2l_map = &band->p2l_map;
      55                 :            : 
      56   [ -  +  -  - ]:         34 :         assert(band->md->state == FTL_BAND_STATE_CLOSED ||
      57                 :            :                band->md->state == FTL_BAND_STATE_FREE);
      58         [ -  + ]:         34 :         assert(p2l_map->band_dma_md != NULL);
      59                 :            : 
      60                 :         34 :         ftl_mempool_put(dev->band_md_pool, p2l_map->band_dma_md);
      61                 :         34 :         p2l_map->band_dma_md = NULL;
      62                 :         34 : }
      63                 :            : 
      64                 :            : static void
      65                 :       2029 : _ftl_band_set_free(struct ftl_band *band)
      66                 :            : {
      67                 :       2029 :         struct spdk_ftl_dev *dev = band->dev;
      68                 :            : 
      69                 :            :         /* Add the band to the free band list */
      70                 :       2029 :         TAILQ_INSERT_TAIL(&dev->free_bands, band, queue_entry);
      71                 :       2029 :         band->md->close_seq_id = 0;
      72                 :       2029 :         band->reloc = false;
      73                 :            : 
      74                 :       2029 :         dev->num_free++;
      75                 :       2029 :         ftl_apply_limits(dev);
      76                 :            : 
      77                 :       2029 :         band->md->p2l_map_checksum = 0;
      78                 :       2029 : }
      79                 :            : 
      80                 :            : static void
      81                 :          6 : _ftl_band_set_preparing(struct ftl_band *band)
      82                 :            : {
      83                 :          6 :         struct spdk_ftl_dev *dev = band->dev;
      84                 :            : 
      85                 :            :         /* Remove band from free list */
      86         [ +  - ]:          6 :         TAILQ_REMOVE(&dev->free_bands, band, queue_entry);
      87                 :            : 
      88                 :          6 :         band->md->wr_cnt++;
      89                 :            : 
      90         [ -  + ]:          6 :         assert(dev->num_free > 0);
      91                 :          6 :         dev->num_free--;
      92                 :            : 
      93                 :          6 :         ftl_apply_limits(dev);
      94                 :          6 : }
      95                 :            : 
      96                 :            : static void
      97                 :          4 : _ftl_band_set_closed_cb(struct ftl_band *band, bool valid)
      98                 :            : {
      99                 :          4 :         struct spdk_ftl_dev *dev = band->dev;
     100                 :            : 
     101         [ -  + ]:          4 :         assert(valid == true);
     102                 :            : 
     103                 :            :         /* Set the state as free_md() checks for that */
     104                 :          4 :         band->md->state = FTL_BAND_STATE_CLOSED;
     105         [ +  - ]:          4 :         if (band->owner.state_change_fn) {
     106                 :          4 :                 band->owner.state_change_fn(band);
     107                 :            :         }
     108                 :            : 
     109                 :          4 :         ftl_p2l_validate_ckpt(band);
     110                 :            : 
     111                 :            :         /* Free the P2L map if there are no outstanding IOs */
     112                 :          4 :         ftl_band_release_p2l_map(band);
     113         [ -  + ]:          4 :         assert(band->p2l_map.ref_cnt == 0);
     114                 :            : 
     115                 :          4 :         TAILQ_INSERT_TAIL(&dev->shut_bands, band, queue_entry);
     116                 :          4 : }
     117                 :            : 
     118                 :            : static void
     119                 :          4 : _ftl_band_set_closed(struct ftl_band *band)
     120                 :            : {
     121                 :            :         /* Verify that band's metadata is consistent with l2p */
     122                 :          4 :         ftl_band_validate_md(band, _ftl_band_set_closed_cb);
     123                 :          4 : }
     124                 :            : 
     125                 :            : ftl_addr
     126                 :       2036 : ftl_band_tail_md_addr(struct ftl_band *band)
     127                 :            : {
     128                 :            :         ftl_addr addr;
     129                 :            : 
     130                 :            :         /* Metadata should be aligned to xfer size */
     131   [ -  +  -  + ]:       2036 :         assert(ftl_band_tail_md_offset(band) % band->dev->xfer_size == 0);
     132                 :            : 
     133                 :       2036 :         addr = ftl_band_tail_md_offset(band) + band->start_addr;
     134                 :            : 
     135                 :       2036 :         return addr;
     136                 :            : }
     137                 :            : 
     138                 :            : const char *
     139                 :         54 : ftl_band_get_state_name(struct ftl_band *band)
     140                 :            : {
     141                 :            :         static const char *names[] = {
     142                 :            :                 "FREE", "PREPARING", "OPENING", "OPEN", "FULL", "CLOSING",
     143                 :            :                 "CLOSED",
     144                 :            :         };
     145                 :            : 
     146         [ -  + ]:         54 :         assert(band->md->state < SPDK_COUNTOF(names));
     147         [ +  - ]:         54 :         if (band->md->state < SPDK_COUNTOF(names)) {
     148                 :         54 :                 return names[band->md->state];
     149                 :            :         } else {
     150                 :          0 :                 assert(false);
     151                 :            :                 return "?";
     152                 :            :         }
     153                 :            : }
     154                 :            : 
     155                 :            : void
     156                 :        448 : ftl_band_set_state(struct ftl_band *band, enum ftl_band_state state)
     157                 :            : {
     158   [ +  +  +  +  :        448 :         switch (state) {
                   +  - ]
     159                 :        418 :         case FTL_BAND_STATE_FREE:
     160         [ -  + ]:        418 :                 assert(band->md->state == FTL_BAND_STATE_CLOSED);
     161                 :        418 :                 _ftl_band_set_free(band);
     162                 :        418 :                 break;
     163                 :            : 
     164                 :          6 :         case FTL_BAND_STATE_PREP:
     165         [ -  + ]:          6 :                 assert(band->md->state == FTL_BAND_STATE_FREE);
     166                 :          6 :                 _ftl_band_set_preparing(band);
     167                 :          6 :                 break;
     168                 :            : 
     169                 :          4 :         case FTL_BAND_STATE_CLOSED:
     170         [ +  - ]:          4 :                 if (band->md->state != FTL_BAND_STATE_CLOSED) {
     171         [ -  + ]:          4 :                         assert(band->md->state == FTL_BAND_STATE_CLOSING);
     172                 :          4 :                         _ftl_band_set_closed(band);
     173                 :          4 :                         return; /* state can be changed asynchronously */
     174                 :            :                 }
     175                 :          0 :                 break;
     176                 :            : 
     177                 :          6 :         case FTL_BAND_STATE_OPEN:
     178                 :          6 :                 band->md->p2l_map_checksum = 0;
     179                 :          6 :                 break;
     180                 :         14 :         case FTL_BAND_STATE_OPENING:
     181                 :            :         case FTL_BAND_STATE_FULL:
     182                 :            :         case FTL_BAND_STATE_CLOSING:
     183                 :         14 :                 break;
     184                 :          0 :         default:
     185         [ #  # ]:          0 :                 FTL_ERRLOG(band->dev, "Unknown band state, %u", state);
     186                 :          0 :                 assert(false);
     187                 :            :                 break;
     188                 :            :         }
     189                 :            : 
     190                 :        444 :         band->md->state = state;
     191                 :            : }
     192                 :            : 
     193                 :            : void
     194                 :          6 : ftl_band_set_type(struct ftl_band *band, enum ftl_band_type type)
     195                 :            : {
     196         [ +  - ]:          6 :         switch (type) {
     197                 :          6 :         case FTL_BAND_TYPE_COMPACTION:
     198                 :            :         case FTL_BAND_TYPE_GC:
     199                 :          6 :                 band->md->type = type;
     200                 :          6 :                 break;
     201                 :          0 :         default:
     202                 :          0 :                 assert(false);
     203                 :            :                 break;
     204                 :            :         }
     205                 :          6 : }
     206                 :            : 
     207                 :            : void
     208                 :     922905 : ftl_band_set_p2l(struct ftl_band *band, uint64_t lba, ftl_addr addr, uint64_t seq_id)
     209                 :            : {
     210                 :     922905 :         struct ftl_p2l_map *p2l_map = &band->p2l_map;
     211                 :            :         uint64_t offset;
     212                 :            : 
     213                 :     922905 :         offset = ftl_band_block_offset_from_addr(band, addr);
     214                 :            : 
     215                 :     922905 :         p2l_map->band_map[offset].lba = lba;
     216                 :     922905 :         p2l_map->band_map[offset].seq_id = seq_id;
     217                 :     922905 : }
     218                 :            : 
     219                 :            : void
     220                 :     922905 : ftl_band_set_addr(struct ftl_band *band, uint64_t lba, ftl_addr addr)
     221                 :            : {
     222                 :     922905 :         band->p2l_map.num_valid++;
     223                 :     922905 :         ftl_bitmap_set(band->dev->valid_map, addr);
     224                 :     922905 : }
     225                 :            : 
     226                 :            : size_t
     227                 :          0 : ftl_band_user_blocks_left(const struct ftl_band *band, size_t offset)
     228                 :            : {
     229                 :          0 :         size_t tail_md_offset = ftl_band_tail_md_offset(band);
     230                 :            : 
     231         [ #  # ]:          0 :         if (spdk_unlikely(offset > tail_md_offset)) {
     232                 :          0 :                 return 0;
     233                 :            :         }
     234                 :            : 
     235                 :          0 :         return tail_md_offset - offset;
     236                 :            : }
     237                 :            : 
     238                 :            : size_t
     239                 :       2112 : ftl_band_user_blocks(const struct ftl_band *band)
     240                 :            : {
     241                 :       4224 :         return ftl_get_num_blocks_in_band(band->dev) -
     242                 :       2112 :                ftl_tail_md_num_blocks(band->dev);
     243                 :            : }
     244                 :            : 
     245                 :            : static inline uint64_t
     246                 :    4109968 : ftl_addr_get_band(const struct spdk_ftl_dev *dev, ftl_addr addr)
     247                 :            : {
     248         [ -  + ]:    4109968 :         return (addr - dev->bands->start_addr) / ftl_get_num_blocks_in_band(dev);
     249                 :            : }
     250                 :            : 
     251                 :            : struct ftl_band *
     252                 :     922890 : ftl_band_from_addr(struct spdk_ftl_dev *dev, ftl_addr addr)
     253                 :            : {
     254                 :     922890 :         uint64_t band_id = ftl_addr_get_band(dev, addr);
     255                 :            : 
     256         [ -  + ]:     922890 :         assert(band_id < ftl_get_num_bands(dev));
     257                 :     922890 :         return &dev->bands[band_id];
     258                 :            : }
     259                 :            : 
     260                 :            : uint64_t
     261                 :    3132364 : ftl_band_block_offset_from_addr(struct ftl_band *band, ftl_addr addr)
     262                 :            : {
     263         [ -  + ]:    3132364 :         assert(ftl_addr_get_band(band->dev, addr) == band->id);
     264                 :    3132364 :         return addr - band->start_addr;
     265                 :            : }
     266                 :            : 
     267                 :            : ftl_addr
     268                 :       4639 : ftl_band_next_xfer_addr(struct ftl_band *band, ftl_addr addr, size_t num_blocks)
     269                 :            : {
     270                 :       4639 :         struct spdk_ftl_dev *dev = band->dev;
     271                 :            :         size_t num_xfers;
     272                 :            :         uint64_t offset;
     273                 :            : 
     274         [ -  + ]:       4639 :         assert(ftl_addr_get_band(dev, addr) == band->id);
     275                 :            : 
     276                 :       4639 :         offset = addr - band->start_addr;
     277                 :            : 
     278                 :            :         /* In case starting address wasn't aligned to xfer_size, we'll align for consistent calculation
     279                 :            :          * purposes - the unaligned value will be preserved at the end however.
     280                 :            :          */
     281         [ -  + ]:       4639 :         num_blocks += (offset % dev->xfer_size);
     282         [ -  + ]:       4639 :         offset -= (offset % dev->xfer_size);
     283                 :            : 
     284                 :            :         /* Calculate offset based on xfer_size aligned writes */
     285         [ -  + ]:       4639 :         num_xfers = (num_blocks / dev->xfer_size);
     286                 :       4639 :         offset += num_xfers * dev->xfer_size;
     287                 :       4639 :         num_blocks -= num_xfers * dev->xfer_size;
     288                 :            : 
     289         [ -  + ]:       4639 :         if (offset > ftl_get_num_blocks_in_band(dev)) {
     290                 :          0 :                 return FTL_ADDR_INVALID;
     291                 :            :         }
     292                 :            : 
     293                 :            :         /* If there's any unalignment (either starting addr value or num_blocks), reintroduce it to the final address
     294                 :            :          */
     295         [ +  + ]:       4639 :         if (num_blocks) {
     296                 :         10 :                 offset += num_blocks;
     297         [ -  + ]:         10 :                 if (offset > ftl_get_num_blocks_in_band(dev)) {
     298                 :          0 :                         return FTL_ADDR_INVALID;
     299                 :            :                 }
     300                 :            :         }
     301                 :            : 
     302                 :       4639 :         addr = band->start_addr + offset;
     303                 :       4639 :         return addr;
     304                 :            : }
     305                 :            : 
     306                 :            : ftl_addr
     307                 :    2940240 : ftl_band_addr_from_block_offset(struct ftl_band *band, uint64_t block_off)
     308                 :            : {
     309                 :            :         ftl_addr addr;
     310                 :            : 
     311                 :    2940240 :         addr = block_off + band->start_addr;
     312                 :    2940240 :         return addr;
     313                 :            : }
     314                 :            : 
     315                 :            : ftl_addr
     316                 :    2104832 : ftl_band_next_addr(struct ftl_band *band, ftl_addr addr, size_t offset)
     317                 :            : {
     318                 :    2104832 :         uint64_t block_off = ftl_band_block_offset_from_addr(band, addr);
     319                 :            : 
     320                 :    2104832 :         return ftl_band_addr_from_block_offset(band, block_off + offset);
     321                 :            : }
     322                 :            : 
     323                 :            : void
     324                 :         39 : ftl_band_acquire_p2l_map(struct ftl_band *band)
     325                 :            : {
     326         [ -  + ]:         39 :         assert(band->p2l_map.band_map != NULL);
     327                 :         39 :         band->p2l_map.ref_cnt++;
     328                 :         39 : }
     329                 :            : 
     330                 :            : static int
     331                 :         39 : ftl_band_alloc_md_entry(struct ftl_band *band)
     332                 :            : {
     333                 :         39 :         struct spdk_ftl_dev *dev = band->dev;
     334                 :         39 :         struct ftl_p2l_map *p2l_map = &band->p2l_map;
     335                 :         39 :         struct ftl_layout_region *region = ftl_layout_region_get(dev, FTL_LAYOUT_REGION_TYPE_BAND_MD);
     336                 :            : 
     337                 :         39 :         p2l_map->band_dma_md = ftl_mempool_get(dev->band_md_pool);
     338                 :            : 
     339         [ -  + ]:         39 :         if (!p2l_map->band_dma_md) {
     340                 :          0 :                 return -1;
     341                 :            :         }
     342                 :            : 
     343         [ -  + ]:         39 :         memset(p2l_map->band_dma_md, 0, region->entry_size * FTL_BLOCK_SIZE);
     344                 :         39 :         return 0;
     345                 :            : }
     346                 :            : 
     347                 :            : int
     348                 :         39 : ftl_band_alloc_p2l_map(struct ftl_band *band)
     349                 :            : {
     350                 :         39 :         struct spdk_ftl_dev *dev = band->dev;
     351                 :         39 :         struct ftl_p2l_map *p2l_map = &band->p2l_map;
     352                 :            : 
     353         [ -  + ]:         39 :         assert(p2l_map->ref_cnt == 0);
     354         [ -  + ]:         39 :         assert(p2l_map->band_map == NULL);
     355                 :            : 
     356         [ -  + ]:         39 :         assert(band->md->df_p2l_map == FTL_DF_OBJ_ID_INVALID);
     357                 :         39 :         p2l_map->band_map = ftl_mempool_get(dev->p2l_pool);
     358         [ -  + ]:         39 :         if (!p2l_map->band_map) {
     359                 :          0 :                 return -1;
     360                 :            :         }
     361                 :            : 
     362         [ -  + ]:         39 :         if (ftl_band_alloc_md_entry(band)) {
     363                 :          0 :                 ftl_band_free_p2l_map(band);
     364                 :          0 :                 return -1;
     365                 :            :         }
     366                 :            : 
     367                 :         39 :         band->md->df_p2l_map = ftl_mempool_get_df_obj_id(dev->p2l_pool, p2l_map->band_map);
     368                 :            : 
     369                 :            :         /* Set the P2L to FTL_LBA_INVALID */
     370         [ -  + ]:         39 :         memset(p2l_map->band_map, -1, FTL_BLOCK_SIZE * ftl_p2l_map_num_blocks(band->dev));
     371                 :            : 
     372                 :         39 :         ftl_band_acquire_p2l_map(band);
     373                 :         39 :         return 0;
     374                 :            : }
     375                 :            : 
     376                 :            : int
     377                 :          0 : ftl_band_open_p2l_map(struct ftl_band *band)
     378                 :            : {
     379                 :          0 :         struct spdk_ftl_dev *dev = band->dev;
     380                 :          0 :         struct ftl_p2l_map *p2l_map = &band->p2l_map;
     381                 :            : 
     382         [ #  # ]:          0 :         assert(p2l_map->ref_cnt == 0);
     383         [ #  # ]:          0 :         assert(p2l_map->band_map == NULL);
     384                 :            : 
     385         [ #  # ]:          0 :         assert(band->md->df_p2l_map != FTL_DF_OBJ_ID_INVALID);
     386                 :            : 
     387         [ #  # ]:          0 :         if (ftl_band_alloc_md_entry(band)) {
     388                 :          0 :                 p2l_map->band_map = NULL;
     389                 :          0 :                 return -1;
     390                 :            :         }
     391                 :            : 
     392                 :          0 :         p2l_map->band_map = ftl_mempool_claim_df(dev->p2l_pool, band->md->df_p2l_map);
     393                 :            : 
     394                 :          0 :         ftl_band_acquire_p2l_map(band);
     395                 :          0 :         return 0;
     396                 :            : }
     397                 :            : 
     398                 :            : void
     399                 :         34 : ftl_band_release_p2l_map(struct ftl_band *band)
     400                 :            : {
     401                 :         34 :         struct ftl_p2l_map *p2l_map = &band->p2l_map;
     402                 :            : 
     403         [ -  + ]:         34 :         assert(p2l_map->band_map != NULL);
     404         [ -  + ]:         34 :         assert(p2l_map->ref_cnt > 0);
     405                 :         34 :         p2l_map->ref_cnt--;
     406                 :            : 
     407         [ +  - ]:         34 :         if (p2l_map->ref_cnt == 0) {
     408         [ +  + ]:         34 :                 if (p2l_map->p2l_ckpt) {
     409                 :          4 :                         ftl_p2l_ckpt_release(band->dev, p2l_map->p2l_ckpt);
     410                 :          4 :                         p2l_map->p2l_ckpt = NULL;
     411                 :            :                 }
     412                 :         34 :                 ftl_band_free_p2l_map(band);
     413                 :         34 :                 ftl_band_free_md_entry(band);
     414                 :            :         }
     415                 :         34 : }
     416                 :            : 
     417                 :            : ftl_addr
     418                 :          0 : ftl_band_p2l_map_addr(struct ftl_band *band)
     419                 :            : {
     420                 :          0 :         return band->tail_md_addr;
     421                 :            : }
     422                 :            : 
     423                 :            : int
     424                 :          6 : ftl_band_write_prep(struct ftl_band *band)
     425                 :            : {
     426                 :          6 :         struct spdk_ftl_dev *dev = band->dev;
     427                 :            : 
     428         [ -  + ]:          6 :         if (ftl_band_alloc_p2l_map(band)) {
     429                 :          0 :                 return -1;
     430                 :            :         }
     431                 :            : 
     432                 :          6 :         band->p2l_map.p2l_ckpt = ftl_p2l_ckpt_acquire(dev);
     433                 :          6 :         band->md->p2l_md_region = ftl_p2l_ckpt_region_type(band->p2l_map.p2l_ckpt);
     434                 :          6 :         ftl_band_iter_init(band);
     435                 :            : 
     436                 :          6 :         band->md->seq = ftl_get_next_seq_id(dev);
     437                 :            : 
     438         [ +  - ]:          6 :         FTL_DEBUGLOG(dev, "Band to write, id %u seq %"PRIu64"\n", band->id, band->md->seq);
     439                 :          6 :         return 0;
     440                 :            : }
     441                 :            : 
     442                 :            : size_t
     443                 :         22 : ftl_p2l_map_pool_elem_size(struct spdk_ftl_dev *dev)
     444                 :            : {
     445                 :            :         /* Map pool element holds the whole tail md */
     446                 :         22 :         return ftl_tail_md_num_blocks(dev) * FTL_BLOCK_SIZE;
     447                 :            : }
     448                 :            : 
     449                 :            : double
     450                 :         54 : ftl_band_invalidity(struct ftl_band *band)
     451                 :            : {
     452                 :         54 :         double valid = band->p2l_map.num_valid;
     453                 :         54 :         double count = ftl_band_user_blocks(band);
     454                 :            : 
     455                 :         54 :         return 1.0 - (valid / count);
     456                 :            : }
     457                 :            : 
     458                 :            : static void
     459                 :          0 : dump_bands_under_relocation(struct spdk_ftl_dev *dev)
     460                 :            : {
     461                 :          0 :         uint64_t i = dev->sb_shm->gc_info.current_band_id;
     462                 :          0 :         uint64_t end = dev->sb_shm->gc_info.current_band_id + dev->num_logical_bands_in_physical;
     463                 :            : 
     464         [ #  # ]:          0 :         for (; i < end; i++) {
     465                 :          0 :                 struct ftl_band *band = &dev->bands[i];
     466                 :            : 
     467         [ #  # ]:          0 :                 FTL_DEBUGLOG(dev, "Band, id %u, phys_is %u, wr cnt = %u, invalidity = %u%%\n",
     468                 :            :                              band->id, band->phys_id, (uint32_t)band->md->wr_cnt,
     469                 :            :                              (uint32_t)(ftl_band_invalidity(band) * 100));
     470                 :            :         }
     471                 :          0 : }
     472                 :            : 
     473                 :            : static bool
     474                 :          0 : is_band_relocateable(struct ftl_band *band)
     475                 :            : {
     476                 :            :         /* Can only move data from closed bands */
     477         [ #  # ]:          0 :         if (FTL_BAND_STATE_CLOSED != band->md->state) {
     478                 :          0 :                 return false;
     479                 :            :         }
     480                 :            : 
     481                 :            :         /* Band is already under relocation, skip it */
     482   [ #  #  #  # ]:          0 :         if (band->reloc) {
     483                 :          0 :                 return false;
     484                 :            :         }
     485                 :            : 
     486                 :          0 :         return true;
     487                 :            : }
     488                 :            : 
     489                 :            : static void
     490                 :          0 : get_band_phys_info(struct spdk_ftl_dev *dev, uint64_t phys_id,
     491                 :            :                    double *invalidity, double *wr_cnt)
     492                 :            : {
     493                 :            :         struct ftl_band *band;
     494                 :          0 :         uint64_t band_id = phys_id * dev->num_logical_bands_in_physical;
     495                 :            : 
     496                 :          0 :         *wr_cnt = *invalidity = 0.0L;
     497         [ #  # ]:          0 :         for (; band_id < ftl_get_num_bands(dev); band_id++) {
     498                 :          0 :                 band = &dev->bands[band_id];
     499                 :            : 
     500         [ #  # ]:          0 :                 if (phys_id != band->phys_id) {
     501                 :          0 :                         break;
     502                 :            :                 }
     503                 :            : 
     504                 :          0 :                 *wr_cnt += band->md->wr_cnt;
     505                 :            : 
     506         [ #  # ]:          0 :                 if (!is_band_relocateable(band)) {
     507                 :          0 :                         continue;
     508                 :            :                 }
     509                 :            : 
     510                 :          0 :                 *invalidity += ftl_band_invalidity(band);
     511                 :            :         }
     512                 :            : 
     513                 :          0 :         *invalidity /= dev->num_logical_bands_in_physical;
     514                 :          0 :         *wr_cnt /= dev->num_logical_bands_in_physical;
     515                 :          0 : }
     516                 :            : 
     517                 :            : static bool
     518                 :          0 : band_cmp(double a_invalidity, double a_wr_cnt,
     519                 :            :          double b_invalidity, double b_wr_cnt,
     520                 :            :          uint64_t a_id, uint64_t b_id)
     521                 :            : {
     522         [ #  # ]:          0 :         assert(a_id != FTL_BAND_PHYS_ID_INVALID);
     523         [ #  # ]:          0 :         assert(b_id != FTL_BAND_PHYS_ID_INVALID);
     524                 :          0 :         double diff = a_invalidity - b_invalidity;
     525         [ #  # ]:          0 :         if (diff < 0.0L) {
     526                 :          0 :                 diff *= -1.0L;
     527                 :            :         }
     528                 :            : 
     529                 :            :         /* Use the following metrics for picking bands for GC (in order):
     530                 :            :          * - relative invalidity
     531                 :            :          * - if invalidity is similar (within 10% points), then their write counts (how many times band was written to)
     532                 :            :          * - if write count is equal, then pick based on their placement on base device (lower LBAs win)
     533                 :            :          */
     534         [ #  # ]:          0 :         if (diff > 0.1L) {
     535                 :          0 :                 return a_invalidity > b_invalidity;
     536                 :            :         }
     537                 :            : 
     538         [ #  # ]:          0 :         if (a_wr_cnt != b_wr_cnt) {
     539                 :          0 :                 return a_wr_cnt < b_wr_cnt;
     540                 :            :         }
     541                 :            : 
     542                 :          0 :         return a_id < b_id;
     543                 :            : }
     544                 :            : 
     545                 :            : static void
     546                 :          0 : band_start_gc(struct spdk_ftl_dev *dev, struct ftl_band *band)
     547                 :            : {
     548         [ #  # ]:          0 :         ftl_bug(false == is_band_relocateable(band));
     549                 :            : 
     550         [ #  # ]:          0 :         TAILQ_REMOVE(&dev->shut_bands, band, queue_entry);
     551                 :          0 :         band->reloc = true;
     552                 :            : 
     553         [ #  # ]:          0 :         FTL_DEBUGLOG(dev, "Band to GC, id %u\n", band->id);
     554                 :          0 : }
     555                 :            : 
     556                 :            : static struct ftl_band *
     557                 :          0 : gc_high_priority_band(struct spdk_ftl_dev *dev)
     558                 :            : {
     559                 :            :         struct ftl_band *band;
     560                 :          0 :         uint64_t high_prio_id = dev->sb_shm->gc_info.band_id_high_prio;
     561                 :            : 
     562         [ #  # ]:          0 :         if (FTL_BAND_ID_INVALID != high_prio_id) {
     563         [ #  # ]:          0 :                 ftl_bug(high_prio_id >= dev->num_bands);
     564                 :            : 
     565                 :          0 :                 band = &dev->bands[high_prio_id];
     566                 :          0 :                 dev->sb_shm->gc_info.band_id_high_prio = FTL_BAND_ID_INVALID;
     567                 :            : 
     568                 :          0 :                 band_start_gc(dev, band);
     569         [ #  # ]:          0 :                 FTL_NOTICELOG(dev, "GC takes high priority band, id %u\n", band->id);
     570                 :          0 :                 return band;
     571                 :            :         }
     572                 :            : 
     573                 :          0 :         return 0;
     574                 :            : }
     575                 :            : 
     576                 :            : static void
     577                 :         10 : ftl_band_reset_gc_iter(struct spdk_ftl_dev *dev)
     578                 :            : {
     579                 :         10 :         dev->sb->gc_info.is_valid = 0;
     580                 :         10 :         dev->sb->gc_info.current_band_id = FTL_BAND_ID_INVALID;
     581                 :         10 :         dev->sb->gc_info.band_id_high_prio = FTL_BAND_ID_INVALID;
     582                 :         10 :         dev->sb->gc_info.band_phys_id = FTL_BAND_PHYS_ID_INVALID;
     583                 :            : 
     584                 :         10 :         dev->sb_shm->gc_info = dev->sb->gc_info;
     585                 :         10 : }
     586                 :            : 
     587                 :            : struct ftl_band *
     588                 :          0 : ftl_band_search_next_to_reloc(struct spdk_ftl_dev *dev)
     589                 :            : {
     590                 :          0 :         double invalidity, max_invalidity = 0.0L;
     591                 :          0 :         double wr_cnt, max_wr_cnt = 0.0L;
     592                 :          0 :         uint64_t phys_id = FTL_BAND_PHYS_ID_INVALID;
     593                 :            :         struct ftl_band *band;
     594                 :            :         uint64_t i, band_count;
     595                 :            :         uint64_t phys_count;
     596                 :            : 
     597                 :          0 :         band = gc_high_priority_band(dev);
     598         [ #  # ]:          0 :         if (spdk_unlikely(NULL != band)) {
     599                 :          0 :                 return band;
     600                 :            :         }
     601                 :            : 
     602                 :          0 :         phys_count = dev->num_logical_bands_in_physical;
     603                 :          0 :         band_count = ftl_get_num_bands(dev);
     604                 :            : 
     605         [ #  # ]:          0 :         for (; dev->sb_shm->gc_info.current_band_id < band_count;) {
     606                 :          0 :                 band = &dev->bands[dev->sb_shm->gc_info.current_band_id];
     607         [ #  # ]:          0 :                 if (band->phys_id != dev->sb_shm->gc_info.band_phys_id) {
     608                 :          0 :                         break;
     609                 :            :                 }
     610                 :            : 
     611         [ #  # ]:          0 :                 if (false == is_band_relocateable(band)) {
     612                 :          0 :                         dev->sb_shm->gc_info.current_band_id++;
     613                 :          0 :                         continue;
     614                 :            :                 }
     615                 :            : 
     616                 :          0 :                 band_start_gc(dev, band);
     617                 :          0 :                 return band;
     618                 :            :         }
     619                 :            : 
     620         [ #  # ]:          0 :         for (i = 0; i < band_count; i += phys_count) {
     621                 :          0 :                 band = &dev->bands[i];
     622                 :            : 
     623                 :            :                 /* Calculate entire band physical group invalidity */
     624                 :          0 :                 get_band_phys_info(dev, band->phys_id, &invalidity, &wr_cnt);
     625                 :            : 
     626         [ #  # ]:          0 :                 if (invalidity != 0.0L) {
     627   [ #  #  #  # ]:          0 :                         if (phys_id == FTL_BAND_PHYS_ID_INVALID ||
     628                 :          0 :                             band_cmp(invalidity, wr_cnt, max_invalidity, max_wr_cnt,
     629                 :          0 :                                      band->phys_id, phys_id)) {
     630                 :          0 :                                 max_wr_cnt = wr_cnt;
     631                 :          0 :                                 phys_id = band->phys_id;
     632                 :            : 
     633         [ #  # ]:          0 :                                 if (invalidity > max_invalidity) {
     634                 :          0 :                                         max_invalidity = invalidity;
     635                 :            :                                 }
     636                 :            :                         }
     637                 :            :                 }
     638                 :            :         }
     639                 :            : 
     640         [ #  # ]:          0 :         if (FTL_BAND_PHYS_ID_INVALID != phys_id) {
     641         [ #  # ]:          0 :                 FTL_DEBUGLOG(dev, "Band physical id %"PRIu64" to GC\n", phys_id);
     642                 :          0 :                 dev->sb_shm->gc_info.is_valid = 0;
     643                 :          0 :                 dev->sb_shm->gc_info.current_band_id = phys_id * phys_count;
     644                 :          0 :                 dev->sb_shm->gc_info.band_phys_id = phys_id;
     645                 :          0 :                 dev->sb_shm->gc_info.is_valid = 1;
     646                 :          0 :                 dump_bands_under_relocation(dev);
     647                 :          0 :                 return ftl_band_search_next_to_reloc(dev);
     648                 :            :         } else {
     649                 :          0 :                 ftl_band_reset_gc_iter(dev);
     650                 :            :         }
     651                 :            : 
     652                 :          0 :         return NULL;
     653                 :            : }
     654                 :            : 
     655                 :            : void
     656                 :         27 : ftl_band_init_gc_iter(struct spdk_ftl_dev *dev)
     657                 :            : {
     658         [ +  + ]:         27 :         if (dev->conf.mode & SPDK_FTL_MODE_CREATE) {
     659                 :         10 :                 ftl_band_reset_gc_iter(dev);
     660                 :         10 :                 return;
     661                 :            :         }
     662                 :            : 
     663         [ +  + ]:         17 :         if (dev->sb->clean) {
     664                 :         16 :                 dev->sb_shm->gc_info = dev->sb->gc_info;
     665                 :         16 :                 return;
     666                 :            :         }
     667                 :            : 
     668   [ +  -  +  - ]:          1 :         if (ftl_fast_startup(dev) || ftl_fast_recovery(dev)) {
     669                 :          1 :                 return;
     670                 :            :         }
     671                 :            : 
     672                 :            :         /* We lost GC state due to dirty shutdown, reset GC state to start over */
     673                 :          0 :         ftl_band_reset_gc_iter(dev);
     674                 :            : }
     675                 :            : 
     676                 :            : void
     677                 :         17 : ftl_valid_map_load_state(struct spdk_ftl_dev *dev)
     678                 :            : {
     679                 :            :         uint64_t i;
     680                 :            :         struct ftl_band *band;
     681                 :            : 
     682         [ +  + ]:       1635 :         for (i = 0; i < dev->num_bands; i++) {
     683                 :       1618 :                 band = &dev->bands[i];
     684                 :       1618 :                 band->p2l_map.num_valid = ftl_bitmap_count_set(band->p2l_map.valid);
     685                 :            :         }
     686                 :         17 : }
     687                 :            : 
     688                 :            : void
     689                 :       1611 : ftl_band_initialize_free_state(struct ftl_band *band)
     690                 :            : {
     691                 :            :         /* All bands start on the shut list during startup, removing it manually here */
     692         [ +  + ]:       1611 :         TAILQ_REMOVE(&band->dev->shut_bands, band, queue_entry);
     693                 :       1611 :         _ftl_band_set_free(band);
     694                 :       1611 : }
     695                 :            : 
     696                 :            : void
     697                 :         16 : ftl_bands_load_state(struct spdk_ftl_dev *dev)
     698                 :            : {
     699                 :            :         uint64_t i;
     700                 :            :         struct ftl_band *band;
     701                 :            : 
     702         [ +  + ]:       1616 :         for (i = 0; i < dev->num_bands; i++) {
     703                 :       1600 :                 band = &dev->bands[i];
     704                 :            : 
     705         [ +  + ]:       1600 :                 if (band->md->state == FTL_BAND_STATE_FREE) {
     706                 :       1596 :                         ftl_band_initialize_free_state(band);
     707                 :            :                 }
     708                 :            :         }
     709                 :         16 : }

Generated by: LCOV version 1.14