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 0 : is_bdev_compatible(struct spdk_ftl_dev *dev, struct spdk_bdev *bdev) 12 : { 13 0 : if (!spdk_bdev_is_md_separate(bdev)) { 14 : /* It doesn't support separate metadata buffer IO */ 15 0 : return false; 16 : } 17 : 18 0 : 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 0 : if (spdk_bdev_get_dif_type(bdev) != SPDK_DIF_DISABLE) { 24 : /* Unsupported DIF type used by bdev */ 25 0 : return false; 26 : } 27 : 28 0 : 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 0 : return true; 35 : } 36 : 37 : static void 38 0 : md_region_setup(struct spdk_ftl_dev *dev, enum ftl_layout_region_type reg_type, 39 : struct ftl_layout_region *region) 40 : { 41 0 : assert(region); 42 0 : region->type = reg_type; 43 0 : region->mirror_type = FTL_LAYOUT_REGION_TYPE_INVALID; 44 0 : region->name = ftl_md_region_name(reg_type); 45 : 46 0 : region->bdev_desc = dev->nv_cache.bdev_desc; 47 0 : region->ioch = dev->nv_cache.cache_ioch; 48 0 : region->vss_blksz = dev->nv_cache.md_size; 49 0 : } 50 : 51 : static int 52 0 : md_region_create(struct spdk_ftl_dev *dev, enum ftl_layout_region_type reg_type, 53 : uint32_t reg_version, size_t reg_blks) 54 : { 55 : const struct ftl_layout_tracker_bdev_region_props *reg_props; 56 : 57 0 : assert(reg_type < FTL_LAYOUT_REGION_TYPE_MAX); 58 0 : reg_blks = ftl_md_region_align_blocks(dev, reg_blks); 59 : 60 0 : reg_props = ftl_layout_tracker_bdev_add_region(dev->nvc_layout_tracker, reg_type, reg_version, 61 : reg_blks, 0); 62 0 : if (!reg_props) { 63 0 : return -1; 64 : } 65 0 : assert(reg_props->type == reg_type); 66 0 : assert(reg_props->ver == reg_version); 67 0 : assert(reg_props->blk_sz == reg_blks); 68 0 : assert(reg_props->blk_offs + reg_blks <= dev->layout.nvc.total_blocks); 69 0 : return 0; 70 : } 71 : 72 : static int 73 0 : md_region_open(struct spdk_ftl_dev *dev, enum ftl_layout_region_type reg_type, uint32_t reg_version, 74 : size_t entry_size, size_t entry_count, struct ftl_layout_region *region) 75 : { 76 0 : const struct ftl_layout_tracker_bdev_region_props *reg_search_ctx = NULL; 77 0 : uint64_t reg_blks = ftl_md_region_blocks(dev, entry_size * entry_count); 78 : 79 0 : assert(reg_type < FTL_LAYOUT_REGION_TYPE_MAX); 80 : 81 : while (true) { 82 0 : ftl_layout_tracker_bdev_find_next_region(dev->nvc_layout_tracker, reg_type, ®_search_ctx); 83 0 : if (!reg_search_ctx || reg_search_ctx->ver == reg_version) { 84 : break; 85 : } 86 : } 87 : 88 0 : if (!reg_search_ctx || reg_search_ctx->blk_sz < reg_blks) { 89 : /* Region not found or insufficient space */ 90 0 : return -1; 91 : } 92 : 93 0 : if (!region) { 94 0 : return 0; 95 : } 96 : 97 0 : md_region_setup(dev, reg_type, region); 98 : 99 0 : region->entry_size = entry_size / FTL_BLOCK_SIZE; 100 0 : region->num_entries = entry_count; 101 : 102 0 : region->current.version = reg_version; 103 0 : region->current.offset = reg_search_ctx->blk_offs; 104 0 : region->current.blocks = reg_search_ctx->blk_sz; 105 : 106 0 : return 0; 107 : } 108 : 109 : struct ftl_nv_cache_device_desc nvc_bdev_vss = { 110 : .name = "bdev", 111 : .features = { 112 : }, 113 : .ops = { 114 : .is_bdev_compatible = is_bdev_compatible, 115 : 116 : .md_layout_ops = { 117 : .region_create = md_region_create, 118 : .region_open = md_region_open, 119 : }, 120 : } 121 : }; 122 0 : FTL_NV_CACHE_DEVICE_TYPE_REGISTER(nvc_bdev_vss)