Line data Source code
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 0 : is_bdev_compatible(struct spdk_ftl_dev *dev, struct spdk_bdev *bdev) 13 : { 14 0 : uint64_t write_unit_size = spdk_bdev_get_write_unit_size(bdev); 15 : 16 0 : if (spdk_bdev_get_block_size(bdev) != FTL_BLOCK_SIZE) { 17 0 : FTL_ERRLOG(dev, "Unsupported block size, only 4096 is supprted.\nn"); 18 0 : return false; 19 : } 20 : 21 0 : if (spdk_bdev_get_md_size(bdev) != 0) { 22 : /* Bdev's metadata is unsupported */ 23 0 : FTL_ERRLOG(dev, "Unsupported metadata size, sector metadata isn't supported.\n"); 24 0 : return false; 25 : } 26 : 27 0 : if (write_unit_size == 1) { 28 : /* No write unit size, all alignments will work out fine */ 29 0 : return true; 30 : } 31 : 32 0 : if (!spdk_u32_is_pow2(write_unit_size) || write_unit_size > (MiB / FTL_BLOCK_SIZE)) { 33 : /* Needs to be a power of 2 for current band size (1GiB) restrictions. 34 : * Current buffers are allocated in 1MiB sizes (256 blocks), so it can't be larger than that. 35 : * In the future, if the restriction is relaxed, the ftl_bitmap_buffer_alignment (64 blocks) 36 : * will need to be taken into consideration as well. 37 : */ 38 0 : FTL_ERRLOG(dev, 39 : "Unsupported write unit size (%lu), must be a power of 2 (in blocks). Can't be larger than 256 (1MiB)\n", 40 : write_unit_size); 41 0 : return false; 42 : } 43 : 44 0 : return true; 45 : } 46 : 47 : static void 48 0 : md_region_setup(struct spdk_ftl_dev *dev, enum ftl_layout_region_type reg_type, 49 : struct ftl_layout_region *region) 50 : { 51 0 : assert(region); 52 0 : region->type = reg_type; 53 0 : region->mirror_type = FTL_LAYOUT_REGION_TYPE_INVALID; 54 0 : region->name = ftl_md_region_name(reg_type); 55 : 56 0 : region->bdev_desc = dev->base_bdev_desc; 57 0 : region->ioch = dev->base_ioch; 58 0 : region->vss_blksz = 0; 59 0 : } 60 : 61 : static int 62 0 : md_region_create(struct spdk_ftl_dev *dev, enum ftl_layout_region_type reg_type, 63 : uint32_t reg_version, size_t reg_blks) 64 : { 65 : const struct ftl_layout_tracker_bdev_region_props *reg_props; 66 : uint64_t data_base_alignment; 67 : 68 0 : assert(reg_type < FTL_LAYOUT_REGION_TYPE_MAX); 69 0 : reg_blks = ftl_md_region_align_blocks(dev, reg_blks); 70 : 71 : /* Allocating a ftl_bitmap requires a 8B input buffer alignment, since we're reusing the global valid map md buffer 72 : * this means that each band starting address needs to be aligned too - each device sector takes 1b in the valid map, 73 : * so 64 sectors (8*8) is the needed alignment 74 : */ 75 0 : data_base_alignment = 8 * ftl_bitmap_buffer_alignment; 76 0 : reg_props = ftl_layout_tracker_bdev_add_region(dev->base_layout_tracker, reg_type, reg_version, 77 : reg_blks, data_base_alignment); 78 0 : if (!reg_props) { 79 0 : return -1; 80 : } 81 0 : assert(reg_props->type == reg_type); 82 0 : assert(reg_props->ver == reg_version); 83 0 : assert(reg_props->blk_sz == reg_blks); 84 0 : assert(reg_props->blk_offs + reg_blks <= dev->layout.base.total_blocks); 85 0 : return 0; 86 : } 87 : 88 : static int 89 0 : md_region_open(struct spdk_ftl_dev *dev, enum ftl_layout_region_type reg_type, uint32_t reg_version, 90 : size_t entry_size, size_t entry_count, struct ftl_layout_region *region) 91 : { 92 0 : const struct ftl_layout_tracker_bdev_region_props *reg_search_ctx = NULL; 93 0 : uint64_t reg_blks = ftl_md_region_blocks(dev, entry_size * entry_count); 94 : 95 0 : assert(reg_type < FTL_LAYOUT_REGION_TYPE_MAX); 96 : 97 : while (true) { 98 0 : ftl_layout_tracker_bdev_find_next_region(dev->base_layout_tracker, reg_type, ®_search_ctx); 99 0 : if (!reg_search_ctx || reg_search_ctx->ver == reg_version) { 100 : break; 101 : } 102 : } 103 : 104 0 : if (!reg_search_ctx || reg_search_ctx->blk_sz < reg_blks) { 105 : /* Region not found or insufficient space */ 106 0 : return -1; 107 : } 108 : 109 0 : if (!region) { 110 0 : return 0; 111 : } 112 : 113 0 : md_region_setup(dev, reg_type, region); 114 : 115 0 : region->entry_size = entry_size / FTL_BLOCK_SIZE; 116 0 : region->num_entries = entry_count; 117 : 118 0 : region->current.version = reg_version; 119 0 : region->current.offset = reg_search_ctx->blk_offs; 120 0 : region->current.blocks = reg_search_ctx->blk_sz; 121 : 122 0 : return 0; 123 : } 124 : 125 : struct ftl_base_device_type base_bdev = { 126 : .name = "base_bdev", 127 : .ops = { 128 : .is_bdev_compatible = is_bdev_compatible, 129 : 130 : .md_layout_ops = { 131 : .region_create = md_region_create, 132 : .region_open = md_region_open, 133 : }, 134 : } 135 : }; 136 0 : FTL_BASE_DEVICE_TYPE_REGISTER(base_bdev)