xref: /spdk/lib/ftl/base/ftl_base_bdev.c (revision 95d6c9fac17572b107042103439aafd696d60b0e)
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, &reg_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