1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
5 #include "include/buffer.h"
7 #include "crimson/common/fixed_kv_node_layout.h"
8 #include "crimson/common/errorator.h"
9 #include "crimson/os/seastore/extentmap_manager.h"
10 #include "crimson/os/seastore/seastore_types.h"
11 #include "crimson/os/seastore/extentmap_manager/btree/extentmap_btree_node.h"
13 namespace crimson::os::seastore::extentmap_manager
{
15 struct extmap_node_meta_le_t
{
16 depth_le_t depth
= init_les32(0);
18 extmap_node_meta_le_t() = default;
19 extmap_node_meta_le_t(const extmap_node_meta_le_t
&) = default;
20 explicit extmap_node_meta_le_t(const extmap_node_meta_t
&val
)
21 : depth(init_les32(val
.depth
)) {}
23 operator extmap_node_meta_t() const {
24 return extmap_node_meta_t
{ depth
};
31 * Abstracts operations on and layout of internal nodes for the
35 * num_entries: uint32_t 4b
38 * keys : objaddr_t[340] (340*4)b
39 * values : laddr_t[340] (340*8)b
42 constexpr size_t INNER_NODE_CAPACITY
=
43 (EXTMAP_BLOCK_SIZE
- sizeof(uint32_t) - sizeof(extmap_node_meta_t
))
44 / (sizeof (objaddr_t
) + sizeof(laddr_t
));
46 struct ExtMapInnerNode
48 common::FixedKVNodeLayout
<
50 extmap_node_meta_t
, extmap_node_meta_le_t
,
52 laddr_t
, laddr_le_t
> {
53 using internal_iterator_t
= const_iterator
;
54 template <typename
... T
>
55 ExtMapInnerNode(T
&&... t
) :
56 ExtMapNode(std::forward
<T
>(t
)...),
57 FixedKVNodeLayout(get_bptr().c_str()) {}
59 static constexpr extent_types_t type
= extent_types_t::EXTMAP_INNER
;
61 extmap_node_meta_t
get_node_meta() const final
{return get_meta();}
63 CachedExtentRef
duplicate_for_write() final
{
64 assert(delta_buffer
.empty());
65 return CachedExtentRef(new ExtMapInnerNode(*this));
68 delta_buffer_t delta_buffer
;
69 delta_buffer_t
*maybe_get_delta_buffer() {
70 return is_mutation_pending() ? &delta_buffer
: nullptr;
73 find_lextent_ret
find_lextent(ext_context_t ec
, objaddr_t lo
, extent_len_t len
) final
;
75 insert_ret
insert(ext_context_t ec
, objaddr_t lo
, lext_map_val_t val
) final
;
77 rm_lextent_ret
rm_lextent(ext_context_t ec
, objaddr_t lo
, lext_map_val_t val
) final
;
79 split_children_ret
make_split_children(ext_context_t ec
) final
;
81 full_merge_ret
make_full_merge(ext_context_t ec
, ExtMapNodeRef right
) final
;
83 make_balanced_ret
make_balanced(ext_context_t ec
, ExtMapNodeRef _right
, bool prefer_left
) final
;
85 std::ostream
&print_detail_l(std::ostream
&out
) const final
;
87 extent_types_t
get_type() const final
{
91 ceph::bufferlist
get_delta() final
{
92 assert(!delta_buffer
.empty());
93 ceph::buffer::ptr
bptr(delta_buffer
.get_bytes());
94 delta_buffer
.copy_out(bptr
.c_str(), bptr
.length());
100 void apply_delta(const ceph::bufferlist
&_bl
) final
{
101 assert(_bl
.length());
102 ceph::bufferlist bl
= _bl
;
104 delta_buffer_t buffer
;
105 buffer
.copy_in(bl
.front().c_str(), bl
.front().length());
106 buffer
.replay(*this);
109 bool at_max_capacity() const final
{
110 return get_size() == get_capacity();
113 bool at_min_capacity() const {
114 return get_size() == get_capacity() / 2;
117 unsigned get_node_size() const {
121 /* get the iterator containing [l, r]
123 std::pair
<internal_iterator_t
, internal_iterator_t
> bound(
124 objaddr_t l
, objaddr_t r
) {
126 for (; retl
!= end(); ++retl
) {
127 if (retl
->get_next_key_or_max() > l
)
131 for (; retr
!= end(); ++retr
) {
132 if (retr
->get_key() >= r
)
138 using split_entry_ertr
= TransactionManager::read_extent_ertr
;
139 using split_entry_ret
= split_entry_ertr::future
<ExtMapNodeRef
>;
140 split_entry_ret
split_entry(ext_context_t ec
, objaddr_t lo
,
141 internal_iterator_t
, ExtMapNodeRef entry
);
142 using merge_entry_ertr
= TransactionManager::read_extent_ertr
;
143 using merge_entry_ret
= merge_entry_ertr::future
<ExtMapNodeRef
>;
144 merge_entry_ret
merge_entry(ext_context_t ec
, objaddr_t lo
,
145 internal_iterator_t iter
, ExtMapNodeRef entry
);
146 internal_iterator_t
get_containing_child(objaddr_t lo
);
153 * Abstracts operations on and layout of leaf nodes for the
157 * num_entries: uint32_t 4b
160 * keys : objaddr_t[204] (204*4)b
161 * values : lext_map_val_t[204] (204*16)b
164 constexpr size_t LEAF_NODE_CAPACITY
=
165 (EXTMAP_BLOCK_SIZE
- sizeof(uint32_t) - sizeof(extmap_node_meta_t
))
166 / (sizeof(objaddr_t
) + sizeof(lext_map_val_t
));
168 struct lext_map_val_le_t
{
170 extent_len_le_t length
= init_extent_len_le_t(0);
172 lext_map_val_le_t() = default;
173 lext_map_val_le_t(const lext_map_val_le_t
&) = default;
174 explicit lext_map_val_le_t(const lext_map_val_t
&val
)
175 : laddr(laddr_le_t(val
.laddr
)),
176 length(init_extent_len_le_t(val
.length
)) {}
178 operator lext_map_val_t() const {
179 return lext_map_val_t
{laddr
, length
};
183 struct ExtMapLeafNode
185 common::FixedKVNodeLayout
<
187 extmap_node_meta_t
, extmap_node_meta_le_t
,
188 objaddr_t
, ceph_le32
,
189 lext_map_val_t
, lext_map_val_le_t
> {
190 using internal_iterator_t
= const_iterator
;
191 template <typename
... T
>
192 ExtMapLeafNode(T
&&... t
) :
193 ExtMapNode(std::forward
<T
>(t
)...),
194 FixedKVNodeLayout(get_bptr().c_str()) {}
196 static constexpr extent_types_t type
= extent_types_t::EXTMAP_LEAF
;
198 extmap_node_meta_t
get_node_meta() const final
{ return get_meta(); }
200 CachedExtentRef
duplicate_for_write() final
{
201 assert(delta_buffer
.empty());
202 return CachedExtentRef(new ExtMapLeafNode(*this));
205 delta_buffer_t delta_buffer
;
206 delta_buffer_t
*maybe_get_delta_buffer() {
207 return is_mutation_pending() ? &delta_buffer
: nullptr;
210 find_lextent_ret
find_lextent(ext_context_t ec
, objaddr_t lo
, extent_len_t len
) final
;
212 insert_ret
insert(ext_context_t ec
, objaddr_t lo
, lext_map_val_t val
) final
;
214 rm_lextent_ret
rm_lextent(ext_context_t ec
, objaddr_t lo
, lext_map_val_t val
) final
;
216 split_children_ret
make_split_children(ext_context_t ec
) final
;
218 full_merge_ret
make_full_merge(ext_context_t ec
, ExtMapNodeRef right
) final
;
220 make_balanced_ret
make_balanced(ext_context_t ec
, ExtMapNodeRef _right
, bool prefer_left
) final
;
222 extent_types_t
get_type() const final
{
226 ceph::bufferlist
get_delta() final
{
227 assert(!delta_buffer
.empty());
228 ceph::buffer::ptr
bptr(delta_buffer
.get_bytes());
229 delta_buffer
.copy_out(bptr
.c_str(), bptr
.length());
235 void apply_delta(const ceph::bufferlist
&_bl
) final
{
236 assert(_bl
.length());
237 ceph::bufferlist bl
= _bl
;
239 delta_buffer_t buffer
;
240 buffer
.copy_in(bl
.front().c_str(), bl
.front().length());
241 buffer
.replay(*this);
244 std::ostream
&print_detail_l(std::ostream
&out
) const final
;
246 bool at_max_capacity() const final
{
247 return get_size() == get_capacity();
250 bool at_min_capacity() const final
{
251 return get_size() == get_capacity() / 2;
254 unsigned get_node_size() const {
258 /* get the iterator containing [l, r]
260 std::pair
<internal_iterator_t
, internal_iterator_t
> bound(
261 objaddr_t l
, objaddr_t r
) {
263 for (; retl
!= end(); ++retl
) {
264 if (retl
->get_key() >= l
|| (retl
->get_key() + retl
->get_val().length
) > l
)
268 for (; retr
!= end(); ++retr
) {
269 if (retr
->get_key() >= r
)
275 std::pair
<internal_iterator_t
, internal_iterator_t
>
276 get_leaf_entries(objaddr_t lo
, extent_len_t len
);
279 using ExtentMapLeafNodeRef
= TCachedExtentRef
<ExtMapLeafNode
>;