]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
4 | #pragma once | |
5 | ||
6 | #include <sys/mman.h> | |
7 | #include <memory> | |
8 | #include <string.h> | |
9 | ||
20effc67 TL |
10 | |
11 | #include "include/buffer.h" | |
12 | ||
13 | #include "crimson/common/fixed_kv_node_layout.h" | |
14 | #include "crimson/common/errorator.h" | |
f67539c2 | 15 | #include "crimson/os/seastore/lba_manager.h" |
20effc67 TL |
16 | #include "crimson/os/seastore/seastore_types.h" |
17 | #include "crimson/os/seastore/cache.h" | |
18 | #include "crimson/os/seastore/cached_extent.h" | |
1e59de90 TL |
19 | |
20 | #include "crimson/os/seastore/btree/btree_range_pin.h" | |
21 | #include "crimson/os/seastore/btree/fixed_kv_btree.h" | |
22 | #include "crimson/os/seastore/btree/fixed_kv_node.h" | |
f67539c2 TL |
23 | |
24 | namespace crimson::os::seastore::lba_manager::btree { | |
25 | ||
20effc67 | 26 | using base_iertr = LBAManager::base_iertr; |
1e59de90 | 27 | using LBANode = FixedKVNode<laddr_t>; |
f67539c2 TL |
28 | |
29 | /** | |
30 | * lba_map_val_t | |
31 | * | |
32 | * struct representing a single lba mapping | |
33 | */ | |
34 | struct lba_map_val_t { | |
35 | extent_len_t len = 0; ///< length of mapping | |
36 | paddr_t paddr; ///< physical addr of mapping | |
37 | uint32_t refcount = 0; ///< refcount | |
38 | uint32_t checksum = 0; ///< checksum of original block written at paddr (TODO) | |
39 | ||
20effc67 | 40 | lba_map_val_t() = default; |
f67539c2 TL |
41 | lba_map_val_t( |
42 | extent_len_t len, | |
43 | paddr_t paddr, | |
44 | uint32_t refcount, | |
45 | uint32_t checksum) | |
46 | : len(len), paddr(paddr), refcount(refcount), checksum(checksum) {} | |
1e59de90 | 47 | bool operator==(const lba_map_val_t&) const = default; |
f67539c2 TL |
48 | }; |
49 | ||
1e59de90 | 50 | std::ostream& operator<<(std::ostream& out, const lba_map_val_t&); |
f67539c2 | 51 | |
20effc67 TL |
52 | constexpr size_t LBA_BLOCK_SIZE = 4096; |
53 | ||
1e59de90 | 54 | using lba_node_meta_t = fixed_kv_node_meta_t<laddr_t>; |
f67539c2 | 55 | |
1e59de90 | 56 | using lba_node_meta_le_t = fixed_kv_node_meta_le_t<laddr_le_t>; |
f67539c2 | 57 | |
20effc67 TL |
58 | /** |
59 | * LBAInternalNode | |
60 | * | |
61 | * Abstracts operations on and layout of internal nodes for the | |
62 | * LBA Tree. | |
63 | * | |
64 | * Layout (4k): | |
65 | * size : uint32_t[1] 4b | |
66 | * (padding) : 4b | |
67 | * meta : lba_node_meta_le_t[3] (1*24)b | |
68 | * keys : laddr_t[255] (254*8)b | |
69 | * values : paddr_t[255] (254*8)b | |
70 | * = 4096 | |
71 | ||
72 | * TODO: make the above capacity calculation part of FixedKVNodeLayout | |
73 | * TODO: the above alignment probably isn't portable without further work | |
74 | */ | |
75 | constexpr size_t INTERNAL_NODE_CAPACITY = 254; | |
76 | struct LBAInternalNode | |
1e59de90 | 77 | : FixedKVInternalNode< |
20effc67 | 78 | INTERNAL_NODE_CAPACITY, |
20effc67 | 79 | laddr_t, laddr_le_t, |
1e59de90 TL |
80 | LBA_BLOCK_SIZE, |
81 | LBAInternalNode> { | |
20effc67 TL |
82 | using Ref = TCachedExtentRef<LBAInternalNode>; |
83 | using internal_iterator_t = const_iterator; | |
84 | template <typename... T> | |
85 | LBAInternalNode(T&&... t) : | |
1e59de90 | 86 | FixedKVInternalNode(std::forward<T>(t)...) {} |
20effc67 TL |
87 | |
88 | static constexpr extent_types_t TYPE = extent_types_t::LADDR_INTERNAL; | |
89 | ||
20effc67 TL |
90 | extent_types_t get_type() const final { |
91 | return TYPE; | |
92 | } | |
f67539c2 | 93 | }; |
20effc67 | 94 | using LBAInternalNodeRef = LBAInternalNode::Ref; |
f67539c2 TL |
95 | |
96 | /** | |
20effc67 TL |
97 | * LBALeafNode |
98 | * | |
99 | * Abstracts operations on and layout of leaf nodes for the | |
100 | * LBA Tree. | |
101 | * | |
102 | * Layout (4k): | |
103 | * size : uint32_t[1] 4b | |
104 | * (padding) : 4b | |
105 | * meta : lba_node_meta_le_t[3] (1*24)b | |
106 | * keys : laddr_t[170] (145*8)b | |
107 | * values : lba_map_val_t[170] (145*20)b | |
108 | * = 4092 | |
f67539c2 | 109 | * |
20effc67 TL |
110 | * TODO: update FixedKVNodeLayout to handle the above calculation |
111 | * TODO: the above alignment probably isn't portable without further work | |
f67539c2 | 112 | */ |
20effc67 TL |
113 | constexpr size_t LEAF_NODE_CAPACITY = 145; |
114 | ||
115 | /** | |
116 | * lba_map_val_le_t | |
117 | * | |
118 | * On disk layout for lba_map_val_t. | |
119 | */ | |
120 | struct lba_map_val_le_t { | |
121 | extent_len_le_t len = init_extent_len_le(0); | |
122 | paddr_le_t paddr; | |
123 | ceph_le32 refcount{0}; | |
124 | ceph_le32 checksum{0}; | |
125 | ||
126 | lba_map_val_le_t() = default; | |
127 | lba_map_val_le_t(const lba_map_val_le_t &) = default; | |
128 | explicit lba_map_val_le_t(const lba_map_val_t &val) | |
129 | : len(init_extent_len_le(val.len)), | |
130 | paddr(paddr_le_t(val.paddr)), | |
131 | refcount(val.refcount), | |
132 | checksum(val.checksum) {} | |
133 | ||
134 | operator lba_map_val_t() const { | |
135 | return lba_map_val_t{ len, paddr, refcount, checksum }; | |
136 | } | |
137 | }; | |
138 | ||
139 | struct LBALeafNode | |
1e59de90 | 140 | : FixedKVLeafNode< |
20effc67 | 141 | LEAF_NODE_CAPACITY, |
20effc67 | 142 | laddr_t, laddr_le_t, |
1e59de90 TL |
143 | lba_map_val_t, lba_map_val_le_t, |
144 | LBA_BLOCK_SIZE, | |
145 | LBALeafNode, | |
146 | true> { | |
20effc67 | 147 | using Ref = TCachedExtentRef<LBALeafNode>; |
1e59de90 TL |
148 | using parent_type_t = FixedKVLeafNode< |
149 | LEAF_NODE_CAPACITY, | |
150 | laddr_t, laddr_le_t, | |
151 | lba_map_val_t, lba_map_val_le_t, | |
152 | LBA_BLOCK_SIZE, | |
153 | LBALeafNode, | |
154 | true>; | |
155 | using internal_const_iterator_t = | |
156 | typename parent_type_t::node_layout_t::const_iterator; | |
157 | using internal_iterator_t = | |
158 | typename parent_type_t::node_layout_t::iterator; | |
20effc67 TL |
159 | template <typename... T> |
160 | LBALeafNode(T&&... t) : | |
1e59de90 | 161 | parent_type_t(std::forward<T>(t)...) {} |
20effc67 TL |
162 | |
163 | static constexpr extent_types_t TYPE = extent_types_t::LADDR_LEAF; | |
164 | ||
1e59de90 TL |
165 | bool validate_stable_children() final { |
166 | LOG_PREFIX(LBALeafNode::validate_stable_children); | |
167 | if (this->children.empty()) { | |
168 | return false; | |
169 | } | |
20effc67 | 170 | |
1e59de90 TL |
171 | for (auto i : *this) { |
172 | auto child = (LogicalCachedExtent*)this->children[i.get_offset()]; | |
173 | if (is_valid_child_ptr(child) && child->get_laddr() != i.get_key()) { | |
174 | SUBERROR(seastore_fixedkv_tree, | |
175 | "stable child not valid: child {}, key {}", | |
176 | *child, | |
177 | i.get_key()); | |
178 | ceph_abort(); | |
179 | return false; | |
180 | } | |
181 | } | |
182 | return true; | |
20effc67 TL |
183 | } |
184 | ||
185 | void update( | |
1e59de90 TL |
186 | internal_const_iterator_t iter, |
187 | lba_map_val_t val, | |
188 | LogicalCachedExtent* nextent) final { | |
189 | LOG_PREFIX(LBALeafNode::update); | |
190 | if (nextent) { | |
191 | SUBTRACE(seastore_fixedkv_tree, "trans.{}, pos {}, {}", | |
192 | this->pending_for_transaction, | |
193 | iter.get_offset(), | |
194 | *nextent); | |
195 | // child-ptr may already be correct, see LBAManager::update_mappings() | |
196 | this->update_child_ptr(iter, nextent); | |
197 | } | |
198 | val.paddr = this->maybe_generate_relative(val.paddr); | |
199 | return this->journal_update( | |
20effc67 TL |
200 | iter, |
201 | val, | |
1e59de90 | 202 | this->maybe_get_delta_buffer()); |
20effc67 TL |
203 | } |
204 | ||
1e59de90 TL |
205 | internal_const_iterator_t insert( |
206 | internal_const_iterator_t iter, | |
20effc67 | 207 | laddr_t addr, |
1e59de90 TL |
208 | lba_map_val_t val, |
209 | LogicalCachedExtent* nextent) final { | |
210 | LOG_PREFIX(LBALeafNode::insert); | |
211 | SUBTRACE(seastore_fixedkv_tree, "trans.{}, pos {}, key {}, extent {}", | |
212 | this->pending_for_transaction, | |
213 | iter.get_offset(), | |
214 | addr, | |
215 | (void*)nextent); | |
216 | this->insert_child_ptr(iter, nextent); | |
217 | val.paddr = this->maybe_generate_relative(val.paddr); | |
218 | this->journal_insert( | |
20effc67 TL |
219 | iter, |
220 | addr, | |
221 | val, | |
1e59de90 | 222 | this->maybe_get_delta_buffer()); |
20effc67 TL |
223 | return iter; |
224 | } | |
225 | ||
1e59de90 TL |
226 | void remove(internal_const_iterator_t iter) final { |
227 | LOG_PREFIX(LBALeafNode::remove); | |
228 | SUBTRACE(seastore_fixedkv_tree, "trans.{}, pos {}, key {}", | |
229 | this->pending_for_transaction, | |
230 | iter.get_offset(), | |
231 | iter.get_key()); | |
232 | assert(iter != this->end()); | |
233 | this->remove_child_ptr(iter); | |
234 | return this->journal_remove( | |
20effc67 | 235 | iter, |
1e59de90 | 236 | this->maybe_get_delta_buffer()); |
20effc67 TL |
237 | } |
238 | ||
239 | // See LBAInternalNode, same concept | |
240 | void resolve_relative_addrs(paddr_t base); | |
1e59de90 TL |
241 | void node_resolve_vals( |
242 | internal_iterator_t from, | |
243 | internal_iterator_t to) const final | |
244 | { | |
245 | if (this->is_initial_pending()) { | |
20effc67 TL |
246 | for (auto i = from; i != to; ++i) { |
247 | auto val = i->get_val(); | |
248 | if (val.paddr.is_relative()) { | |
249 | assert(val.paddr.is_block_relative()); | |
1e59de90 | 250 | val.paddr = this->get_paddr().add_relative(val.paddr); |
20effc67 TL |
251 | i->set_val(val); |
252 | } | |
253 | } | |
254 | } | |
255 | } | |
1e59de90 TL |
256 | void node_unresolve_vals( |
257 | internal_iterator_t from, | |
258 | internal_iterator_t to) const final | |
259 | { | |
260 | if (this->is_initial_pending()) { | |
20effc67 TL |
261 | for (auto i = from; i != to; ++i) { |
262 | auto val = i->get_val(); | |
263 | if (val.paddr.is_relative()) { | |
264 | auto val = i->get_val(); | |
265 | assert(val.paddr.is_record_relative()); | |
1e59de90 | 266 | val.paddr = val.paddr.block_relative_to(this->get_paddr()); |
20effc67 TL |
267 | i->set_val(val); |
268 | } | |
269 | } | |
270 | } | |
271 | } | |
272 | ||
20effc67 TL |
273 | extent_types_t get_type() const final { |
274 | return TYPE; | |
275 | } | |
276 | ||
1e59de90 | 277 | std::ostream &_print_detail(std::ostream &out) const final; |
20effc67 TL |
278 | }; |
279 | using LBALeafNodeRef = TCachedExtentRef<LBALeafNode>; | |
f67539c2 TL |
280 | |
281 | } | |
1e59de90 TL |
282 | |
283 | #if FMT_VERSION >= 90000 | |
284 | template <> struct fmt::formatter<crimson::os::seastore::lba_manager::btree::lba_node_meta_t> : fmt::ostream_formatter {}; | |
285 | template <> struct fmt::formatter<crimson::os::seastore::lba_manager::btree::lba_map_val_t> : fmt::ostream_formatter {}; | |
286 | template <> struct fmt::formatter<crimson::os::seastore::lba_manager::btree::LBAInternalNode> : fmt::ostream_formatter {}; | |
287 | template <> struct fmt::formatter<crimson::os::seastore::lba_manager::btree::LBALeafNode> : fmt::ostream_formatter {}; | |
288 | #endif |