1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
8 #include <boost/intrusive_ptr.hpp>
9 #include <boost/smart_ptr/intrusive_ref_counter.hpp>
10 #include <seastar/core/future.hh>
12 #include "include/ceph_assert.h"
13 #include "include/buffer_fwd.h"
14 #include "include/interval_set.h"
15 #include "common/interval_map.h"
16 #include "crimson/osd/exceptions.h"
18 #include "crimson/os/seastore/seastore_types.h"
19 #include "crimson/os/seastore/lba_manager.h"
20 #include "crimson/os/seastore/cache.h"
21 #include "crimson/os/seastore/segment_manager.h"
23 #include "crimson/os/seastore/lba_manager/btree/lba_btree_node.h"
24 #include "crimson/os/seastore/lba_manager/btree/lba_btree.h"
26 namespace crimson::os::seastore::lba_manager::btree
{
31 * Uses a wandering btree to track two things:
32 * 1) lba state including laddr_t -> paddr_t mapping
33 * 2) reverse paddr_t -> laddr_t mapping for gc (TODO)
35 * Generally, any transaction will involve
36 * 1) deltas against lba tree nodes
37 * 2) new lba tree nodes
38 * - Note, there must necessarily be a delta linking
39 * these new nodes into the tree -- might be a
40 * bootstrap_state_t delta if new root
42 * get_mappings, alloc_extent_*, etc populate a Transaction
43 * which then gets submitted
45 class BtreeLBAManager
: public LBAManager
{
48 SegmentManager
&segment_manager
,
52 Transaction
&t
) final
;
54 get_mappings_ret
get_mappings(
56 laddr_t offset
, extent_len_t length
) final
;
58 get_mappings_ret
get_mappings(
60 laddr_list_t
&&list
) final
;
62 get_mapping_ret
get_mapping(
64 laddr_t offset
) final
;
66 alloc_extent_ret
alloc_extent(
72 ref_ret
decref_extent(
75 return update_refcount(t
, addr
, -1);
78 ref_ret
incref_extent(
81 return update_refcount(t
, addr
, 1);
84 void complete_transaction(
85 Transaction
&t
) final
;
87 init_cached_extent_ret
init_cached_extent(
89 CachedExtentRef e
) final
;
91 scan_mappings_ret
scan_mappings(
95 scan_mappings_func_t
&&f
) final
;
97 scan_mapped_space_ret
scan_mapped_space(
99 scan_mapped_space_func_t
&&f
) final
;
101 rewrite_extent_ret
rewrite_extent(
103 CachedExtentRef extent
) final
;
105 update_le_mapping_ret
update_mapping(
109 paddr_t paddr
) final
;
111 get_physical_extent_if_live_ret
get_physical_extent_if_live(
116 segment_off_t len
) final
;
118 void add_pin(LBAPin
&pin
) final
{
119 auto *bpin
= reinterpret_cast<BtreeLBAPin
*>(&pin
);
120 pin_set
.add_pin(bpin
->pin
);
121 bpin
->parent
= nullptr;
126 SegmentManager
&segment_manager
;
129 btree_pin_set_t pin_set
;
131 op_context_t
get_context(Transaction
&t
) {
132 return op_context_t
{cache
, t
, &pin_set
};
135 static btree_range_pin_t
&get_pin(CachedExtent
&e
);
137 seastar::metrics::metric_group metrics
;
138 void register_metrics();
139 template <typename F
, typename
... Args
>
143 return cache
.get_root(
145 ).si_then([this, c
, f
=std::forward
<F
>(f
)](RootBlockRef croot
) mutable {
146 return seastar::do_with(
147 LBABtree(croot
->get_root().lba_root
),
148 [this, c
, croot
, f
=std::move(f
)](auto &btree
) mutable {
151 ).si_then([this, c
, croot
, &btree
] {
152 if (btree
.is_root_dirty()) {
153 auto mut_croot
= cache
.duplicate_for_write(
155 )->cast
<RootBlock
>();
156 mut_croot
->get_root().lba_root
= btree
.get_root_undirty();
158 return base_iertr::now();
164 template <typename State
, typename F
>
165 auto with_btree_state(
169 return seastar::do_with(
170 std::forward
<State
>(init
),
171 [this, c
, f
=std::forward
<F
>(f
)](auto &state
) mutable {
172 (void)this; // silence incorrect clang warning about capture
173 return with_btree(c
, [&state
, f
=std::move(f
)](auto &btree
) mutable {
174 return f(btree
, state
);
175 }).si_then([&state
] {
176 return seastar::make_ready_future
<State
>(std::move(state
));
181 template <typename State
, typename F
>
182 auto with_btree_state(
185 return with_btree_state
<State
, F
>(c
, State
{}, std::forward
<F
>(f
));
188 template <typename Ret
, typename F
>
192 return with_btree_state
<Ret
>(
194 [f
=std::forward
<F
>(f
)](auto &btree
, auto &ret
) mutable {
197 ).si_then([&ret
](auto &&_ret
) {
198 ret
= std::move(_ret
);
206 * Updates refcount, returns resulting refcount
208 using update_refcount_ret
= ref_ret
;
209 update_refcount_ret
update_refcount(
217 * Updates mapping, removes if f returns nullopt
219 using update_mapping_iertr
= ref_iertr
;
220 using update_mapping_ret
= ref_iertr::future
<lba_map_val_t
>;
221 using update_func_t
= std::function
<
222 lba_map_val_t(const lba_map_val_t
&v
)
224 update_mapping_ret
update_mapping(
229 using BtreeLBAManagerRef
= std::unique_ptr
<BtreeLBAManager
>;