1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2023 Solidigm All Rights Reserved 3 */ 4 5 #include "ftl_base_dev.h" 6 #include "ftl_core.h" 7 #include "ftl_layout.h" 8 #include "ftl_band.h" 9 #include "utils/ftl_layout_tracker_bdev.h" 10 11 static bool 12 is_bdev_compatible(struct spdk_ftl_dev *dev, struct spdk_bdev *bdev) 13 { 14 return spdk_bdev_get_block_size(bdev) == FTL_BLOCK_SIZE; 15 } 16 17 static void 18 md_region_setup(struct spdk_ftl_dev *dev, enum ftl_layout_region_type reg_type, 19 struct ftl_layout_region *region) 20 { 21 assert(region); 22 region->type = reg_type; 23 region->mirror_type = FTL_LAYOUT_REGION_TYPE_INVALID; 24 region->name = ftl_md_region_name(reg_type); 25 26 region->bdev_desc = dev->base_bdev_desc; 27 region->ioch = dev->base_ioch; 28 region->vss_blksz = 0; 29 } 30 31 static int 32 md_region_create(struct spdk_ftl_dev *dev, enum ftl_layout_region_type reg_type, 33 uint32_t reg_version, size_t reg_blks) 34 { 35 const struct ftl_layout_tracker_bdev_region_props *reg_props; 36 uint64_t data_base_alignment; 37 38 assert(reg_type < FTL_LAYOUT_REGION_TYPE_MAX); 39 reg_blks = ftl_md_region_align_blocks(dev, reg_blks); 40 41 /* Allocating a ftl_bitmap requires a 8B input buffer alignment, since we're reusing the global valid map md buffer 42 * this means that each band starting address needs to be aligned too - each device sector takes 1b in the valid map, 43 * so 64 sectors (8*8) is the needed alignment 44 */ 45 data_base_alignment = 8 * ftl_bitmap_buffer_alignment; 46 reg_props = ftl_layout_tracker_bdev_add_region(dev->base_layout_tracker, reg_type, reg_version, 47 reg_blks, data_base_alignment); 48 if (!reg_props) { 49 return -1; 50 } 51 assert(reg_props->type == reg_type); 52 assert(reg_props->ver == reg_version); 53 assert(reg_props->blk_sz == reg_blks); 54 assert(reg_props->blk_offs + reg_blks <= dev->layout.base.total_blocks); 55 return 0; 56 } 57 58 static int 59 md_region_open(struct spdk_ftl_dev *dev, enum ftl_layout_region_type reg_type, uint32_t reg_version, 60 size_t entry_size, size_t entry_count, struct ftl_layout_region *region) 61 { 62 const struct ftl_layout_tracker_bdev_region_props *reg_search_ctx = NULL; 63 uint64_t reg_blks = ftl_md_region_blocks(dev, entry_size * entry_count); 64 65 assert(reg_type < FTL_LAYOUT_REGION_TYPE_MAX); 66 67 while (true) { 68 ftl_layout_tracker_bdev_find_next_region(dev->base_layout_tracker, reg_type, ®_search_ctx); 69 if (!reg_search_ctx || reg_search_ctx->ver == reg_version) { 70 break; 71 } 72 } 73 74 if (!reg_search_ctx || reg_search_ctx->blk_sz < reg_blks) { 75 /* Region not found or insufficient space */ 76 return -1; 77 } 78 79 if (!region) { 80 return 0; 81 } 82 83 md_region_setup(dev, reg_type, region); 84 85 region->entry_size = entry_size / FTL_BLOCK_SIZE; 86 region->num_entries = entry_count; 87 88 region->current.version = reg_version; 89 region->current.offset = reg_search_ctx->blk_offs; 90 region->current.blocks = reg_search_ctx->blk_sz; 91 92 return 0; 93 } 94 95 struct ftl_base_device_type base_bdev = { 96 .name = "base_bdev", 97 .ops = { 98 .is_bdev_compatible = is_bdev_compatible, 99 100 .md_layout_ops = { 101 .region_create = md_region_create, 102 .region_open = md_region_open, 103 }, 104 } 105 }; 106 FTL_BASE_DEVICE_TYPE_REGISTER(base_bdev) 107