LCOV - code coverage report
Current view: top level - lib/ftl - ftl_band.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 90 342 26.3 %
Date: 2024-07-14 13:47:04 Functions: 13 43 30.2 %

          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           0 : ftl_band_tail_md_offset(const struct ftl_band *band)
      22             : {
      23           0 :         return ftl_get_num_blocks_in_band(band->dev) -
      24           0 :                ftl_tail_md_num_blocks(band->dev);
      25             : }
      26             : 
      27             : int
      28           0 : ftl_band_filled(struct ftl_band *band, size_t offset)
      29             : {
      30           0 :         return offset == ftl_band_tail_md_offset(band);
      31             : }
      32             : 
      33             : static void
      34           6 : ftl_band_free_p2l_map(struct ftl_band *band)
      35             : {
      36           6 :         struct spdk_ftl_dev *dev = band->dev;
      37           6 :         struct ftl_p2l_map *p2l_map = &band->p2l_map;
      38             : 
      39           6 :         assert(band->md->state == FTL_BAND_STATE_CLOSED ||
      40             :                band->md->state == FTL_BAND_STATE_FREE);
      41           6 :         assert(p2l_map->ref_cnt == 0);
      42           6 :         assert(p2l_map->band_map != NULL);
      43             : 
      44           6 :         band->md->df_p2l_map = FTL_DF_OBJ_ID_INVALID;
      45           6 :         ftl_mempool_put(dev->p2l_pool, p2l_map->band_map);
      46           6 :         p2l_map->band_map = NULL;
      47           6 : }
      48             : 
      49             : 
      50             : static void
      51           6 : ftl_band_free_md_entry(struct ftl_band *band)
      52             : {
      53           6 :         struct spdk_ftl_dev *dev = band->dev;
      54           6 :         struct ftl_p2l_map *p2l_map = &band->p2l_map;
      55             : 
      56           6 :         assert(band->md->state == FTL_BAND_STATE_CLOSED ||
      57             :                band->md->state == FTL_BAND_STATE_FREE);
      58           6 :         assert(p2l_map->band_dma_md != NULL);
      59             : 
      60           6 :         ftl_mempool_put(dev->band_md_pool, p2l_map->band_dma_md);
      61           6 :         p2l_map->band_dma_md = NULL;
      62           6 : }
      63             : 
      64             : static void
      65           0 : _ftl_band_set_free(struct ftl_band *band)
      66             : {
      67           0 :         struct spdk_ftl_dev *dev = band->dev;
      68             : 
      69             :         /* Add the band to the free band list */
      70           0 :         TAILQ_INSERT_TAIL(&dev->free_bands, band, queue_entry);
      71           0 :         band->md->close_seq_id = 0;
      72           0 :         band->reloc = false;
      73             : 
      74           0 :         dev->num_free++;
      75           0 :         ftl_apply_limits(dev);
      76             : 
      77           0 :         band->md->p2l_map_checksum = 0;
      78           0 : }
      79             : 
      80             : static void
      81           0 : _ftl_band_set_preparing(struct ftl_band *band)
      82             : {
      83           0 :         struct spdk_ftl_dev *dev = band->dev;
      84             : 
      85             :         /* Remove band from free list */
      86           0 :         TAILQ_REMOVE(&dev->free_bands, band, queue_entry);
      87             : 
      88           0 :         band->md->wr_cnt++;
      89             : 
      90           0 :         assert(dev->num_free > 0);
      91           0 :         dev->num_free--;
      92             : 
      93           0 :         ftl_apply_limits(dev);
      94           0 : }
      95             : 
      96             : static void
      97           0 : _ftl_band_set_closed_cb(struct ftl_band *band, bool valid)
      98             : {
      99           0 :         struct spdk_ftl_dev *dev = band->dev;
     100             : 
     101           0 :         assert(valid == true);
     102             : 
     103             :         /* Set the state as free_md() checks for that */
     104           0 :         band->md->state = FTL_BAND_STATE_CLOSED;
     105           0 :         if (band->owner.state_change_fn) {
     106           0 :                 band->owner.state_change_fn(band);
     107             :         }
     108             : 
     109           0 :         ftl_p2l_validate_ckpt(band);
     110             : 
     111             :         /* Free the P2L map if there are no outstanding IOs */
     112           0 :         ftl_band_release_p2l_map(band);
     113           0 :         assert(band->p2l_map.ref_cnt == 0);
     114             : 
     115           0 :         TAILQ_INSERT_TAIL(&dev->shut_bands, band, queue_entry);
     116           0 : }
     117             : 
     118             : static void
     119           0 : _ftl_band_set_closed(struct ftl_band *band)
     120             : {
     121             :         /* Verify that band's metadata is consistent with l2p */
     122           0 :         ftl_band_validate_md(band, _ftl_band_set_closed_cb);
     123           0 : }
     124             : 
     125             : ftl_addr
     126           0 : ftl_band_tail_md_addr(struct ftl_band *band)
     127             : {
     128             :         ftl_addr addr;
     129             : 
     130             :         /* Metadata should be aligned to xfer size */
     131           0 :         assert(ftl_band_tail_md_offset(band) % band->dev->xfer_size == 0);
     132             : 
     133           0 :         addr = ftl_band_tail_md_offset(band) + band->start_addr;
     134             : 
     135           0 :         return addr;
     136             : }
     137             : 
     138             : const char *
     139           0 : 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           0 :         assert(band->md->state < SPDK_COUNTOF(names));
     147           0 :         if (band->md->state < SPDK_COUNTOF(names)) {
     148           0 :                 return names[band->md->state];
     149             :         } else {
     150           0 :                 assert(false);
     151             :                 return "?";
     152             :         }
     153             : }
     154             : 
     155             : void
     156           0 : ftl_band_set_state(struct ftl_band *band, enum ftl_band_state state)
     157             : {
     158           0 :         switch (state) {
     159           0 :         case FTL_BAND_STATE_FREE:
     160           0 :                 assert(band->md->state == FTL_BAND_STATE_CLOSED);
     161           0 :                 _ftl_band_set_free(band);
     162           0 :                 break;
     163             : 
     164           0 :         case FTL_BAND_STATE_PREP:
     165           0 :                 assert(band->md->state == FTL_BAND_STATE_FREE);
     166           0 :                 _ftl_band_set_preparing(band);
     167           0 :                 break;
     168             : 
     169           0 :         case FTL_BAND_STATE_CLOSED:
     170           0 :                 if (band->md->state != FTL_BAND_STATE_CLOSED) {
     171           0 :                         assert(band->md->state == FTL_BAND_STATE_CLOSING);
     172           0 :                         _ftl_band_set_closed(band);
     173           0 :                         return; /* state can be changed asynchronously */
     174             :                 }
     175           0 :                 break;
     176             : 
     177           0 :         case FTL_BAND_STATE_OPEN:
     178           0 :                 band->md->p2l_map_checksum = 0;
     179           0 :                 break;
     180           0 :         case FTL_BAND_STATE_OPENING:
     181             :         case FTL_BAND_STATE_FULL:
     182             :         case FTL_BAND_STATE_CLOSING:
     183           0 :                 break;
     184           0 :         default:
     185           0 :                 FTL_ERRLOG(band->dev, "Unknown band state, %u", state);
     186           0 :                 assert(false);
     187             :                 break;
     188             :         }
     189             : 
     190           0 :         band->md->state = state;
     191             : }
     192             : 
     193             : void
     194           0 : ftl_band_set_type(struct ftl_band *band, enum ftl_band_type type)
     195             : {
     196           0 :         switch (type) {
     197           0 :         case FTL_BAND_TYPE_COMPACTION:
     198             :         case FTL_BAND_TYPE_GC:
     199           0 :                 band->md->type = type;
     200           0 :                 break;
     201           0 :         default:
     202           0 :                 assert(false);
     203             :                 break;
     204             :         }
     205           0 : }
     206             : 
     207             : void
     208           5 : ftl_band_set_p2l(struct ftl_band *band, uint64_t lba, ftl_addr addr, uint64_t seq_id)
     209             : {
     210           5 :         struct ftl_p2l_map *p2l_map = &band->p2l_map;
     211             :         uint64_t offset;
     212             : 
     213           5 :         offset = ftl_band_block_offset_from_addr(band, addr);
     214             : 
     215           5 :         p2l_map->band_map[offset].lba = lba;
     216           5 :         p2l_map->band_map[offset].seq_id = seq_id;
     217           5 : }
     218             : 
     219             : void
     220           5 : ftl_band_set_addr(struct ftl_band *band, uint64_t lba, ftl_addr addr)
     221             : {
     222           5 :         band->p2l_map.num_valid++;
     223           5 :         ftl_bitmap_set(band->dev->valid_map, addr);
     224           5 : }
     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           0 : ftl_band_user_blocks(const struct ftl_band *band)
     240             : {
     241           0 :         return ftl_get_num_blocks_in_band(band->dev) -
     242           0 :                ftl_tail_md_num_blocks(band->dev);
     243             : }
     244             : 
     245             : static inline uint64_t
     246       30026 : ftl_addr_get_band(const struct spdk_ftl_dev *dev, ftl_addr addr)
     247             : {
     248       30026 :         return (addr - dev->bands->start_addr) / ftl_get_num_blocks_in_band(dev);
     249             : }
     250             : 
     251             : struct ftl_band *
     252           2 : ftl_band_from_addr(struct spdk_ftl_dev *dev, ftl_addr addr)
     253             : {
     254           2 :         uint64_t band_id = ftl_addr_get_band(dev, addr);
     255             : 
     256           2 :         assert(band_id < ftl_get_num_bands(dev));
     257           2 :         return &dev->bands[band_id];
     258             : }
     259             : 
     260             : uint64_t
     261       20006 : ftl_band_block_offset_from_addr(struct ftl_band *band, ftl_addr addr)
     262             : {
     263       20006 :         assert(ftl_addr_get_band(band->dev, addr) == band->id);
     264       20006 :         return addr - band->start_addr;
     265             : }
     266             : 
     267             : ftl_addr
     268           3 : ftl_band_next_xfer_addr(struct ftl_band *band, ftl_addr addr, size_t num_blocks)
     269             : {
     270           3 :         struct spdk_ftl_dev *dev = band->dev;
     271             :         size_t num_xfers;
     272             :         uint64_t offset;
     273             : 
     274           3 :         assert(ftl_addr_get_band(dev, addr) == band->id);
     275             : 
     276           3 :         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           3 :         num_blocks += (offset % dev->xfer_size);
     282           3 :         offset -= (offset % dev->xfer_size);
     283             : 
     284             :         /* Calculate offset based on xfer_size aligned writes */
     285           3 :         num_xfers = (num_blocks / dev->xfer_size);
     286           3 :         offset += num_xfers * dev->xfer_size;
     287           3 :         num_blocks -= num_xfers * dev->xfer_size;
     288             : 
     289           3 :         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           3 :         if (num_blocks) {
     296           2 :                 offset += num_blocks;
     297           2 :                 if (offset > ftl_get_num_blocks_in_band(dev)) {
     298           0 :                         return FTL_ADDR_INVALID;
     299             :                 }
     300             :         }
     301             : 
     302           3 :         addr = band->start_addr + offset;
     303           3 :         return addr;
     304             : }
     305             : 
     306             : ftl_addr
     307       10000 : ftl_band_addr_from_block_offset(struct ftl_band *band, uint64_t block_off)
     308             : {
     309             :         ftl_addr addr;
     310             : 
     311       10000 :         addr = block_off + band->start_addr;
     312       10000 :         return addr;
     313             : }
     314             : 
     315             : ftl_addr
     316           0 : ftl_band_next_addr(struct ftl_band *band, ftl_addr addr, size_t offset)
     317             : {
     318           0 :         uint64_t block_off = ftl_band_block_offset_from_addr(band, addr);
     319             : 
     320           0 :         return ftl_band_addr_from_block_offset(band, block_off + offset);
     321             : }
     322             : 
     323             : void
     324           6 : ftl_band_acquire_p2l_map(struct ftl_band *band)
     325             : {
     326           6 :         assert(band->p2l_map.band_map != NULL);
     327           6 :         band->p2l_map.ref_cnt++;
     328           6 : }
     329             : 
     330             : static int
     331           6 : ftl_band_alloc_md_entry(struct ftl_band *band)
     332             : {
     333           6 :         struct spdk_ftl_dev *dev = band->dev;
     334           6 :         struct ftl_p2l_map *p2l_map = &band->p2l_map;
     335           6 :         struct ftl_layout_region *region = ftl_layout_region_get(dev, FTL_LAYOUT_REGION_TYPE_BAND_MD);
     336             : 
     337           6 :         p2l_map->band_dma_md = ftl_mempool_get(dev->band_md_pool);
     338             : 
     339           6 :         if (!p2l_map->band_dma_md) {
     340           0 :                 return -1;
     341             :         }
     342             : 
     343           6 :         memset(p2l_map->band_dma_md, 0, region->entry_size * FTL_BLOCK_SIZE);
     344           6 :         return 0;
     345             : }
     346             : 
     347             : int
     348           6 : ftl_band_alloc_p2l_map(struct ftl_band *band)
     349             : {
     350           6 :         struct spdk_ftl_dev *dev = band->dev;
     351           6 :         struct ftl_p2l_map *p2l_map = &band->p2l_map;
     352             : 
     353           6 :         assert(p2l_map->ref_cnt == 0);
     354           6 :         assert(p2l_map->band_map == NULL);
     355             : 
     356           6 :         assert(band->md->df_p2l_map == FTL_DF_OBJ_ID_INVALID);
     357           6 :         p2l_map->band_map = ftl_mempool_get(dev->p2l_pool);
     358           6 :         if (!p2l_map->band_map) {
     359           0 :                 return -1;
     360             :         }
     361             : 
     362           6 :         if (ftl_band_alloc_md_entry(band)) {
     363           0 :                 ftl_band_free_p2l_map(band);
     364           0 :                 return -1;
     365             :         }
     366             : 
     367           6 :         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           6 :         memset(p2l_map->band_map, -1, FTL_BLOCK_SIZE * ftl_p2l_map_num_blocks(band->dev));
     371             : 
     372           6 :         ftl_band_acquire_p2l_map(band);
     373           6 :         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           6 : ftl_band_release_p2l_map(struct ftl_band *band)
     400             : {
     401           6 :         struct ftl_p2l_map *p2l_map = &band->p2l_map;
     402             : 
     403           6 :         assert(p2l_map->band_map != NULL);
     404           6 :         assert(p2l_map->ref_cnt > 0);
     405           6 :         p2l_map->ref_cnt--;
     406             : 
     407           6 :         if (p2l_map->ref_cnt == 0) {
     408           6 :                 if (p2l_map->p2l_ckpt) {
     409           0 :                         ftl_p2l_ckpt_release(band->dev, p2l_map->p2l_ckpt);
     410           0 :                         p2l_map->p2l_ckpt = NULL;
     411             :                 }
     412           6 :                 ftl_band_free_p2l_map(band);
     413           6 :                 ftl_band_free_md_entry(band);
     414             :         }
     415           6 : }
     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           0 : ftl_band_write_prep(struct ftl_band *band)
     425             : {
     426           0 :         struct spdk_ftl_dev *dev = band->dev;
     427             : 
     428           0 :         if (ftl_band_alloc_p2l_map(band)) {
     429           0 :                 return -1;
     430             :         }
     431             : 
     432           0 :         band->p2l_map.p2l_ckpt = ftl_p2l_ckpt_acquire(dev);
     433           0 :         band->md->p2l_md_region = ftl_p2l_ckpt_region_type(band->p2l_map.p2l_ckpt);
     434           0 :         ftl_band_iter_init(band);
     435             : 
     436           0 :         band->md->seq = ftl_get_next_seq_id(dev);
     437             : 
     438           0 :         FTL_DEBUGLOG(dev, "Band to write, id %u seq %"PRIu64"\n", band->id, band->md->seq);
     439           0 :         return 0;
     440             : }
     441             : 
     442             : size_t
     443           0 : ftl_p2l_map_pool_elem_size(struct spdk_ftl_dev *dev)
     444             : {
     445             :         /* Map pool element holds the whole tail md */
     446           0 :         return ftl_tail_md_num_blocks(dev) * FTL_BLOCK_SIZE;
     447             : }
     448             : 
     449             : double
     450           0 : ftl_band_invalidity(struct ftl_band *band)
     451             : {
     452           0 :         double valid = band->p2l_map.num_valid;
     453           0 :         double count = ftl_band_user_blocks(band);
     454             : 
     455           0 :         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           0 : ftl_band_reset_gc_iter(struct spdk_ftl_dev *dev)
     578             : {
     579           0 :         dev->sb->gc_info.is_valid = 0;
     580           0 :         dev->sb->gc_info.current_band_id = FTL_BAND_ID_INVALID;
     581           0 :         dev->sb->gc_info.band_id_high_prio = FTL_BAND_ID_INVALID;
     582           0 :         dev->sb->gc_info.band_phys_id = FTL_BAND_PHYS_ID_INVALID;
     583             : 
     584           0 :         dev->sb_shm->gc_info = dev->sb->gc_info;
     585           0 : }
     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           0 : ftl_band_init_gc_iter(struct spdk_ftl_dev *dev)
     657             : {
     658           0 :         if (dev->conf.mode & SPDK_FTL_MODE_CREATE) {
     659           0 :                 ftl_band_reset_gc_iter(dev);
     660           0 :                 return;
     661             :         }
     662             : 
     663           0 :         if (dev->sb->clean) {
     664           0 :                 dev->sb_shm->gc_info = dev->sb->gc_info;
     665           0 :                 return;
     666             :         }
     667             : 
     668           0 :         if (ftl_fast_startup(dev) || ftl_fast_recovery(dev)) {
     669           0 :                 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           0 : ftl_valid_map_load_state(struct spdk_ftl_dev *dev)
     678             : {
     679             :         uint64_t i;
     680             :         struct ftl_band *band;
     681             : 
     682           0 :         for (i = 0; i < dev->num_bands; i++) {
     683           0 :                 band = &dev->bands[i];
     684           0 :                 band->p2l_map.num_valid = ftl_bitmap_count_set(band->p2l_map.valid);
     685             :         }
     686           0 : }
     687             : 
     688             : void
     689           0 : 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           0 :         TAILQ_REMOVE(&band->dev->shut_bands, band, queue_entry);
     693           0 :         _ftl_band_set_free(band);
     694           0 : }
     695             : 
     696             : void
     697           0 : ftl_bands_load_state(struct spdk_ftl_dev *dev)
     698             : {
     699             :         uint64_t i;
     700             :         struct ftl_band *band;
     701             : 
     702           0 :         for (i = 0; i < dev->num_bands; i++) {
     703           0 :                 band = &dev->bands[i];
     704             : 
     705           0 :                 if (band->md->state == FTL_BAND_STATE_FREE) {
     706           0 :                         ftl_band_initialize_free_state(band);
     707             :                 }
     708             :         }
     709           0 : }

Generated by: LCOV version 1.15