LCOV - code coverage report
Current view: top level - lib/ftl - ftl_p2l.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 0 249 0.0 %
Date: 2024-07-11 21:30:05 Functions: 0 20 0.0 %

          Line data    Source code
       1             : /*   SPDX-License-Identifier: BSD-3-Clause
       2             :  *   Copyright (C) 2022 Intel Corporation.
       3             :  *   All rights reserved.
       4             :  */
       5             : 
       6             : #include "spdk/bdev_module.h"
       7             : #include "spdk/crc32.h"
       8             : 
       9             : #include "ftl_internal.h"
      10             : #include "ftl_band.h"
      11             : #include "ftl_core.h"
      12             : #include "ftl_layout.h"
      13             : #include "ftl_nv_cache_io.h"
      14             : #include "ftl_writer.h"
      15             : #include "mngt/ftl_mngt.h"
      16             : 
      17             : struct ftl_p2l_ckpt {
      18             :         TAILQ_ENTRY(ftl_p2l_ckpt)       link;
      19             :         union ftl_md_vss                *vss_md_page;
      20             :         struct ftl_md                   *md;
      21             :         struct ftl_layout_region        *layout_region;
      22             :         uint64_t                        num_pages;
      23             : 
      24             : #if defined(DEBUG)
      25             :         uint64_t                        dbg_bmp_sz;
      26             :         void                            *dbg_bmp;
      27             :         struct ftl_bitmap               *bmp;
      28             : #endif
      29             : };
      30             : 
      31             : static struct ftl_p2l_ckpt *
      32           0 : ftl_p2l_ckpt_new(struct spdk_ftl_dev *dev, int region_type)
      33             : {
      34             :         struct ftl_p2l_ckpt *ckpt;
      35           0 :         struct ftl_layout_region *region = ftl_layout_region_get(dev, region_type);
      36             : 
      37           0 :         ckpt = calloc(1, sizeof(struct ftl_p2l_ckpt));
      38           0 :         if (!ckpt) {
      39           0 :                 return NULL;
      40             :         }
      41             : 
      42           0 :         ckpt->vss_md_page = ftl_md_vss_buf_alloc(region, region->num_entries);
      43           0 :         ckpt->layout_region = region;
      44           0 :         ckpt->md = dev->layout.md[region_type];
      45           0 :         ckpt->num_pages = spdk_divide_round_up(ftl_get_num_blocks_in_band(dev), FTL_NUM_LBA_IN_BLOCK);
      46             : 
      47           0 :         if (!ckpt->vss_md_page) {
      48           0 :                 free(ckpt);
      49           0 :                 return NULL;
      50             :         }
      51             : 
      52             : #if defined(DEBUG)
      53             :         /* The bitmap size must be a multiple of word size (8b) - round up */
      54           0 :         ckpt->dbg_bmp_sz = spdk_divide_round_up(ckpt->num_pages, 8);
      55             : 
      56           0 :         ckpt->dbg_bmp = calloc(1, ckpt->dbg_bmp_sz);
      57           0 :         assert(ckpt->dbg_bmp);
      58           0 :         ckpt->bmp = ftl_bitmap_create(ckpt->dbg_bmp, ckpt->dbg_bmp_sz);
      59           0 :         assert(ckpt->bmp);
      60             : #endif
      61             : 
      62           0 :         return ckpt;
      63             : }
      64             : 
      65             : static void
      66           0 : ftl_p2l_ckpt_destroy(struct ftl_p2l_ckpt *ckpt)
      67             : {
      68             : #if defined(DEBUG)
      69           0 :         ftl_bitmap_destroy(ckpt->bmp);
      70           0 :         free(ckpt->dbg_bmp);
      71             : #endif
      72           0 :         spdk_dma_free(ckpt->vss_md_page);
      73           0 :         free(ckpt);
      74           0 : }
      75             : 
      76             : int
      77           0 : ftl_p2l_ckpt_init(struct spdk_ftl_dev *dev)
      78             : {
      79             :         int region_type;
      80             :         struct ftl_p2l_ckpt *ckpt;
      81             : 
      82           0 :         TAILQ_INIT(&dev->p2l_ckpt.free);
      83           0 :         TAILQ_INIT(&dev->p2l_ckpt.inuse);
      84           0 :         for (region_type = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN;
      85             :              region_type <= FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MAX;
      86           0 :              region_type++) {
      87           0 :                 ckpt = ftl_p2l_ckpt_new(dev, region_type);
      88           0 :                 if (!ckpt) {
      89           0 :                         return -1;
      90             :                 }
      91           0 :                 TAILQ_INSERT_TAIL(&dev->p2l_ckpt.free, ckpt, link);
      92             :         }
      93           0 :         return 0;
      94             : }
      95             : 
      96             : void
      97           0 : ftl_p2l_ckpt_deinit(struct spdk_ftl_dev *dev)
      98             : {
      99             :         struct ftl_p2l_ckpt *ckpt, *ckpt_next;
     100             : 
     101           0 :         TAILQ_FOREACH_SAFE(ckpt, &dev->p2l_ckpt.free, link, ckpt_next) {
     102           0 :                 TAILQ_REMOVE(&dev->p2l_ckpt.free, ckpt, link);
     103           0 :                 ftl_p2l_ckpt_destroy(ckpt);
     104             :         }
     105             : 
     106           0 :         TAILQ_FOREACH_SAFE(ckpt, &dev->p2l_ckpt.inuse, link, ckpt_next) {
     107           0 :                 TAILQ_REMOVE(&dev->p2l_ckpt.inuse, ckpt, link);
     108           0 :                 ftl_p2l_ckpt_destroy(ckpt);
     109             :         }
     110           0 : }
     111             : 
     112             : struct ftl_p2l_ckpt *
     113           0 : ftl_p2l_ckpt_acquire(struct spdk_ftl_dev *dev)
     114             : {
     115             :         struct ftl_p2l_ckpt *ckpt;
     116             : 
     117           0 :         ckpt = TAILQ_FIRST(&dev->p2l_ckpt.free);
     118           0 :         assert(ckpt);
     119           0 :         TAILQ_REMOVE(&dev->p2l_ckpt.free, ckpt, link);
     120           0 :         TAILQ_INSERT_TAIL(&dev->p2l_ckpt.inuse, ckpt, link);
     121           0 :         return ckpt;
     122             : }
     123             : 
     124             : void
     125           0 : ftl_p2l_ckpt_release(struct spdk_ftl_dev *dev, struct ftl_p2l_ckpt *ckpt)
     126             : {
     127           0 :         assert(ckpt);
     128             : #if defined(DEBUG)
     129           0 :         memset(ckpt->dbg_bmp, 0, ckpt->dbg_bmp_sz);
     130             : #endif
     131           0 :         TAILQ_REMOVE(&dev->p2l_ckpt.inuse, ckpt, link);
     132           0 :         TAILQ_INSERT_TAIL(&dev->p2l_ckpt.free, ckpt, link);
     133           0 : }
     134             : 
     135             : static void
     136           0 : ftl_p2l_ckpt_issue_end(int status, void *arg)
     137             : {
     138           0 :         struct ftl_rq *rq = arg;
     139           0 :         assert(rq);
     140             : 
     141           0 :         if (status) {
     142             : #ifdef SPDK_FTL_RETRY_ON_ERROR
     143             :                 /* retry */
     144             :                 ftl_md_persist_entry_retry(&rq->md_persist_entry_ctx);
     145             :                 return;
     146             : #else
     147           0 :                 ftl_abort();
     148             : #endif
     149             :         }
     150             : 
     151           0 :         assert(rq->io.band->queue_depth > 0);
     152           0 :         rq->io.band->queue_depth--;
     153             : 
     154           0 :         rq->owner.cb(rq);
     155           0 : }
     156             : 
     157             : void
     158           0 : ftl_p2l_ckpt_issue(struct ftl_rq *rq)
     159             : {
     160           0 :         struct ftl_rq_entry *iter = rq->entries;
     161           0 :         ftl_addr addr = rq->io.addr;
     162           0 :         struct ftl_p2l_ckpt *ckpt = NULL;
     163             :         struct ftl_p2l_ckpt_page *map_page;
     164             :         union ftl_md_vss *md_page;
     165             :         struct ftl_band *band;
     166             :         uint64_t band_offs, p2l_map_page_no, i;
     167             : 
     168           0 :         assert(rq);
     169           0 :         band = rq->io.band;
     170           0 :         ckpt = band->p2l_map.p2l_ckpt;
     171           0 :         assert(ckpt);
     172             : 
     173             :         /* Derive the P2L map page no */
     174           0 :         band_offs =  ftl_band_block_offset_from_addr(band, rq->io.addr);
     175           0 :         p2l_map_page_no = band_offs / FTL_NUM_LBA_IN_BLOCK;
     176           0 :         assert((band_offs + rq->num_blocks - 1) / FTL_NUM_LBA_IN_BLOCK == p2l_map_page_no);
     177           0 :         assert(p2l_map_page_no < ckpt->num_pages);
     178             : 
     179             :         /* Get the corresponding P2L map page - the underlying stored data is the same as in the end metadata of band P2L (ftl_p2l_map_entry),
     180             :          * however we're interested in a whole page (4KiB) worth of content
     181             :          */
     182           0 :         map_page = ((struct ftl_p2l_ckpt_page *)band->p2l_map.band_map) + p2l_map_page_no;
     183           0 :         assert(map_page);
     184             : 
     185             :         /* Set up the md */
     186           0 :         md_page = &ckpt->vss_md_page[p2l_map_page_no];
     187           0 :         md_page->p2l_ckpt.seq_id = band->md->seq;
     188           0 :         assert(rq->num_blocks == FTL_NUM_LBA_IN_BLOCK);
     189             : 
     190             :         /* Update the band P2L map */
     191           0 :         for (i = 0; i < rq->num_blocks; i++, iter++) {
     192           0 :                 if (iter->lba != FTL_LBA_INVALID) {
     193             :                         /* This is compaction or reloc */
     194           0 :                         assert(!ftl_addr_in_nvc(rq->dev, addr));
     195           0 :                         ftl_band_set_p2l(band, iter->lba, addr, iter->seq_id);
     196             :                 }
     197           0 :                 addr = ftl_band_next_addr(band, addr, 1);
     198             :         }
     199             : 
     200             : #if defined(DEBUG)
     201           0 :         ftl_bitmap_set(ckpt->bmp, p2l_map_page_no);
     202             : #endif
     203             : 
     204           0 :         md_page->p2l_ckpt.p2l_checksum = spdk_crc32c_update(map_page,
     205           0 :                                          rq->num_blocks * sizeof(struct ftl_p2l_map_entry), 0);
     206             :         /* Save the P2L map entry */
     207           0 :         ftl_md_persist_entry(ckpt->md, p2l_map_page_no, map_page, md_page, ftl_p2l_ckpt_issue_end,
     208             :                              rq, &rq->md_persist_entry_ctx);
     209           0 : }
     210             : 
     211             : #if defined(DEBUG)
     212             : static void
     213           0 : ftl_p2l_validate_pages(struct ftl_band *band, struct ftl_p2l_ckpt *ckpt,
     214             :                        uint64_t page_begin, uint64_t page_end, bool val)
     215             : {
     216             :         uint64_t page_no;
     217             : 
     218           0 :         for (page_no = page_begin; page_no < page_end; page_no++) {
     219           0 :                 assert(ftl_bitmap_get(ckpt->bmp, page_no) == val);
     220             :         }
     221           0 : }
     222             : 
     223             : void
     224           0 : ftl_p2l_validate_ckpt(struct ftl_band *band)
     225             : {
     226           0 :         struct ftl_p2l_ckpt *ckpt = band->p2l_map.p2l_ckpt;
     227           0 :         uint64_t num_blks_tail_md = ftl_tail_md_num_blocks(band->dev);
     228           0 :         uint64_t num_pages_tail_md = num_blks_tail_md / FTL_NUM_LBA_IN_BLOCK;
     229             : 
     230           0 :         if (!ckpt) {
     231           0 :                 return;
     232             :         }
     233             : 
     234           0 :         assert(num_blks_tail_md % FTL_NUM_LBA_IN_BLOCK == 0);
     235             : 
     236             :         /* all data pages written */
     237           0 :         ftl_p2l_validate_pages(band, ckpt,
     238           0 :                                0, ckpt->num_pages - num_pages_tail_md, true);
     239             : 
     240             :         /* tail md pages not written */
     241           0 :         ftl_p2l_validate_pages(band, ckpt, ckpt->num_pages - num_pages_tail_md,
     242             :                                ckpt->num_pages, false);
     243             : }
     244             : #endif
     245             : 
     246             : static struct ftl_band *
     247           0 : ftl_get_band_from_region(struct spdk_ftl_dev *dev, enum ftl_layout_region_type type)
     248             : {
     249           0 :         struct ftl_band *band = NULL;
     250             :         uint64_t i;
     251             : 
     252           0 :         assert(type >= FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN);
     253           0 :         assert(type <= FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MAX);
     254             : 
     255           0 :         for (i = 0; i < ftl_get_num_bands(dev); i++) {
     256           0 :                 band = &dev->bands[i];
     257           0 :                 if ((band->md->state == FTL_BAND_STATE_OPEN ||
     258           0 :                      band->md->state == FTL_BAND_STATE_FULL) &&
     259           0 :                     band->md->p2l_md_region == type) {
     260           0 :                         return band;
     261             :                 }
     262             :         }
     263             : 
     264           0 :         return NULL;
     265             : }
     266             : 
     267             : static void ftl_mngt_persist_band_p2l(struct ftl_mngt_process *mngt, struct ftl_p2l_sync_ctx *ctx);
     268             : 
     269             : static void
     270           0 : ftl_p2l_ckpt_persist_end(int status, void *arg)
     271             : {
     272           0 :         struct ftl_mngt_process *mngt = arg;
     273             :         struct ftl_p2l_sync_ctx *ctx;
     274             : 
     275           0 :         assert(mngt);
     276             : 
     277           0 :         if (status) {
     278           0 :                 ftl_mngt_fail_step(mngt);
     279           0 :                 return;
     280             :         }
     281             : 
     282           0 :         ctx = ftl_mngt_get_step_ctx(mngt);
     283           0 :         ctx->page_start++;
     284             : 
     285           0 :         if (ctx->page_start == ctx->page_end) {
     286           0 :                 ctx->md_region++;
     287           0 :                 ftl_mngt_continue_step(mngt);
     288             :         } else {
     289           0 :                 ftl_mngt_persist_band_p2l(mngt, ctx);
     290             :         }
     291             : }
     292             : 
     293             : static void
     294           0 : ftl_mngt_persist_band_p2l(struct ftl_mngt_process *mngt, struct ftl_p2l_sync_ctx *ctx)
     295             : {
     296           0 :         struct ftl_band *band = ctx->band;
     297             :         union ftl_md_vss *md_page;
     298             :         struct ftl_p2l_ckpt_page *map_page;
     299             :         struct ftl_p2l_ckpt *ckpt;
     300             : 
     301           0 :         ckpt = band->p2l_map.p2l_ckpt;
     302             : 
     303           0 :         map_page = ((struct ftl_p2l_ckpt_page *)band->p2l_map.band_map) + ctx->page_start;
     304             : 
     305           0 :         md_page = &ckpt->vss_md_page[ctx->page_start];
     306           0 :         md_page->p2l_ckpt.seq_id = band->md->seq;
     307           0 :         md_page->p2l_ckpt.p2l_checksum = spdk_crc32c_update(map_page,
     308             :                                          FTL_NUM_LBA_IN_BLOCK * sizeof(struct ftl_p2l_map_entry), 0);
     309             : 
     310             :         /* Save the P2L map entry */
     311           0 :         ftl_md_persist_entry(ckpt->md, ctx->page_start, map_page, md_page,
     312             :                              ftl_p2l_ckpt_persist_end, mngt, &band->md_persist_entry_ctx);
     313           0 : }
     314             : 
     315             : void
     316           0 : ftl_mngt_persist_bands_p2l(struct ftl_mngt_process *mngt)
     317             : {
     318           0 :         struct ftl_p2l_sync_ctx *ctx = ftl_mngt_get_step_ctx(mngt);
     319             :         struct ftl_band *band;
     320             :         uint64_t band_offs, p2l_map_page_no;
     321             : 
     322           0 :         if (ctx->md_region > FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MAX) {
     323           0 :                 ftl_mngt_next_step(mngt);
     324           0 :                 return;
     325             :         }
     326             : 
     327           0 :         band = ftl_get_band_from_region(ftl_mngt_get_dev(mngt), ctx->md_region);
     328             : 
     329             :         /* No band has the md region assigned (shutdown happened before next_band was assigned) */
     330           0 :         if (!band) {
     331           0 :                 ctx->page_start = 0;
     332           0 :                 ctx->page_end = 0;
     333           0 :                 ctx->md_region++;
     334           0 :                 ftl_mngt_continue_step(mngt);
     335           0 :                 return;
     336             :         }
     337             : 
     338           0 :         band_offs = ftl_band_block_offset_from_addr(band, band->md->iter.addr);
     339           0 :         p2l_map_page_no = band_offs / FTL_NUM_LBA_IN_BLOCK;
     340             : 
     341           0 :         ctx->page_start = 0;
     342           0 :         ctx->page_end = p2l_map_page_no;
     343           0 :         ctx->band = band;
     344             : 
     345             :         /* Band wasn't written to - no need to sync its P2L */
     346           0 :         if (ctx->page_end == 0) {
     347           0 :                 ctx->md_region++;
     348           0 :                 ftl_mngt_continue_step(mngt);
     349           0 :                 return;
     350             :         }
     351             : 
     352           0 :         ftl_mngt_persist_band_p2l(mngt, ctx);
     353             : }
     354             : 
     355             : uint64_t
     356           0 : ftl_mngt_p2l_ckpt_get_seq_id(struct spdk_ftl_dev *dev, int md_region)
     357             : {
     358           0 :         struct ftl_layout *layout = &dev->layout;
     359           0 :         struct ftl_md *md = layout->md[md_region];
     360           0 :         union ftl_md_vss *page_md_buf = ftl_md_get_vss_buffer(md);
     361           0 :         uint64_t page_no, seq_id = 0;
     362             : 
     363           0 :         for (page_no = 0; page_no < layout->p2l.ckpt_pages; page_no++, page_md_buf++) {
     364           0 :                 if (seq_id < page_md_buf->p2l_ckpt.seq_id) {
     365           0 :                         seq_id = page_md_buf->p2l_ckpt.seq_id;
     366             :                 }
     367             :         }
     368           0 :         return seq_id;
     369             : }
     370             : 
     371             : int
     372           0 : ftl_mngt_p2l_ckpt_restore(struct ftl_band *band, uint32_t md_region, uint64_t seq_id)
     373             : {
     374           0 :         struct ftl_layout *layout = &band->dev->layout;
     375           0 :         struct ftl_md *md = layout->md[md_region];
     376           0 :         union ftl_md_vss *page_md_buf = ftl_md_get_vss_buffer(md);
     377           0 :         struct ftl_p2l_ckpt_page *page = ftl_md_get_buffer(md);
     378             :         struct ftl_p2l_ckpt_page *map_page;
     379           0 :         uint64_t page_no, page_max = 0;
     380           0 :         bool page_found = false;
     381             : 
     382           0 :         assert(band->md->p2l_md_region == md_region);
     383           0 :         if (band->md->p2l_md_region != md_region) {
     384           0 :                 return -EINVAL;
     385             :         }
     386             : 
     387           0 :         assert(band->md->seq == seq_id);
     388           0 :         if (band->md->seq != seq_id) {
     389           0 :                 return -EINVAL;
     390             :         }
     391             : 
     392           0 :         for (page_no = 0; page_no < layout->p2l.ckpt_pages; page_no++, page++, page_md_buf++) {
     393           0 :                 if (page_md_buf->p2l_ckpt.seq_id != seq_id) {
     394           0 :                         continue;
     395             :                 }
     396             : 
     397           0 :                 page_max = page_no;
     398           0 :                 page_found = true;
     399             : 
     400             :                 /* Get the corresponding P2L map page - the underlying stored data is the same as in the end metadata of band P2L (ftl_p2l_map_entry),
     401             :                  * however we're interested in a whole page (4KiB) worth of content
     402             :                  */
     403           0 :                 map_page = ((struct ftl_p2l_ckpt_page *)band->p2l_map.band_map) + page_no;
     404             : 
     405           0 :                 if (page_md_buf->p2l_ckpt.p2l_checksum &&
     406           0 :                     page_md_buf->p2l_ckpt.p2l_checksum != spdk_crc32c_update(page,
     407             :                                     FTL_NUM_LBA_IN_BLOCK * sizeof(struct ftl_p2l_map_entry), 0)) {
     408           0 :                         ftl_stats_crc_error(band->dev, FTL_STATS_TYPE_MD_NV_CACHE);
     409           0 :                         return -EINVAL;
     410             :                 }
     411             : 
     412             :                 /* Restore the page from P2L checkpoint */
     413           0 :                 *map_page = *page;
     414             :         }
     415             : 
     416           0 :         assert(page_found);
     417           0 :         if (!page_found) {
     418           0 :                 return -EINVAL;
     419             :         }
     420             : 
     421             :         /* Restore check point in band P2L map */
     422           0 :         band->p2l_map.p2l_ckpt = ftl_p2l_ckpt_acquire_region_type(
     423             :                                          band->dev, md_region);
     424             : 
     425             : #ifdef DEBUG
     426             :         /* Set check point valid map for validation */
     427           0 :         struct ftl_p2l_ckpt *ckpt = band->p2l_map.p2l_ckpt ;
     428           0 :         for (uint64_t i = 0; i <= page_max; i++) {
     429           0 :                 ftl_bitmap_set(ckpt->bmp, i);
     430             :         }
     431             : #endif
     432             : 
     433           0 :         ftl_band_iter_init(band);
     434           0 :         ftl_band_iter_set(band, (page_max + 1) * FTL_NUM_LBA_IN_BLOCK);
     435             : 
     436           0 :         return 0;
     437             : }
     438             : 
     439             : enum ftl_layout_region_type
     440           0 : ftl_p2l_ckpt_region_type(const struct ftl_p2l_ckpt *ckpt) {
     441           0 :         return ckpt->layout_region->type;
     442             : }
     443             : 
     444             : struct ftl_p2l_ckpt *
     445           0 : ftl_p2l_ckpt_acquire_region_type(struct spdk_ftl_dev *dev, uint32_t region_type)
     446             : {
     447           0 :         struct ftl_p2l_ckpt *ckpt = NULL;
     448             : 
     449           0 :         TAILQ_FOREACH(ckpt, &dev->p2l_ckpt.free, link) {
     450           0 :                 if (ckpt->layout_region->type == region_type) {
     451           0 :                         break;
     452             :                 }
     453             :         }
     454             : 
     455           0 :         assert(ckpt);
     456             : 
     457           0 :         TAILQ_REMOVE(&dev->p2l_ckpt.free, ckpt, link);
     458           0 :         TAILQ_INSERT_TAIL(&dev->p2l_ckpt.inuse, ckpt, link);
     459             : 
     460           0 :         return ckpt;
     461             : }
     462             : 
     463             : int
     464           0 : ftl_mngt_p2l_ckpt_restore_clean(struct ftl_band *band)
     465             : {
     466           0 :         struct spdk_ftl_dev *dev = band->dev;
     467           0 :         struct ftl_layout *layout = &dev->layout;
     468             :         struct ftl_p2l_ckpt_page *page, *map_page;
     469           0 :         enum ftl_layout_region_type md_region = band->md->p2l_md_region;
     470             :         uint64_t page_no;
     471             :         uint64_t num_written_pages;
     472             :         union ftl_md_vss *page_md_buf;
     473             : 
     474           0 :         if (md_region < FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN ||
     475             :             md_region > FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MAX) {
     476           0 :                 return -EINVAL;
     477             :         }
     478             : 
     479           0 :         assert(band->md->iter.offset % FTL_NUM_LBA_IN_BLOCK == 0);
     480           0 :         num_written_pages = band->md->iter.offset / FTL_NUM_LBA_IN_BLOCK;
     481             : 
     482             :         /* Associate band with md region before shutdown */
     483           0 :         if (!band->p2l_map.p2l_ckpt) {
     484           0 :                 band->p2l_map.p2l_ckpt = ftl_p2l_ckpt_acquire_region_type(dev, md_region);
     485             :         }
     486             : 
     487             :         /* Band was opened but no data was written */
     488           0 :         if (band->md->iter.offset == 0) {
     489           0 :                 return 0;
     490             :         }
     491             : 
     492           0 :         page_no = 0;
     493             : 
     494             :         /* Restore P2L map up to last written page */
     495           0 :         page_md_buf = ftl_md_get_vss_buffer(layout->md[md_region]);
     496           0 :         page = ftl_md_get_buffer(layout->md[md_region]);
     497             : 
     498           0 :         for (; page_no < num_written_pages; page_no++, page++, page_md_buf++) {
     499           0 :                 if (page_md_buf->p2l_ckpt.seq_id != band->md->seq) {
     500           0 :                         assert(page_md_buf->p2l_ckpt.seq_id == band->md->seq);
     501             :                 }
     502             : 
     503             :                 /* Get the corresponding P2L map page */
     504           0 :                 map_page = ((struct ftl_p2l_ckpt_page *)band->p2l_map.band_map) + page_no;
     505             : 
     506             :                 /* Restore the page from P2L checkpoint */
     507           0 :                 *map_page = *page;
     508             : 
     509             : #if defined(DEBUG)
     510           0 :                 assert(ftl_bitmap_get(band->p2l_map.p2l_ckpt->bmp, page_no) == false);
     511           0 :                 ftl_bitmap_set(band->p2l_map.p2l_ckpt->bmp, page_no);
     512             : #endif
     513             :         }
     514             : 
     515           0 :         assert(page_md_buf->p2l_ckpt.seq_id < band->md->seq);
     516             : 
     517           0 :         return 0;
     518             : }
     519             : 
     520             : void
     521           0 : ftl_mngt_p2l_ckpt_restore_shm_clean(struct ftl_band *band)
     522             : {
     523           0 :         struct spdk_ftl_dev *dev = band->dev;
     524           0 :         enum ftl_layout_region_type md_region = band->md->p2l_md_region;
     525             : 
     526             :         /* Associate band with md region before shutdown */
     527           0 :         if (!band->p2l_map.p2l_ckpt) {
     528           0 :                 band->p2l_map.p2l_ckpt = ftl_p2l_ckpt_acquire_region_type(dev, md_region);
     529             :         }
     530             : 
     531             : #if defined(DEBUG)
     532             :         uint64_t page_no;
     533             :         uint64_t num_written_pages;
     534             : 
     535           0 :         assert(band->md->iter.offset % FTL_NUM_LBA_IN_BLOCK == 0);
     536           0 :         num_written_pages = band->md->iter.offset / FTL_NUM_LBA_IN_BLOCK;
     537             : 
     538             :         /* Band was opened but no data was written */
     539           0 :         if (band->md->iter.offset == 0) {
     540           0 :                 return;
     541             :         }
     542             : 
     543             :         /* Set page number to first data page - skip head md */
     544           0 :         page_no = 0;
     545             : 
     546           0 :         for (; page_no < num_written_pages; page_no++) {
     547           0 :                 assert(ftl_bitmap_get(band->p2l_map.p2l_ckpt->bmp, page_no) == false);
     548           0 :                 ftl_bitmap_set(band->p2l_map.p2l_ckpt->bmp, page_no);
     549             :         }
     550             : #endif
     551             : }

Generated by: LCOV version 1.15