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/btree/fixed_kv_btree.h"
19 #include "crimson/os/seastore/seastore_types.h"
20 #include "crimson/os/seastore/lba_manager.h"
21 #include "crimson/os/seastore/cache.h"
23 #include "crimson/os/seastore/lba_manager/btree/lba_btree_node.h"
24 #include "crimson/os/seastore/btree/btree_range_pin.h"
26 namespace crimson::os::seastore::lba_manager::btree
{
28 class BtreeLBAMapping
: public BtreeNodeMapping
<laddr_t
, paddr_t
> {
29 // To support cloning, there are two kinds of lba mappings:
30 // 1. physical lba mapping: the pladdr in the value of which is the paddr of
31 // the corresponding extent;
32 // 2. indirect lba mapping: the pladdr in the value of which is an laddr pointing
33 // to the physical lba mapping that's pointing to the actual paddr of the
34 // extent being searched;
36 // Accordingly, BtreeLBAMapping may also work under two modes: indirect or direct
37 // 1. BtreeLBAMappings that come from quering an indirect lba mapping in the lba tree
39 // 2. BtreeLBAMappings that come from quering a physical lba mapping in the lba tree
42 // For direct BtreeLBAMappings, there are two important fields:
43 // 1. key: the laddr of the lba mapping being queried;
44 // 2. paddr: the paddr recorded in the value of the lba mapping being queried.
45 // For indirect BtreeLBAMappings, BtreeLBAMapping has three important fields:
46 // 1. key: the laddr key of the lba entry being queried;
47 // 2. intermediate_key: the laddr within the scope of the physical lba mapping
48 // that the current indirect lba mapping points to; although an indirect mapping
49 // points to the start of the physical lba mapping, it may change to other
51 // 3. intermediate_base: the laddr key of the physical lba mapping, intermediate_key
52 // and intermediate_base should be the same when doing cloning
53 // 4. intermediate_offset: intermediate_key - intermediate_base
54 // 5. paddr: the paddr recorded in the physical lba mapping pointed to by the
55 // indirect lba mapping being queried;
57 // NOTE THAT, for direct BtreeLBAMappings, their intermediate_keys are the same as
60 BtreeLBAMapping(op_context_t
<laddr_t
> ctx
)
61 : BtreeNodeMapping(ctx
) {}
63 op_context_t
<laddr_t
> c
,
64 CachedExtentRef parent
,
72 val
.pladdr
.is_paddr() ? val
.pladdr
.get_paddr() : P_ADDR_NULL
,
76 indirect(val
.pladdr
.is_laddr() ? true : false),
77 intermediate_key(indirect
? val
.pladdr
.get_laddr() : L_ADDR_NULL
),
78 intermediate_length(indirect
? val
.len
: 0),
83 lba_map_val_t
get_map_val() const {
87 bool is_indirect() const final
{
91 void set_key_for_indirect(
94 laddr_t interkey
= L_ADDR_NULL
)
96 turn_indirect(interkey
);
98 intermediate_length
= len
;
102 laddr_t
get_key() const final
{
106 pladdr_t
get_raw_val() const {
110 void set_paddr(paddr_t addr
) {
114 laddr_t
get_intermediate_key() const final
{
115 assert(is_indirect());
116 assert(intermediate_key
!= L_ADDR_NULL
);
117 return intermediate_key
;
120 laddr_t
get_intermediate_base() const final
{
121 assert(is_indirect());
122 assert(intermediate_base
!= L_ADDR_NULL
);
123 return intermediate_base
;
126 extent_len_t
get_intermediate_offset() const final
{
127 assert(intermediate_key
>= intermediate_base
);
128 assert((intermediate_key
== L_ADDR_NULL
)
129 == (intermediate_base
== L_ADDR_NULL
));
130 return intermediate_key
- intermediate_base
;
133 extent_len_t
get_intermediate_length() const final
{
134 assert(is_indirect());
135 assert(intermediate_length
);
136 return intermediate_length
;
139 void set_intermediate_base(laddr_t base
) {
140 intermediate_base
= base
;
144 std::unique_ptr
<BtreeNodeMapping
<laddr_t
, paddr_t
>> _duplicate(
145 op_context_t
<laddr_t
> ctx
) const final
{
146 auto pin
= std::unique_ptr
<BtreeLBAMapping
>(new BtreeLBAMapping(ctx
));
148 pin
->intermediate_base
= intermediate_base
;
149 pin
->intermediate_key
= intermediate_key
;
150 pin
->indirect
= indirect
;
151 pin
->raw_val
= raw_val
;
152 pin
->map_val
= map_val
;
156 void turn_indirect(laddr_t interkey
) {
157 assert(value
.is_paddr());
158 intermediate_base
= key
;
159 intermediate_key
= (interkey
== L_ADDR_NULL
? key
: interkey
);
162 laddr_t key
= L_ADDR_NULL
;
163 bool indirect
= false;
164 laddr_t intermediate_key
= L_ADDR_NULL
;
165 laddr_t intermediate_base
= L_ADDR_NULL
;
166 extent_len_t intermediate_length
= 0;
168 lba_map_val_t map_val
;
171 using BtreeLBAMappingRef
= std::unique_ptr
<BtreeLBAMapping
>;
173 using LBABtree
= FixedKVBtree
<
174 laddr_t
, lba_map_val_t
, LBAInternalNode
,
175 LBALeafNode
, BtreeLBAMapping
, LBA_BLOCK_SIZE
, true>;
180 * Uses a wandering btree to track two things:
181 * 1) lba state including laddr_t -> paddr_t mapping
182 * 2) reverse paddr_t -> laddr_t mapping for gc (TODO)
184 * Generally, any transaction will involve
185 * 1) deltas against lba tree nodes
186 * 2) new lba tree nodes
187 * - Note, there must necessarily be a delta linking
188 * these new nodes into the tree -- might be a
189 * bootstrap_state_t delta if new root
191 * get_mappings, alloc_extent_*, etc populate a Transaction
192 * which then gets submitted
194 class BtreeLBAManager
: public LBAManager
{
196 BtreeLBAManager(Cache
&cache
)
203 Transaction
&t
) final
;
205 get_mappings_ret
get_mappings(
207 laddr_t offset
, extent_len_t length
) final
;
209 get_mappings_ret
get_mappings(
211 laddr_list_t
&&list
) final
;
213 get_mapping_ret
get_mapping(
215 laddr_t offset
) final
;
217 alloc_extent_ret
reserve_region(
222 return _alloc_extent(
232 alloc_extent_ret
clone_extent(
236 laddr_t intermediate_key
,
238 laddr_t intermediate_base
)
240 return _alloc_extent(
250 alloc_extent_ret
alloc_extent(
255 LogicalCachedExtent
&ext
) final
257 return _alloc_extent(
267 ref_ret
decref_extent(
270 bool cascade_remove
) final
{
271 return update_refcount(t
, addr
, -1, cascade_remove
);
274 ref_ret
incref_extent(
276 laddr_t addr
) final
{
277 return update_refcount(t
, addr
, 1, false);
280 ref_ret
incref_extent(
284 ceph_assert(delta
> 0);
285 return update_refcount(t
, addr
, delta
, false);
291 * Checks whether e is live (reachable from lba tree) and drops or initializes
294 * Returns if e is live.
296 init_cached_extent_ret
init_cached_extent(
298 CachedExtentRef e
) final
;
300 check_child_trackers_ret
check_child_trackers(Transaction
&t
) final
;
302 scan_mappings_ret
scan_mappings(
306 scan_mappings_func_t
&&f
) final
;
308 rewrite_extent_ret
rewrite_extent(
310 CachedExtentRef extent
) final
;
312 update_mapping_ret
update_mapping(
317 LogicalCachedExtent
*) final
;
319 get_physical_extent_if_live_ret
get_physical_extent_if_live(
324 extent_len_t len
) final
;
330 uint64_t num_alloc_extents
= 0;
331 uint64_t num_alloc_extents_iter_nexts
= 0;
334 op_context_t
<laddr_t
> get_context(Transaction
&t
) {
335 return op_context_t
<laddr_t
>{cache
, t
};
338 seastar::metrics::metric_group metrics
;
339 void register_metrics();
344 * Updates refcount, returns resulting refcount
346 using update_refcount_ret
= ref_ret
;
347 update_refcount_ret
update_refcount(
351 bool cascade_remove
);
356 * Updates mapping, removes if f returns nullopt
358 using _update_mapping_iertr
= ref_iertr
;
359 using _update_mapping_ret
= ref_iertr::future
<lba_map_val_t
>;
360 using update_func_t
= std::function
<
361 lba_map_val_t(const lba_map_val_t
&v
)
363 _update_mapping_ret
_update_mapping(
367 LogicalCachedExtent
*);
369 alloc_extent_ret
_alloc_extent(
375 laddr_t intermediate_base
,
376 LogicalCachedExtent
*);
378 using _get_mapping_ret
= get_mapping_iertr::future
<BtreeLBAMappingRef
>;
379 _get_mapping_ret
_get_mapping(
383 using _get_original_mappings_ret
= get_mappings_ret
;
384 _get_original_mappings_ret
_get_original_mappings(
385 op_context_t
<laddr_t
> c
,
386 std::list
<BtreeLBAMappingRef
> &pin_list
);
388 ref_iertr::future
<std::optional
<std::pair
<paddr_t
, extent_len_t
>>>
389 _decref_intermediate(
394 using BtreeLBAManagerRef
= std::unique_ptr
<BtreeLBAManager
>;