xref: /spdk/lib/ftl/nvc/ftl_nvc_bdev_vss.c (revision 71c1bbeeb5dc30a74ce4779c3058f15161340b87)
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 is_bdev_compatible(struct spdk_ftl_dev *dev, struct spdk_bdev *bdev)
12 {
13 	if (!spdk_bdev_is_md_separate(bdev)) {
14 		/* It doesn't support separate metadata buffer IO */
15 		return false;
16 	}
17 
18 	if (spdk_bdev_get_md_size(bdev) != sizeof(union ftl_md_vss)) {
19 		/* Bdev's metadata is invalid size */
20 		return false;
21 	}
22 
23 	if (spdk_bdev_get_dif_type(bdev) != SPDK_DIF_DISABLE) {
24 		/* Unsupported DIF type used by bdev */
25 		return false;
26 	}
27 
28 	if (ftl_md_xfer_blocks(dev) * spdk_bdev_get_md_size(bdev) > FTL_ZERO_BUFFER_SIZE) {
29 		FTL_ERRLOG(dev, "Zero buffer too small for bdev %s metadata transfer\n",
30 			   spdk_bdev_get_name(bdev));
31 		return false;
32 	}
33 
34 	return true;
35 }
36 
37 static bool
38 is_chunk_active(struct spdk_ftl_dev *dev, uint64_t chunk_offset)
39 {
40 	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 	assert(!reg_free || reg_free->type == FTL_LAYOUT_REGION_TYPE_FREE);
45 	return reg_free != NULL;
46 }
47 
48 static void
49 md_region_setup(struct spdk_ftl_dev *dev, enum ftl_layout_region_type reg_type,
50 		struct ftl_layout_region *region)
51 {
52 	assert(region);
53 	region->type = reg_type;
54 	region->mirror_type = FTL_LAYOUT_REGION_TYPE_INVALID;
55 	region->name = ftl_md_region_name(reg_type);
56 
57 	region->bdev_desc = dev->nv_cache.bdev_desc;
58 	region->ioch = dev->nv_cache.cache_ioch;
59 	region->vss_blksz = dev->nv_cache.md_size;
60 }
61 
62 static int
63 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 	assert(reg_type < FTL_LAYOUT_REGION_TYPE_MAX);
69 	reg_blks = ftl_md_region_align_blocks(dev, reg_blks);
70 
71 	reg_props = ftl_layout_tracker_bdev_add_region(dev->nvc_layout_tracker, reg_type, reg_version,
72 			reg_blks, 0);
73 	if (!reg_props) {
74 		return -1;
75 	}
76 	assert(reg_props->type == reg_type);
77 	assert(reg_props->ver == reg_version);
78 	assert(reg_props->blk_sz == reg_blks);
79 	assert(reg_props->blk_offs + reg_blks <= dev->layout.nvc.total_blocks);
80 	return 0;
81 }
82 
83 static int
84 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 	const struct ftl_layout_tracker_bdev_region_props *reg_search_ctx = NULL;
88 	uint64_t reg_blks = ftl_md_region_blocks(dev, entry_size * entry_count);
89 
90 	assert(reg_type < FTL_LAYOUT_REGION_TYPE_MAX);
91 
92 	while (true) {
93 		ftl_layout_tracker_bdev_find_next_region(dev->nvc_layout_tracker, reg_type, &reg_search_ctx);
94 		if (!reg_search_ctx || reg_search_ctx->ver == reg_version) {
95 			break;
96 		}
97 	}
98 
99 	if (!reg_search_ctx || reg_search_ctx->blk_sz < reg_blks) {
100 		/* Region not found or insufficient space */
101 		return -1;
102 	}
103 
104 	if (!region) {
105 		return 0;
106 	}
107 
108 	md_region_setup(dev, reg_type, region);
109 
110 	region->entry_size = entry_size / FTL_BLOCK_SIZE;
111 	region->num_entries = entry_count;
112 
113 	region->current.version = reg_version;
114 	region->current.offset = reg_search_ctx->blk_offs;
115 	region->current.blocks = reg_search_ctx->blk_sz;
116 
117 	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 FTL_NV_CACHE_DEVICE_TYPE_REGISTER(nvc_bdev_vss)
134