Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause 2 : : * Copyright 2023 Solidigm All Rights Reserved 3 : : */ 4 : : 5 : : #include "ftl_nvc_dev.h" 6 : : #include "ftl_core.h" 7 : : #include "ftl_layout.h" 8 : : #include "utils/ftl_layout_tracker_bdev.h" 9 : : 10 : : static bool 11 : 27 : is_bdev_compatible(struct spdk_ftl_dev *dev, struct spdk_bdev *bdev) 12 : : { 13 [ - + ]: 27 : if (!spdk_bdev_is_md_separate(bdev)) { 14 : : /* It doesn't support separate metadata buffer IO */ 15 : 0 : return false; 16 : : } 17 : : 18 [ - + ]: 27 : if (spdk_bdev_get_md_size(bdev) != sizeof(union ftl_md_vss)) { 19 : : /* Bdev's metadata is invalid size */ 20 : 0 : return false; 21 : : } 22 : : 23 [ - + ]: 27 : if (spdk_bdev_get_dif_type(bdev) != SPDK_DIF_DISABLE) { 24 : : /* Unsupported DIF type used by bdev */ 25 : 0 : return false; 26 : : } 27 : : 28 [ - + ]: 27 : if (ftl_md_xfer_blocks(dev) * spdk_bdev_get_md_size(bdev) > FTL_ZERO_BUFFER_SIZE) { 29 [ # # ]: 0 : FTL_ERRLOG(dev, "Zero buffer too small for bdev %s metadata transfer\n", 30 : : spdk_bdev_get_name(bdev)); 31 : 0 : return false; 32 : : } 33 : : 34 : 27 : return true; 35 : : } 36 : : 37 : : static bool 38 : 275 : is_chunk_active(struct spdk_ftl_dev *dev, uint64_t chunk_offset) 39 : : { 40 : 275 : const struct ftl_layout_tracker_bdev_region_props *reg_free = ftl_layout_tracker_bdev_insert_region( 41 : : dev->nvc_layout_tracker, FTL_LAYOUT_REGION_TYPE_INVALID, 0, chunk_offset, 42 : : dev->layout.nvc.chunk_data_blocks); 43 : : 44 [ + + - + ]: 275 : assert(!reg_free || reg_free->type == FTL_LAYOUT_REGION_TYPE_FREE); 45 : 275 : return reg_free != NULL; 46 : : } 47 : : 48 : : static void 49 : 105 : md_region_setup(struct spdk_ftl_dev *dev, enum ftl_layout_region_type reg_type, 50 : : struct ftl_layout_region *region) 51 : : { 52 [ - + ]: 105 : assert(region); 53 : 105 : region->type = reg_type; 54 : 105 : region->mirror_type = FTL_LAYOUT_REGION_TYPE_INVALID; 55 : 105 : region->name = ftl_md_region_name(reg_type); 56 : : 57 : 105 : region->bdev_desc = dev->nv_cache.bdev_desc; 58 : 105 : region->ioch = dev->nv_cache.cache_ioch; 59 : 105 : region->vss_blksz = dev->nv_cache.md_size; 60 : 105 : } 61 : : 62 : : static int 63 : 105 : md_region_create(struct spdk_ftl_dev *dev, enum ftl_layout_region_type reg_type, 64 : : uint32_t reg_version, size_t reg_blks) 65 : : { 66 : : const struct ftl_layout_tracker_bdev_region_props *reg_props; 67 : : 68 [ - + ]: 105 : assert(reg_type < FTL_LAYOUT_REGION_TYPE_MAX); 69 : 105 : reg_blks = ftl_md_region_align_blocks(dev, reg_blks); 70 : : 71 : 105 : reg_props = ftl_layout_tracker_bdev_add_region(dev->nvc_layout_tracker, reg_type, reg_version, 72 : : reg_blks, 0); 73 [ - + ]: 105 : if (!reg_props) { 74 : 0 : return -1; 75 : : } 76 [ - + ]: 105 : assert(reg_props->type == reg_type); 77 [ - + ]: 105 : assert(reg_props->ver == reg_version); 78 [ - + ]: 105 : assert(reg_props->blk_sz == reg_blks); 79 [ - + ]: 105 : assert(reg_props->blk_offs + reg_blks <= dev->layout.nvc.total_blocks); 80 : 105 : return 0; 81 : : } 82 : : 83 : : static int 84 : 105 : md_region_open(struct spdk_ftl_dev *dev, enum ftl_layout_region_type reg_type, uint32_t reg_version, 85 : : size_t entry_size, size_t entry_count, struct ftl_layout_region *region) 86 : : { 87 : 105 : const struct ftl_layout_tracker_bdev_region_props *reg_search_ctx = NULL; 88 : 105 : uint64_t reg_blks = ftl_md_region_blocks(dev, entry_size * entry_count); 89 : : 90 [ + - ]: 105 : assert(reg_type < FTL_LAYOUT_REGION_TYPE_MAX); 91 : : 92 : : while (true) { 93 : 105 : ftl_layout_tracker_bdev_find_next_region(dev->nvc_layout_tracker, reg_type, ®_search_ctx); 94 [ + - - + ]: 105 : if (!reg_search_ctx || reg_search_ctx->ver == reg_version) { 95 : : break; 96 : : } 97 : : } 98 : : 99 [ + - - + ]: 105 : if (!reg_search_ctx || reg_search_ctx->blk_sz < reg_blks) { 100 : : /* Region not found or insufficient space */ 101 : 0 : return -1; 102 : : } 103 : : 104 [ - + ]: 105 : if (!region) { 105 : 0 : return 0; 106 : : } 107 : : 108 : 105 : md_region_setup(dev, reg_type, region); 109 : : 110 : 105 : region->entry_size = entry_size / FTL_BLOCK_SIZE; 111 : 105 : region->num_entries = entry_count; 112 : : 113 : 105 : region->current.version = reg_version; 114 : 105 : region->current.offset = reg_search_ctx->blk_offs; 115 : 105 : region->current.blocks = reg_search_ctx->blk_sz; 116 : : 117 : 105 : return 0; 118 : : } 119 : : 120 : : struct ftl_nv_cache_device_type nvc_bdev_vss = { 121 : : .name = "bdev", 122 : : .features = { 123 : : }, 124 : : .ops = { 125 : : .is_bdev_compatible = is_bdev_compatible, 126 : : .is_chunk_active = is_chunk_active, 127 : : .md_layout_ops = { 128 : : .region_create = md_region_create, 129 : : .region_open = md_region_open, 130 : : }, 131 : : } 132 : : }; 133 : 1993 : FTL_NV_CACHE_DEVICE_TYPE_REGISTER(nvc_bdev_vss)