LCOV - code coverage report
Current view: top level - lib/ftl/upgrade - ftl_sb_v5.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 158 292 54.1 %
Date: 2024-07-10 18:23:03 Functions: 17 30 56.7 %

          Line data    Source code
       1             : /*   SPDX-License-Identifier: BSD-3-Clause
       2             :  *   Copyright 2023 Solidigm All Rights Reserved
       3             :  *   All rights reserved.
       4             :  */
       5             : 
       6             : #include "spdk/string.h"
       7             : 
       8             : #include "ftl_sb_v5.h"
       9             : #include "ftl_core.h"
      10             : #include "ftl_layout.h"
      11             : #include "ftl_band.h"
      12             : #include "upgrade/ftl_sb_prev.h"
      13             : #include "upgrade/ftl_sb_upgrade.h"
      14             : #include "upgrade/ftl_layout_upgrade.h"
      15             : #include "utils/ftl_layout_tracker_bdev.h"
      16             : 
      17             : typedef size_t (*blob_store_fn)(struct spdk_ftl_dev *dev, void *blob_buf, size_t blob_buf_sz);
      18             : typedef int (*blob_load_fn)(struct spdk_ftl_dev *dev, void *blob_buf, size_t blob_sz);
      19             : 
      20             : bool
      21           4 : ftl_superblock_v5_is_blob_area_empty(union ftl_superblock_ver *sb_ver)
      22             : {
      23           4 :         return sb_ver->v5.blob_area_end == 0;
      24             : }
      25             : 
      26             : static bool
      27           0 : validate_blob_area(struct ftl_superblock_v5_md_blob_hdr *sb_blob_hdr,
      28             :                    ftl_df_obj_id sb_blob_area_end)
      29             : {
      30           0 :         return sb_blob_hdr->df_id <= sb_blob_area_end &&
      31           0 :                (sb_blob_hdr->df_id + sb_blob_hdr->blob_sz) <= sb_blob_area_end;
      32             : }
      33             : 
      34             : bool
      35           0 : ftl_superblock_v5_validate_blob_area(struct spdk_ftl_dev *dev)
      36             : {
      37           0 :         union ftl_superblock_ver *sb_ver = (union ftl_superblock_ver *)dev->sb;
      38             : 
      39           0 :         return validate_blob_area(&sb_ver->v5.md_layout_nvc, sb_ver->v5.blob_area_end) &&
      40           0 :                validate_blob_area(&sb_ver->v5.md_layout_base, sb_ver->v5.blob_area_end) &&
      41           0 :                validate_blob_area(&sb_ver->v5.layout_params, sb_ver->v5.blob_area_end);
      42             : }
      43             : 
      44             : static size_t
      45           6 : sb_blob_store(struct spdk_ftl_dev *dev, struct ftl_superblock_v5_md_blob_hdr *sb_blob_hdr,
      46             :               blob_store_fn blob_store, void *sb_blob_area)
      47             : {
      48           6 :         struct ftl_superblock_v5 *sb = (struct ftl_superblock_v5 *)dev->sb;
      49           6 :         uintptr_t sb_end = ((uintptr_t)sb) + FTL_SUPERBLOCK_SIZE;
      50           6 :         size_t blob_sz = sb_end - (uintptr_t)sb_blob_area;
      51             : 
      52             :         /* Test SB blob area overflow */
      53           6 :         if ((uintptr_t)sb_blob_area < (uintptr_t)sb->blob_area) {
      54           0 :                 ftl_bug(true);
      55             :                 return 0;
      56             :         }
      57           6 :         if ((uintptr_t)sb_blob_area >= sb_end) {
      58           0 :                 ftl_bug(true);
      59             :                 return 0;
      60             :         }
      61             : 
      62           6 :         blob_sz = blob_store(dev, sb_blob_area, blob_sz);
      63           6 :         sb_blob_hdr->blob_sz = blob_sz;
      64           6 :         sb_blob_hdr->df_id = ftl_df_get_obj_id(sb->blob_area, sb_blob_area);
      65           6 :         return blob_sz;
      66             : }
      67             : 
      68             : static size_t
      69           2 : base_blob_store(struct spdk_ftl_dev *dev, void *blob_buf, size_t blob_buf_sz)
      70             : {
      71           2 :         return ftl_layout_tracker_bdev_blob_store(dev->base_layout_tracker, blob_buf, blob_buf_sz);
      72             : }
      73             : 
      74             : static size_t
      75           2 : nvc_blob_store(struct spdk_ftl_dev *dev, void *blob_buf, size_t blob_buf_sz)
      76             : {
      77           2 :         return ftl_layout_tracker_bdev_blob_store(dev->nvc_layout_tracker, blob_buf, blob_buf_sz);
      78             : }
      79             : 
      80             : int
      81           2 : ftl_superblock_v5_store_blob_area(struct spdk_ftl_dev *dev)
      82             : {
      83           2 :         struct ftl_superblock_v5 *sb = (struct ftl_superblock_v5 *)dev->sb;
      84             :         void *sb_blob_area;
      85             :         size_t blob_sz;
      86             : 
      87             :         /* Store the NVC-backed FTL MD layout info */
      88           2 :         sb_blob_area = ftl_df_get_obj_ptr(sb->blob_area, 0);
      89           2 :         spdk_strcpy_pad(sb->nvc_dev_name, dev->nv_cache.nvc_desc->name,
      90             :                         SPDK_COUNTOF(sb->nvc_dev_name), '\0');
      91           2 :         blob_sz = sb_blob_store(dev, &sb->md_layout_nvc, nvc_blob_store, sb_blob_area);
      92           2 :         FTL_NOTICELOG(dev, "nvc layout blob store 0x%"PRIx64" bytes\n", blob_sz);
      93           2 :         if (!blob_sz) {
      94           0 :                 return -1;
      95             :         }
      96             : 
      97             :         /* Store the base dev-backed FTL MD layout info */
      98           2 :         sb_blob_area += blob_sz;
      99           2 :         spdk_strcpy_pad(sb->base_dev_name, dev->base_type->name, SPDK_COUNTOF(sb->base_dev_name), '\0');
     100           2 :         blob_sz = sb_blob_store(dev, &sb->md_layout_base, base_blob_store, sb_blob_area);
     101           2 :         FTL_NOTICELOG(dev, "base layout blob store 0x%"PRIx64" bytes\n", blob_sz);
     102           2 :         if (!blob_sz) {
     103           0 :                 return -1;
     104             :         }
     105             : 
     106             :         /* Store the region props */
     107           2 :         sb_blob_area += blob_sz;
     108           2 :         blob_sz = sb_blob_store(dev, &sb->layout_params, ftl_layout_blob_store, sb_blob_area);
     109           2 :         FTL_NOTICELOG(dev, "layout blob store 0x%"PRIx64" bytes\n", blob_sz);
     110           2 :         if (!blob_sz) {
     111           0 :                 return -1;
     112             :         }
     113             : 
     114             :         /* Update the blob area end */
     115           2 :         sb_blob_area += blob_sz;
     116           2 :         sb->blob_area_end = ftl_df_get_obj_id(sb->blob_area, sb_blob_area);
     117             : 
     118           2 :         return 0;
     119             : }
     120             : 
     121             : static const struct ftl_layout_tracker_bdev_region_props *
     122          14 : sb_md_layout_find_oldest_region(struct spdk_ftl_dev *dev,
     123             :                                 struct ftl_layout_tracker_bdev *layout_tracker,
     124             :                                 enum ftl_layout_region_type reg_type, void *find_filter)
     125             : {
     126          14 :         const struct ftl_layout_tracker_bdev_region_props *reg_search_ctx = NULL;
     127          14 :         const struct ftl_layout_tracker_bdev_region_props *reg_oldest = NULL;
     128             :         uint32_t ver_oldest;
     129             : 
     130             :         while (true) {
     131          24 :                 ftl_layout_tracker_bdev_find_next_region(layout_tracker, reg_type, &reg_search_ctx);
     132          24 :                 if (!reg_search_ctx) {
     133          14 :                         break;
     134             :                 }
     135             : 
     136          10 :                 if (!reg_oldest) {
     137           7 :                         reg_oldest = reg_search_ctx;
     138           7 :                         ver_oldest = reg_search_ctx->ver;
     139           7 :                         continue;
     140             :                 }
     141             : 
     142           3 :                 ftl_bug(ver_oldest == reg_search_ctx->ver);
     143           3 :                 if (ver_oldest > reg_search_ctx->ver) {
     144           1 :                         reg_oldest = reg_search_ctx;
     145           1 :                         ver_oldest = reg_search_ctx->ver;
     146             :                 }
     147             :         }
     148             : 
     149          14 :         return reg_oldest;
     150             : }
     151             : 
     152             : static const struct ftl_layout_tracker_bdev_region_props *
     153          10 : sb_md_layout_find_latest_region(struct spdk_ftl_dev *dev,
     154             :                                 struct ftl_layout_tracker_bdev *layout_tracker, enum ftl_layout_region_type reg_type,
     155             :                                 void *find_filter)
     156             : {
     157          10 :         const struct ftl_layout_tracker_bdev_region_props *reg_search_ctx = NULL;
     158          10 :         const struct ftl_layout_tracker_bdev_region_props *reg_latest = NULL;
     159             :         uint32_t ver_latest;
     160             : 
     161             :         while (true) {
     162          17 :                 ftl_layout_tracker_bdev_find_next_region(layout_tracker, reg_type, &reg_search_ctx);
     163          17 :                 if (!reg_search_ctx) {
     164          10 :                         break;
     165             :                 }
     166             : 
     167           7 :                 if (!reg_latest) {
     168           5 :                         reg_latest = reg_search_ctx;
     169           5 :                         ver_latest = reg_search_ctx->ver;
     170           5 :                         continue;
     171             :                 }
     172             : 
     173           2 :                 ftl_bug(ver_latest == reg_search_ctx->ver);
     174           2 :                 if (ver_latest < reg_search_ctx->ver) {
     175           1 :                         reg_latest = reg_search_ctx;
     176           1 :                         ver_latest = reg_search_ctx->ver;
     177             :                 }
     178             :         }
     179             : 
     180          10 :         return reg_latest;
     181             : }
     182             : 
     183             : static const struct ftl_layout_tracker_bdev_region_props *
     184           8 : sb_md_layout_find_region_version(struct spdk_ftl_dev *dev,
     185             :                                  struct ftl_layout_tracker_bdev *layout_tracker, enum ftl_layout_region_type reg_type,
     186             :                                  void *find_filter)
     187             : {
     188           8 :         const struct ftl_layout_tracker_bdev_region_props *reg_search_ctx = NULL;
     189           8 :         uint32_t *reg_ver = find_filter;
     190             : 
     191           8 :         assert(reg_ver);
     192             : 
     193             :         while (true) {
     194          12 :                 ftl_layout_tracker_bdev_find_next_region(layout_tracker, reg_type, &reg_search_ctx);
     195          12 :                 if (!reg_search_ctx) {
     196           6 :                         break;
     197             :                 }
     198             : 
     199           6 :                 if (reg_search_ctx->ver == *reg_ver) {
     200           2 :                         break;
     201             :                 }
     202             :         }
     203             : 
     204           8 :         return reg_search_ctx;
     205             : }
     206             : 
     207             : typedef const struct ftl_layout_tracker_bdev_region_props *(*sb_md_layout_find_fn)(
     208             :         struct spdk_ftl_dev *dev, struct ftl_layout_tracker_bdev *layout_tracker,
     209             :         enum ftl_layout_region_type reg_type, void *find_filter);
     210             : 
     211             : static const struct ftl_layout_tracker_bdev_region_props *
     212          16 : sb_md_layout_find_region(struct spdk_ftl_dev *dev, enum ftl_layout_region_type reg_type,
     213             :                          sb_md_layout_find_fn find_fn, void *find_filter)
     214             : {
     215             :         const struct ftl_layout_tracker_bdev_region_props *reg_search_ctx;
     216          16 :         struct ftl_layout_tracker_bdev *nvc_layout_tracker = dev->nvc_layout_tracker;
     217          16 :         struct ftl_layout_tracker_bdev *base_layout_tracker = dev->base_layout_tracker;
     218             : 
     219          16 :         reg_search_ctx = find_fn(dev, nvc_layout_tracker, reg_type, find_filter);
     220          16 :         if (reg_search_ctx) {
     221          14 :                 assert(find_fn(dev, base_layout_tracker, reg_type, find_filter) == NULL);
     222          14 :                 return reg_search_ctx;
     223             :         }
     224             : 
     225           2 :         reg_search_ctx = find_fn(dev, base_layout_tracker, reg_type, find_filter);
     226           2 :         return reg_search_ctx;
     227             : }
     228             : 
     229             : static int
     230          29 : sb_blob_load(struct spdk_ftl_dev *dev, struct ftl_superblock_v5_md_blob_hdr *sb_blob_hdr,
     231             :              blob_load_fn blob_load)
     232             : {
     233          29 :         struct ftl_superblock_v5 *sb = (struct ftl_superblock_v5 *)dev->sb;
     234          29 :         uintptr_t sb_end = ((uintptr_t)sb) + FTL_SUPERBLOCK_SIZE;
     235             :         void *blob_area;
     236             : 
     237          29 :         if (sb_blob_hdr->df_id == FTL_DF_OBJ_ID_INVALID) {
     238             :                 /* Uninitialized blob */
     239           2 :                 return -1;
     240             :         }
     241             : 
     242          27 :         blob_area = ftl_df_get_obj_ptr(sb->blob_area, sb_blob_hdr->df_id);
     243             : 
     244             :         /* Test SB blob area overflow */
     245          27 :         if ((uintptr_t)blob_area < (uintptr_t)sb->blob_area) {
     246           0 :                 ftl_bug(true);
     247             :                 return -1;
     248             :         }
     249          27 :         if ((uintptr_t)blob_area + sb_blob_hdr->blob_sz >= sb_end) {
     250           0 :                 ftl_bug(true);
     251             :                 return -1;
     252             :         }
     253             : 
     254          27 :         return blob_load(dev, blob_area, sb_blob_hdr->blob_sz);
     255             : }
     256             : 
     257             : static int
     258           8 : base_blob_load(struct spdk_ftl_dev *dev, void *blob_buf, size_t blob_sz)
     259             : {
     260           8 :         return ftl_layout_tracker_bdev_blob_load(dev->base_layout_tracker, blob_buf, blob_sz);
     261             : }
     262             : 
     263             : static int
     264          12 : nvc_blob_load(struct spdk_ftl_dev *dev, void *blob_buf, size_t blob_sz)
     265             : {
     266          12 :         return ftl_layout_tracker_bdev_blob_load(dev->nvc_layout_tracker, blob_buf, blob_sz);
     267             : }
     268             : 
     269             : int
     270          14 : ftl_superblock_v5_load_blob_area(struct spdk_ftl_dev *dev)
     271             : {
     272          14 :         struct ftl_superblock_v5 *sb = (struct ftl_superblock_v5 *)dev->sb;
     273             : 
     274             :         /* Load the NVC-backed FTL MD layout info */
     275          14 :         if (strncmp(sb->nvc_dev_name, dev->nv_cache.nvc_desc->name, SPDK_COUNTOF(sb->nvc_dev_name))) {
     276           0 :                 return -1;
     277             :         }
     278          14 :         FTL_NOTICELOG(dev, "nvc layout blob load 0x%"PRIx64" bytes\n", (uint64_t)sb->md_layout_nvc.blob_sz);
     279          14 :         if (sb_blob_load(dev, &sb->md_layout_nvc, nvc_blob_load)) {
     280           6 :                 return -1;
     281             :         }
     282             : 
     283             :         /* Load the base dev-backed FTL MD layout info */
     284           8 :         if (strncmp(sb->base_dev_name, dev->base_type->name, SPDK_COUNTOF(sb->base_dev_name))) {
     285           0 :                 return -1;
     286             :         }
     287           8 :         FTL_NOTICELOG(dev, "base layout blob load 0x%"PRIx64" bytes\n",
     288             :                       (uint64_t)sb->md_layout_base.blob_sz);
     289           8 :         if (sb_blob_load(dev, &sb->md_layout_base, base_blob_load)) {
     290           1 :                 return -1;
     291             :         }
     292             : 
     293             :         /* Load the region props */
     294           7 :         FTL_NOTICELOG(dev, "layout blob load 0x%"PRIx64" bytes\n", (uint64_t)sb->layout_params.blob_sz);
     295           7 :         if (sb_blob_load(dev, &sb->layout_params, ftl_layout_blob_load)) {
     296           1 :                 return -1;
     297             :         }
     298             : 
     299           6 :         return 0;
     300             : }
     301             : 
     302             : static struct ftl_layout_tracker_bdev *
     303           3 : sb_get_md_layout_tracker(struct spdk_ftl_dev *dev, struct ftl_layout_region *reg)
     304             : {
     305           3 :         return (reg->bdev_desc == dev->base_bdev_desc) ? dev->base_layout_tracker : dev->nvc_layout_tracker;
     306             : }
     307             : 
     308             : static void
     309           1 : sb_md_layout_delete_prev_region(struct spdk_ftl_dev *dev, struct ftl_layout_region *reg)
     310             : {
     311             :         int rc;
     312           1 :         struct ftl_layout_tracker_bdev *layout_tracker = sb_get_md_layout_tracker(dev, reg);
     313             : 
     314           1 :         rc = ftl_layout_tracker_bdev_rm_region(layout_tracker, reg->type, reg->current.version);
     315           1 :         ftl_bug(rc != 0);
     316           1 : }
     317             : 
     318             : static void
     319           2 : sb_md_layout_update_prev_region(struct spdk_ftl_dev *dev, struct ftl_layout_region *reg,
     320             :                                 uint32_t new_version)
     321             : {
     322             :         int rc;
     323           2 :         const struct ftl_layout_tracker_bdev_region_props *reg_search_ctx = NULL;
     324           2 :         struct ftl_layout_tracker_bdev *layout_tracker = sb_get_md_layout_tracker(dev, reg);
     325             :         struct ftl_layout_tracker_bdev_region_props reg_props;
     326             : 
     327             :         /* Get region properties */
     328           2 :         ftl_layout_tracker_bdev_find_next_region(layout_tracker, reg->type, &reg_search_ctx);
     329           2 :         ftl_bug(reg_search_ctx == NULL);
     330           2 :         reg_props = *reg_search_ctx;
     331             : 
     332             :         /* Delete the region */
     333           2 :         rc = ftl_layout_tracker_bdev_rm_region(layout_tracker, reg_props.type, reg_props.ver);
     334           2 :         ftl_bug(rc != 0);
     335             : 
     336             :         /* Insert the same region with new version */
     337           2 :         reg_search_ctx = ftl_layout_tracker_bdev_insert_region(layout_tracker, reg_props.type, new_version,
     338             :                          reg_props.blk_offs, reg_props.blk_sz);
     339           2 :         ftl_bug(reg_search_ctx == NULL);
     340             : 
     341             :         /* Verify the oldest region version stored in the SB is the new_version */
     342           2 :         reg_search_ctx = sb_md_layout_find_region(dev, reg_props.type, sb_md_layout_find_oldest_region,
     343             :                          NULL);
     344           2 :         ftl_bug(reg_search_ctx == NULL);
     345           2 :         ftl_bug(reg_search_ctx->ver != new_version);
     346           2 : }
     347             : 
     348             : int
     349           3 : ftl_superblock_v5_md_layout_upgrade_region(struct spdk_ftl_dev *dev, struct ftl_layout_region *reg,
     350             :                 uint32_t new_version)
     351             : {
     352           3 :         const struct ftl_layout_tracker_bdev_region_props *reg_next = NULL;
     353             :         uint64_t latest_ver;
     354             : 
     355           3 :         ftl_bug(reg->current.version >= new_version);
     356             : 
     357           3 :         reg_next = sb_md_layout_find_region(dev, reg->type, sb_md_layout_find_region_version, &new_version);
     358           3 :         if (reg_next) {
     359             :                 /**
     360             :                  * Major upgrade.
     361             :                  * Found a new MD region allocated for upgrade to the next version.
     362             :                  * Destroy the previous version now that the upgrade is completed.
     363             :                  */
     364           1 :                 ftl_bug(reg_next->ver != new_version);
     365           1 :                 ftl_bug(reg_next->type != reg->type);
     366           1 :                 sb_md_layout_delete_prev_region(dev, reg);
     367           1 :                 reg->current.offset = reg_next->blk_offs;
     368           1 :                 reg->current.blocks = reg_next->blk_sz;
     369             :         } else {
     370             :                 /**
     371             :                  * Minor upgrade.
     372             :                  * Upgraded the MD region in place.
     373             :                  * Update the version in place.
     374             :                  */
     375           2 :                 sb_md_layout_update_prev_region(dev, reg, new_version);
     376             :         }
     377             : 
     378           3 :         reg->current.version = new_version;
     379           3 :         latest_ver = ftl_layout_upgrade_region_get_latest_version(reg->type);
     380           3 :         if (new_version == latest_ver) {
     381             :                 /* Audit the only region version stored in the SB */
     382           1 :                 reg_next = sb_md_layout_find_region(dev, reg->type, sb_md_layout_find_latest_region, NULL);
     383           1 :                 ftl_bug(reg_next == NULL);
     384           1 :                 ftl_bug(reg_next->ver != new_version);
     385             : 
     386           1 :                 reg_next = sb_md_layout_find_region(dev, reg->type, sb_md_layout_find_oldest_region, NULL);
     387           1 :                 ftl_bug(reg_next == NULL);
     388           1 :                 ftl_bug(reg_next->ver != new_version);
     389             : 
     390           1 :                 reg_next = sb_md_layout_find_region(dev, reg->type, sb_md_layout_find_region_version, &new_version);
     391           1 :                 ftl_bug(reg->type != reg_next->type);
     392           1 :                 ftl_bug(reg->current.version != reg_next->ver);
     393           1 :                 ftl_bug(reg->current.offset != reg_next->blk_offs);
     394           1 :                 ftl_bug(reg->current.blocks != reg_next->blk_sz);
     395             :         }
     396             : 
     397           3 :         return 0;
     398             : }
     399             : 
     400             : void
     401           0 : ftl_superblock_v5_md_layout_dump(struct spdk_ftl_dev *dev)
     402             : {
     403           0 :         struct ftl_layout_tracker_bdev *nvc_layout_tracker = dev->nvc_layout_tracker;
     404           0 :         struct ftl_layout_tracker_bdev *base_layout_tracker = dev->base_layout_tracker;
     405           0 :         const struct ftl_layout_tracker_bdev_region_props *reg_search_ctx = NULL;
     406             : 
     407           0 :         FTL_NOTICELOG(dev, "SB metadata layout - nvc:\n");
     408             :         while (true) {
     409           0 :                 ftl_layout_tracker_bdev_find_next_region(nvc_layout_tracker, FTL_LAYOUT_REGION_TYPE_INVALID,
     410             :                                 &reg_search_ctx);
     411           0 :                 if (!reg_search_ctx) {
     412           0 :                         break;
     413             :                 }
     414             : 
     415           0 :                 FTL_NOTICELOG(dev,
     416             :                               "Region type:0x%"PRIx32" ver:%"PRIu32" blk_offs:0x%"PRIx64" blk_sz:0x%"PRIx64"\n",
     417             :                               reg_search_ctx->type, reg_search_ctx->ver, reg_search_ctx->blk_offs, reg_search_ctx->blk_sz);
     418             :         }
     419             : 
     420           0 :         reg_search_ctx = NULL;
     421           0 :         FTL_NOTICELOG(dev, "SB metadata layout - base dev:\n");
     422             :         while (true) {
     423           0 :                 ftl_layout_tracker_bdev_find_next_region(base_layout_tracker, FTL_LAYOUT_REGION_TYPE_INVALID,
     424             :                                 &reg_search_ctx);
     425           0 :                 if (!reg_search_ctx) {
     426           0 :                         break;
     427             :                 }
     428             : 
     429           0 :                 FTL_NOTICELOG(dev,
     430             :                               "Region type:0x%"PRIx32" ver:%"PRIu32" blk_offs:0x%"PRIx64" blk_sz:0x%"PRIx64"\n",
     431             :                               reg_search_ctx->type, reg_search_ctx->ver, reg_search_ctx->blk_offs, reg_search_ctx->blk_sz);
     432             :         }
     433           0 : }
     434             : 
     435             : static int
     436           0 : layout_apply_from_sb_blob(struct spdk_ftl_dev *dev, struct ftl_layout_tracker_bdev *layout_tracker,
     437             :                           int (*filter_region_type_fn)(enum ftl_layout_region_type))
     438             : {
     439             :         struct ftl_layout_region *reg;
     440           0 :         const struct ftl_layout_tracker_bdev_region_props *reg_search_ctx = NULL;
     441             : 
     442             :         while (true) {
     443           0 :                 ftl_layout_tracker_bdev_find_next_region(layout_tracker, FTL_LAYOUT_REGION_TYPE_INVALID,
     444             :                                 &reg_search_ctx);
     445           0 :                 if (!reg_search_ctx) {
     446           0 :                         break;
     447             :                 }
     448           0 :                 if (reg_search_ctx->type == FTL_LAYOUT_REGION_TYPE_FREE) {
     449           0 :                         continue;
     450             :                 }
     451           0 :                 if (filter_region_type_fn(reg_search_ctx->type)) {
     452           0 :                         FTL_ERRLOG(dev, "Unknown region found in layout blob: type 0x%"PRIx32"\n", reg_search_ctx->type);
     453           0 :                         return -1;
     454             :                 }
     455             : 
     456           0 :                 reg = &dev->layout.region[reg_search_ctx->type];
     457             : 
     458             :                 /* First region of a given type found */
     459           0 :                 if (reg->type == FTL_LAYOUT_REGION_TYPE_INVALID) {
     460           0 :                         reg->type = reg_search_ctx->type;
     461           0 :                         reg->current.version = reg_search_ctx->ver;
     462           0 :                         reg->current.offset = reg_search_ctx->blk_offs;
     463           0 :                         reg->current.blocks = reg_search_ctx->blk_sz;
     464           0 :                         continue;
     465             :                 }
     466             : 
     467             :                 /* Update to the oldest region version found */
     468           0 :                 if (reg_search_ctx->ver < reg->current.version) {
     469           0 :                         reg->current.version = reg_search_ctx->ver;
     470           0 :                         reg->current.offset = reg_search_ctx->blk_offs;
     471           0 :                         reg->current.blocks = reg_search_ctx->blk_sz;
     472           0 :                         continue;
     473             :                 }
     474             : 
     475             :                 /* Skip newer region versions */
     476           0 :                 if (reg_search_ctx->ver > reg->current.version) {
     477           0 :                         continue;
     478             :                 }
     479             : 
     480             :                 /* Current region version already found */
     481           0 :                 assert(reg_search_ctx->ver == reg->current.version);
     482           0 :                 if (reg->current.offset != reg_search_ctx->blk_offs ||
     483           0 :                     reg->current.blocks != reg_search_ctx->blk_sz) {
     484           0 :                         FTL_ERRLOG(dev, "Corrupted layout blob: reg type 0x%"PRIx32"\n", reg_search_ctx->type);
     485           0 :                         return -1;
     486             :                 }
     487             :         }
     488           0 :         return 0;
     489             : }
     490             : 
     491             : static int
     492           0 : layout_region_verify(struct spdk_ftl_dev *dev, enum ftl_layout_region_type reg_type,
     493             :                      uint32_t reg_ver)
     494             : {
     495           0 :         struct ftl_layout_region *reg = ftl_layout_region_get(dev, reg_type);
     496             : 
     497           0 :         if (!reg) {
     498           0 :                 FTL_ERRLOG(dev, "Region not found in nvc layout blob: reg type 0x%"PRIx32"\n", reg_type);
     499           0 :                 return -1;
     500             :         }
     501             : 
     502             :         /* Unknown version found in the blob */
     503           0 :         if (reg->current.version > reg_ver) {
     504           0 :                 FTL_ERRLOG(dev, "Unknown region version found in layout blob: reg type 0x%"PRIx32"\n",
     505             :                            reg_type);
     506           0 :                 return -1;
     507             :         }
     508             : 
     509           0 :         return 0;
     510             : }
     511             : 
     512             : static int
     513           0 : layout_fixup_reg_data_base(struct spdk_ftl_dev *dev)
     514             : {
     515           0 :         const struct ftl_md_layout_ops *base_md_ops = &dev->base_type->ops.md_layout_ops;
     516           0 :         struct ftl_layout_region *reg = &dev->layout.region[FTL_LAYOUT_REGION_TYPE_DATA_BASE];
     517           0 :         const struct ftl_layout_tracker_bdev_region_props *reg_search_ctx = NULL;
     518             : 
     519           0 :         assert(reg->type == FTL_LAYOUT_REGION_TYPE_INVALID);
     520             : 
     521           0 :         FTL_NOTICELOG(dev, "Adding a region\n");
     522             : 
     523             :         /* Add the region */
     524           0 :         if (base_md_ops->region_create(dev, FTL_LAYOUT_REGION_TYPE_DATA_BASE, 0,
     525             :                                        ftl_layout_base_offset(dev))) {
     526           0 :                 return -1;
     527             :         }
     528           0 :         if (base_md_ops->region_open(dev, FTL_LAYOUT_REGION_TYPE_DATA_BASE, 0, FTL_BLOCK_SIZE,
     529             :                                      ftl_layout_base_offset(dev), reg)) {
     530           0 :                 return -1;
     531             :         }
     532             : 
     533           0 :         ftl_layout_tracker_bdev_find_next_region(dev->base_layout_tracker, FTL_LAYOUT_REGION_TYPE_DATA_BASE,
     534             :                         &reg_search_ctx);
     535           0 :         assert(reg_search_ctx);
     536           0 :         return 0;
     537             : }
     538             : 
     539             : static int
     540           0 : layout_fixup_base(struct spdk_ftl_dev *dev)
     541             : {
     542             :         struct ftl_layout_region_descr {
     543             :                 enum ftl_layout_region_type type;
     544             :                 uint32_t ver;
     545             :                 int (*on_reg_miss)(struct spdk_ftl_dev *dev);
     546             :         };
     547             :         struct ftl_layout_region_descr *reg_descr;
     548             :         static struct ftl_layout_region_descr nvc_regs[] = {
     549             :                 { .type = FTL_LAYOUT_REGION_TYPE_SB_BASE, .ver = FTL_SB_VERSION_CURRENT },
     550             :                 { .type = FTL_LAYOUT_REGION_TYPE_DATA_BASE, .ver = 0, .on_reg_miss = layout_fixup_reg_data_base },
     551             :                 { .type = FTL_LAYOUT_REGION_TYPE_VALID_MAP, .ver = 0 },
     552             :                 { .type = FTL_LAYOUT_REGION_TYPE_INVALID, .ver = 0 },
     553             :         };
     554             : 
     555           0 :         for (reg_descr = nvc_regs; reg_descr->type != FTL_LAYOUT_REGION_TYPE_INVALID; reg_descr++) {
     556             :                 struct ftl_layout_region *region;
     557             : 
     558           0 :                 if (layout_region_verify(dev, reg_descr->type, reg_descr->ver) &&
     559           0 :                     reg_descr->on_reg_miss && reg_descr->on_reg_miss(dev)) {
     560           0 :                         return -1;
     561             :                 }
     562             : 
     563           0 :                 region = &dev->layout.region[reg_descr->type];
     564           0 :                 region->type = reg_descr->type;
     565           0 :                 region->mirror_type = FTL_LAYOUT_REGION_TYPE_INVALID;
     566           0 :                 region->name = ftl_md_region_name(reg_descr->type);
     567             : 
     568           0 :                 region->bdev_desc = dev->base_bdev_desc;
     569           0 :                 region->ioch = dev->base_ioch;
     570           0 :                 region->vss_blksz = 0;
     571             :         }
     572             : 
     573           0 :         return 0;
     574             : }
     575             : 
     576             : static int
     577           0 : layout_fixup_nvc(struct spdk_ftl_dev *dev)
     578             : {
     579             :         struct ftl_layout_region_descr {
     580             :                 enum ftl_layout_region_type type;
     581             :                 uint32_t ver;
     582             :                 enum ftl_layout_region_type mirror_type;
     583             :         };
     584             :         struct ftl_layout_region_descr *reg_descr;
     585             :         static struct ftl_layout_region_descr nvc_regs[] = {
     586             :                 { .type = FTL_LAYOUT_REGION_TYPE_SB, .ver = FTL_SB_VERSION_CURRENT, .mirror_type = FTL_LAYOUT_REGION_TYPE_SB_BASE },
     587             :                 { .type = FTL_LAYOUT_REGION_TYPE_L2P, .ver = 0 },
     588             :                 { .type = FTL_LAYOUT_REGION_TYPE_BAND_MD, .ver = FTL_BAND_VERSION_CURRENT, .mirror_type = FTL_LAYOUT_REGION_TYPE_BAND_MD_MIRROR },
     589             :                 { .type = FTL_LAYOUT_REGION_TYPE_BAND_MD_MIRROR, .ver = FTL_BAND_VERSION_CURRENT },
     590             :                 { .type = FTL_LAYOUT_REGION_TYPE_TRIM_MD, .ver = 0, .mirror_type = FTL_LAYOUT_REGION_TYPE_TRIM_MD_MIRROR },
     591             :                 { .type = FTL_LAYOUT_REGION_TYPE_TRIM_MD_MIRROR, .ver = 0 },
     592             :                 { .type = FTL_LAYOUT_REGION_TYPE_NVC_MD, .ver = FTL_NVC_VERSION_CURRENT, .mirror_type = FTL_LAYOUT_REGION_TYPE_NVC_MD_MIRROR },
     593             :                 { .type = FTL_LAYOUT_REGION_TYPE_NVC_MD_MIRROR, .ver = FTL_NVC_VERSION_CURRENT },
     594             :                 { .type = FTL_LAYOUT_REGION_TYPE_DATA_NVC, .ver = 0 },
     595             :                 { .type = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_GC, .ver = FTL_P2L_VERSION_CURRENT },
     596             :                 { .type = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_GC_NEXT, .ver = FTL_P2L_VERSION_CURRENT },
     597             :                 { .type = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_COMP, .ver = FTL_P2L_VERSION_CURRENT },
     598             :                 { .type = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_COMP_NEXT, .ver = FTL_P2L_VERSION_CURRENT },
     599             :                 { .type = FTL_LAYOUT_REGION_TYPE_INVALID, .ver = 0 },
     600             :         };
     601             : 
     602           0 :         for (reg_descr = nvc_regs; reg_descr->type != FTL_LAYOUT_REGION_TYPE_INVALID; reg_descr++) {
     603             :                 struct ftl_layout_region *region;
     604             : 
     605           0 :                 if (layout_region_verify(dev, reg_descr->type, reg_descr->ver)) {
     606           0 :                         return -1;
     607             :                 }
     608             : 
     609           0 :                 region = &dev->layout.region[reg_descr->type];
     610           0 :                 region->type = reg_descr->type;
     611           0 :                 region->mirror_type = FTL_LAYOUT_REGION_TYPE_INVALID;
     612           0 :                 region->name = ftl_md_region_name(reg_descr->type);
     613             : 
     614           0 :                 region->bdev_desc = dev->nv_cache.bdev_desc;
     615           0 :                 region->ioch = dev->nv_cache.cache_ioch;
     616           0 :                 region->vss_blksz = dev->nv_cache.md_size;
     617             : 
     618           0 :                 if (reg_descr->mirror_type) {
     619           0 :                         dev->layout.region[reg_descr->type].mirror_type = reg_descr->mirror_type;
     620             :                 }
     621             :         }
     622             : 
     623           0 :         return 0;
     624             : }
     625             : 
     626             : static int
     627           0 : filter_region_type_base(enum ftl_layout_region_type reg_type)
     628             : {
     629           0 :         switch (reg_type) {
     630           0 :         case FTL_LAYOUT_REGION_TYPE_SB_BASE:
     631             :         case FTL_LAYOUT_REGION_TYPE_DATA_BASE:
     632             :         case FTL_LAYOUT_REGION_TYPE_VALID_MAP:
     633           0 :                 return 0;
     634             : 
     635           0 :         default:
     636           0 :                 return 1;
     637             :         }
     638             : }
     639             : 
     640             : static int
     641           0 : filter_region_type_nvc(enum ftl_layout_region_type reg_type)
     642             : {
     643           0 :         return filter_region_type_base(reg_type) ? 0 : 1;
     644             : }
     645             : 
     646             : static int
     647           0 : layout_apply_nvc(struct spdk_ftl_dev *dev)
     648             : {
     649           0 :         if (layout_apply_from_sb_blob(dev, dev->nvc_layout_tracker, filter_region_type_nvc) ||
     650           0 :             layout_fixup_nvc(dev)) {
     651           0 :                 return -1;
     652             :         }
     653           0 :         return 0;
     654             : }
     655             : 
     656             : static int
     657           0 : layout_apply_base(struct spdk_ftl_dev *dev)
     658             : {
     659           0 :         if (layout_apply_from_sb_blob(dev, dev->base_layout_tracker, filter_region_type_base) ||
     660           0 :             layout_fixup_base(dev)) {
     661           0 :                 return -1;
     662             :         }
     663           0 :         return 0;
     664             : }
     665             : 
     666             : int
     667           0 : ftl_superblock_v5_md_layout_apply(struct spdk_ftl_dev *dev)
     668             : {
     669           0 :         if (layout_apply_nvc(dev) || layout_apply_base(dev)) {
     670           0 :                 return -1;
     671             :         }
     672           0 :         return 0;
     673             : }

Generated by: LCOV version 1.15