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_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 : 27 : is_bdev_compatible(struct spdk_ftl_dev *dev, struct spdk_bdev *bdev)
13 : : {
14 : 27 : uint64_t write_unit_size = spdk_bdev_get_write_unit_size(bdev);
15 : :
16 [ - + ]: 27 : 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 [ - + ]: 27 : 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 [ + - ]: 27 : if (write_unit_size == 1) {
28 : : /* No write unit size, all alignments will work out fine */
29 : 27 : 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 : 0 : }
46 : :
47 : : static void
48 : 39 : md_region_setup(struct spdk_ftl_dev *dev, enum ftl_layout_region_type reg_type,
49 : : struct ftl_layout_region *region)
50 : : {
51 [ - + # # ]: 39 : assert(region);
52 [ # # # # ]: 39 : region->type = reg_type;
53 [ # # # # ]: 39 : region->mirror_type = FTL_LAYOUT_REGION_TYPE_INVALID;
54 [ # # # # ]: 39 : region->name = ftl_md_region_name(reg_type);
55 : :
56 [ # # # # : 39 : region->bdev_desc = dev->base_bdev_desc;
# # # # ]
57 [ # # # # : 39 : region->ioch = dev->base_ioch;
# # # # ]
58 [ # # # # ]: 39 : region->vss_blksz = 0;
59 : 39 : }
60 : :
61 : : static int
62 : 39 : 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 [ - + # # ]: 39 : assert(reg_type < FTL_LAYOUT_REGION_TYPE_MAX);
69 : 39 : 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 : 39 : data_base_alignment = 8 * ftl_bitmap_buffer_alignment;
76 [ # # # # ]: 39 : reg_props = ftl_layout_tracker_bdev_add_region(dev->base_layout_tracker, reg_type, reg_version,
77 : 0 : reg_blks, data_base_alignment);
78 [ - + ]: 39 : if (!reg_props) {
79 : 0 : return -1;
80 : : }
81 [ - + # # : 39 : assert(reg_props->type == reg_type);
# # # # ]
82 [ - + # # : 39 : assert(reg_props->ver == reg_version);
# # # # ]
83 [ - + # # : 39 : assert(reg_props->blk_sz == reg_blks);
# # # # ]
84 [ - + # # : 39 : assert(reg_props->blk_offs + reg_blks <= dev->layout.base.total_blocks);
# # # # #
# # # # #
# # ]
85 : 39 : return 0;
86 : 0 : }
87 : :
88 : : static int
89 : 39 : 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 : 39 : const struct ftl_layout_tracker_bdev_region_props *reg_search_ctx = NULL;
93 : 39 : uint64_t reg_blks = ftl_md_region_blocks(dev, entry_size * entry_count);
94 : :
95 [ + - # # ]: 39 : assert(reg_type < FTL_LAYOUT_REGION_TYPE_MAX);
96 : :
97 : 0 : while (true) {
98 [ # # # # ]: 39 : ftl_layout_tracker_bdev_find_next_region(dev->base_layout_tracker, reg_type, ®_search_ctx);
99 [ + - - + : 39 : if (!reg_search_ctx || reg_search_ctx->ver == reg_version) {
# # # # ]
100 : 0 : break;
101 : : }
102 : : }
103 : :
104 [ + - - + : 39 : 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 [ - + ]: 39 : if (!region) {
110 : 0 : return 0;
111 : : }
112 : :
113 : 39 : md_region_setup(dev, reg_type, region);
114 : :
115 [ # # # # : 39 : region->entry_size = entry_size / FTL_BLOCK_SIZE;
# # ]
116 [ # # # # ]: 39 : region->num_entries = entry_count;
117 : :
118 [ # # # # : 39 : region->current.version = reg_version;
# # ]
119 [ # # # # : 39 : region->current.offset = reg_search_ctx->blk_offs;
# # # # #
# ]
120 [ # # # # : 39 : region->current.blocks = reg_search_ctx->blk_sz;
# # # # #
# ]
121 : :
122 : 39 : return 0;
123 : 0 : }
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 : 2166 : FTL_BASE_DEVICE_TYPE_REGISTER(base_bdev)
|