Skip to content

Commit 3250b54

Browse files
authored
Merge pull request ceph#58367 from xxhdx1985126/wip-seastore-lba-mapping-iterator
crimson/os/seastore/cached_extent: add the "refresh" ability to lba mappings Reviewed-by: Yingxin Cheng <[email protected]>
2 parents 15722b8 + 98f2da0 commit 3250b54

File tree

14 files changed

+230
-66
lines changed

14 files changed

+230
-66
lines changed

src/crimson/os/seastore/btree/btree_range_pin.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ get_child_ret_t<LogicalCachedExtent>
1111
BtreeNodeMapping<key_t, val_t>::get_logical_extent(
1212
Transaction &t)
1313
{
14-
ceph_assert(is_parent_valid());
14+
ceph_assert(is_parent_viewable());
1515
assert(pos != std::numeric_limits<uint16_t>::max());
1616
ceph_assert(t.get_trans_id() == ctx.trans.get_trans_id());
1717
auto &p = (FixedKVNode<key_t>&)*parent;

src/crimson/os/seastore/btree/btree_range_pin.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,13 +218,17 @@ class BtreeNodeMapping : public PhysicalNodeMapping<key_t, val_t> {
218218
get_child_ret_t<LogicalCachedExtent> get_logical_extent(Transaction&) final;
219219
bool is_stable() const final;
220220
bool is_data_stable() const final;
221-
bool is_parent_valid() const final {
221+
bool is_parent_viewable() const final {
222222
ceph_assert(parent);
223223
if (!parent->is_valid()) {
224224
return false;
225225
}
226226
return !is_unviewable_by_trans(*parent, ctx.trans);
227227
}
228+
bool is_parent_valid() const final {
229+
ceph_assert(parent);
230+
return parent->is_valid();
231+
}
228232
};
229233

230234
}

src/crimson/os/seastore/btree/fixed_kv_btree.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,7 +1047,7 @@ class FixedKVBtree {
10471047
fixed_kv_extent.get_user_hint(),
10481048
// get target rewrite generation
10491049
fixed_kv_extent.get_rewrite_generation());
1050-
n_fixed_kv_extent->rewrite(fixed_kv_extent, 0);
1050+
n_fixed_kv_extent->rewrite(c.trans, fixed_kv_extent, 0);
10511051

10521052
SUBTRACET(
10531053
seastore_fixedkv_tree,
@@ -1068,7 +1068,6 @@ class FixedKVBtree {
10681068
});
10691069
};
10701070

1071-
CachedExtentRef n_fixed_kv_extent;
10721071
if (e->get_type() == internal_node_t::TYPE) {
10731072
auto lint = e->cast<internal_node_t>();
10741073
return do_rewrite(*lint);

src/crimson/os/seastore/btree/fixed_kv_node.h

Lines changed: 139 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ struct FixedKVNode : ChildableCachedExtent {
3232
using FixedKVNodeRef = TCachedExtentRef<FixedKVNode>;
3333
fixed_kv_node_meta_t<node_key_t> range;
3434

35-
struct copy_source_cmp_t {
35+
struct fixedkv_node_cmp_t {
3636
using is_transparent = node_key_t;
3737
bool operator()(const FixedKVNodeRef &l, const FixedKVNodeRef &r) const {
3838
assert(l->range.end <= r->range.begin
@@ -84,11 +84,78 @@ struct FixedKVNode : ChildableCachedExtent {
8484
* cannot be rewritten) because their parents must be mutated upon remapping.
8585
*/
8686
std::vector<ChildableCachedExtent*> children;
87-
std::set<FixedKVNodeRef, copy_source_cmp_t> copy_sources;
87+
std::set<FixedKVNodeRef, fixedkv_node_cmp_t> copy_sources;
8888
uint16_t capacity = 0;
8989
parent_tracker_t* my_tracker = nullptr;
9090
RootBlockRef root_block;
9191

92+
// copy dests points from a stable node back to its pending nodes
93+
// having copy sources at the same tree level, it serves as a two-level index:
94+
// transaction-id then node-key to the pending node.
95+
//
96+
// The copy dest pointers must be symmetric to the copy source pointers.
97+
//
98+
// copy_dests_t will be automatically unregisterred upon transaction destruction,
99+
// see Transaction::views
100+
struct copy_dests_t : trans_spec_view_t {
101+
std::set<FixedKVNodeRef, fixedkv_node_cmp_t> dests_by_key;
102+
copy_dests_t(Transaction &t) : trans_spec_view_t{t.get_trans_id()} {}
103+
~copy_dests_t() {
104+
LOG_PREFIX(~copy_dests_t);
105+
SUBTRACE(seastore_fixedkv_tree, "copy_dests_t destroyed");
106+
}
107+
};
108+
109+
trans_view_set_t copy_dests_by_trans;
110+
111+
void add_copy_dest(Transaction &t, FixedKVNodeRef dest) {
112+
ceph_assert(is_stable());
113+
ceph_assert(dest->is_pending());
114+
auto tid = t.get_trans_id();
115+
auto iter = copy_dests_by_trans.lower_bound(
116+
tid, trans_spec_view_t::cmp_t());
117+
if (iter == copy_dests_by_trans.end() ||
118+
iter->pending_for_transaction != tid) {
119+
iter = copy_dests_by_trans.insert_before(
120+
iter, t.add_transactional_view<copy_dests_t>(t));
121+
}
122+
auto &copy_dests = static_cast<copy_dests_t&>(*iter);
123+
auto [it, inserted] = copy_dests.dests_by_key.insert(dest);
124+
assert(inserted || it->get() == dest.get());
125+
}
126+
127+
void del_copy_dest(Transaction &t, FixedKVNodeRef dest) {
128+
auto iter = copy_dests_by_trans.find(
129+
t.get_trans_id(), trans_spec_view_t::cmp_t());
130+
ceph_assert(iter != copy_dests_by_trans.end());
131+
auto &copy_dests = static_cast<copy_dests_t&>(*iter);
132+
auto it = copy_dests.dests_by_key.find(dest);
133+
ceph_assert(it != copy_dests.dests_by_key.end());
134+
copy_dests.dests_by_key.erase(dest);
135+
}
136+
137+
FixedKVNodeRef find_pending_version(Transaction &t, node_key_t key) {
138+
assert(is_stable());
139+
auto mut_iter = mutation_pendings.find(
140+
t.get_trans_id(), trans_spec_view_t::cmp_t());
141+
if (mut_iter != mutation_pendings.end()) {
142+
assert(copy_dests_by_trans.find(t.get_trans_id()) ==
143+
copy_dests_by_trans.end());
144+
return (FixedKVNode*)(&(*mut_iter));
145+
}
146+
auto iter = copy_dests_by_trans.find(
147+
t.get_trans_id(), trans_spec_view_t::cmp_t());
148+
ceph_assert(iter != copy_dests_by_trans.end());
149+
auto &copy_dests = static_cast<copy_dests_t&>(*iter);
150+
auto it = copy_dests.dests_by_key.lower_bound(key);
151+
if ((*it)->range.begin > key) {
152+
ceph_assert(it != copy_dests.dests_by_key.begin());
153+
--it;
154+
}
155+
ceph_assert((*it)->range.begin <= key && key < (*it)->range.end);
156+
return *it;
157+
}
158+
92159
bool is_linked() {
93160
assert(!has_parent_tracker() || !(bool)root_block);
94161
return (bool)has_parent_tracker() || (bool)root_block;
@@ -161,19 +228,22 @@ struct FixedKVNode : ChildableCachedExtent {
161228

162229
virtual bool have_children() const = 0;
163230

164-
void on_rewrite(CachedExtent &extent, extent_len_t off) final {
231+
void on_rewrite(Transaction &t, CachedExtent &extent, extent_len_t off) final {
165232
assert(get_type() == extent.get_type());
166233
assert(off == 0);
167234
auto &foreign_extent = (FixedKVNode&)extent;
168235
range = get_node_meta();
169236

170237
if (have_children()) {
171238
if (!foreign_extent.is_pending()) {
239+
foreign_extent.add_copy_dest(t, this);
172240
copy_sources.emplace(&foreign_extent);
173241
} else {
174242
ceph_assert(foreign_extent.is_mutation_pending());
175-
copy_sources.emplace(
176-
foreign_extent.get_prior_instance()->template cast<FixedKVNode>());
243+
auto copy_source =
244+
foreign_extent.get_prior_instance()->template cast<FixedKVNode>();
245+
copy_source->add_copy_dest(t, this);
246+
copy_sources.emplace(copy_source);
177247
children = std::move(foreign_extent.children);
178248
adjust_ptracker_for_children();
179249
}
@@ -211,17 +281,24 @@ struct FixedKVNode : ChildableCachedExtent {
211281
}
212282

213283
static void push_copy_sources(
284+
Transaction &t,
214285
FixedKVNode &dest,
215286
FixedKVNode &src)
216287
{
217288
ceph_assert(dest.is_initial_pending());
218289
if (!src.is_pending()) {
290+
src.add_copy_dest(t, &dest);
219291
dest.copy_sources.emplace(&src);
220292
} else if (src.is_mutation_pending()) {
221-
dest.copy_sources.emplace(
222-
src.get_prior_instance()->template cast<FixedKVNode>());
293+
auto copy_src =
294+
src.get_prior_instance()->template cast<FixedKVNode>();
295+
copy_src->add_copy_dest(t, &dest);
296+
dest.copy_sources.emplace(copy_src);
223297
} else {
224298
ceph_assert(src.is_initial_pending());
299+
for (auto &cs : src.copy_sources) {
300+
cs->add_copy_dest(t, &dest);
301+
}
225302
dest.copy_sources.insert(
226303
src.copy_sources.begin(),
227304
src.copy_sources.end());
@@ -306,13 +383,20 @@ struct FixedKVNode : ChildableCachedExtent {
306383
}
307384

308385
void split_child_ptrs(
386+
Transaction &t,
309387
FixedKVNode &left,
310388
FixedKVNode &right)
311389
{
312390
assert(!left.my_tracker);
313391
assert(!right.my_tracker);
314-
push_copy_sources(left, *this);
315-
push_copy_sources(right, *this);
392+
if (is_initial_pending()) {
393+
for (auto &cs : copy_sources) {
394+
cs->del_copy_dest(t, this);
395+
}
396+
}
397+
398+
push_copy_sources(t, left, *this);
399+
push_copy_sources(t, right, *this);
316400
if (is_pending()) {
317401
uint16_t pivot = get_node_split_pivot();
318402
move_child_ptrs(left, *this, 0, 0, pivot);
@@ -322,12 +406,24 @@ struct FixedKVNode : ChildableCachedExtent {
322406
}
323407

324408
void merge_child_ptrs(
409+
Transaction &t,
325410
FixedKVNode &left,
326411
FixedKVNode &right)
327412
{
328413
ceph_assert(!my_tracker);
329-
push_copy_sources(*this, left);
330-
push_copy_sources(*this, right);
414+
415+
if (left.is_initial_pending()) {
416+
for (auto &cs : left.copy_sources) {
417+
cs->del_copy_dest(t, &left);
418+
}
419+
}
420+
if (right.is_initial_pending()) {
421+
for (auto &cs : right.copy_sources) {
422+
cs->del_copy_dest(t, &right);
423+
}
424+
}
425+
push_copy_sources(t, *this, left);
426+
push_copy_sources(t, *this, right);
331427

332428
if (left.is_pending()) {
333429
move_child_ptrs(*this, left, 0, 0, left.get_node_size());
@@ -341,6 +437,7 @@ struct FixedKVNode : ChildableCachedExtent {
341437
}
342438

343439
static void balance_child_ptrs(
440+
Transaction &t,
344441
FixedKVNode &left,
345442
FixedKVNode &right,
346443
bool prefer_left,
@@ -355,35 +452,46 @@ struct FixedKVNode : ChildableCachedExtent {
355452
pivot_idx++;
356453
}
357454

455+
if (left.is_initial_pending()) {
456+
for (auto &cs : left.copy_sources) {
457+
cs->del_copy_dest(t, &left);
458+
}
459+
}
460+
if (right.is_initial_pending()) {
461+
for (auto &cs : right.copy_sources) {
462+
cs->del_copy_dest(t, &right);
463+
}
464+
}
465+
358466
assert(!replacement_left.my_tracker);
359467
assert(!replacement_right.my_tracker);
360468
if (pivot_idx < l_size) {
361469
// deal with left
362-
push_copy_sources(replacement_left, left);
363-
push_copy_sources(replacement_right, left);
470+
push_copy_sources(t, replacement_left, left);
471+
push_copy_sources(t, replacement_right, left);
364472
if (left.is_pending()) {
365473
move_child_ptrs(replacement_left, left, 0, 0, pivot_idx);
366474
move_child_ptrs(replacement_right, left, 0, pivot_idx, l_size);
367475
left.my_tracker = nullptr;
368476
}
369477

370478
// deal with right
371-
push_copy_sources(replacement_right, right);
479+
push_copy_sources(t, replacement_right, right);
372480
if (right.is_pending()) {
373481
move_child_ptrs(replacement_right, right, l_size - pivot_idx, 0, r_size);
374482
right.my_tracker= nullptr;
375483
}
376484
} else {
377485
// deal with left
378-
push_copy_sources(replacement_left, left);
486+
push_copy_sources(t, replacement_left, left);
379487
if (left.is_pending()) {
380488
move_child_ptrs(replacement_left, left, 0, 0, l_size);
381489
left.my_tracker = nullptr;
382490
}
383491

384492
// deal with right
385-
push_copy_sources(replacement_left, right);
386-
push_copy_sources(replacement_right, right);
493+
push_copy_sources(t, replacement_left, right);
494+
push_copy_sources(t, replacement_right, right);
387495
if (right.is_pending()) {
388496
move_child_ptrs(replacement_left, right, l_size, 0, pivot_idx - l_size);
389497
move_child_ptrs(replacement_right, right, 0, pivot_idx - l_size, r_size);
@@ -821,10 +929,10 @@ struct FixedKVInternalNode
821929
c.trans, node_size, placement_hint_t::HOT, INIT_GENERATION);
822930
auto right = c.cache.template alloc_new_non_data_extent<node_type_t>(
823931
c.trans, node_size, placement_hint_t::HOT, INIT_GENERATION);
824-
this->split_child_ptrs(*left, *right);
825932
auto pivot = this->split_into(*left, *right);
826933
left->range = left->get_meta();
827934
right->range = right->get_meta();
935+
this->split_child_ptrs(c.trans, *left, *right);
828936
return std::make_tuple(
829937
left,
830938
right,
@@ -836,9 +944,9 @@ struct FixedKVInternalNode
836944
Ref &right) {
837945
auto replacement = c.cache.template alloc_new_non_data_extent<node_type_t>(
838946
c.trans, node_size, placement_hint_t::HOT, INIT_GENERATION);
839-
replacement->merge_child_ptrs(*this, *right);
840947
replacement->merge_from(*this, *right->template cast<node_type_t>());
841948
replacement->range = replacement->get_meta();
949+
replacement->merge_child_ptrs(c.trans, *this, *right);
842950
return replacement;
843951
}
844952

@@ -860,15 +968,15 @@ struct FixedKVInternalNode
860968
prefer_left,
861969
*replacement_left,
862970
*replacement_right);
971+
replacement_left->range = replacement_left->get_meta();
972+
replacement_right->range = replacement_right->get_meta();
863973
this->balance_child_ptrs(
974+
c.trans,
864975
*this,
865976
right,
866977
prefer_left,
867978
*replacement_left,
868979
*replacement_right);
869-
870-
replacement_left->range = replacement_left->get_meta();
871-
replacement_right->range = replacement_right->get_meta();
872980
return std::make_tuple(
873981
replacement_left,
874982
replacement_right,
@@ -1231,12 +1339,12 @@ struct FixedKVLeafNode
12311339
c.trans, node_size, placement_hint_t::HOT, INIT_GENERATION);
12321340
auto right = c.cache.template alloc_new_non_data_extent<node_type_t>(
12331341
c.trans, node_size, placement_hint_t::HOT, INIT_GENERATION);
1234-
if constexpr (has_children) {
1235-
this->split_child_ptrs(*left, *right);
1236-
}
12371342
auto pivot = this->split_into(*left, *right);
12381343
left->range = left->get_meta();
12391344
right->range = right->get_meta();
1345+
if constexpr (has_children) {
1346+
this->split_child_ptrs(c.trans, *left, *right);
1347+
}
12401348
return std::make_tuple(
12411349
left,
12421350
right,
@@ -1248,11 +1356,11 @@ struct FixedKVLeafNode
12481356
Ref &right) {
12491357
auto replacement = c.cache.template alloc_new_non_data_extent<node_type_t>(
12501358
c.trans, node_size, placement_hint_t::HOT, INIT_GENERATION);
1251-
if constexpr (has_children) {
1252-
replacement->merge_child_ptrs(*this, *right);
1253-
}
12541359
replacement->merge_from(*this, *right->template cast<node_type_t>());
12551360
replacement->range = replacement->get_meta();
1361+
if constexpr (has_children) {
1362+
replacement->merge_child_ptrs(c.trans, *this, *right);
1363+
}
12561364
return replacement;
12571365
}
12581366

@@ -1274,17 +1382,17 @@ struct FixedKVLeafNode
12741382
prefer_left,
12751383
*replacement_left,
12761384
*replacement_right);
1385+
replacement_left->range = replacement_left->get_meta();
1386+
replacement_right->range = replacement_right->get_meta();
12771387
if constexpr (has_children) {
12781388
this->balance_child_ptrs(
1389+
c.trans,
12791390
*this,
12801391
right,
12811392
prefer_left,
12821393
*replacement_left,
12831394
*replacement_right);
12841395
}
1285-
1286-
replacement_left->range = replacement_left->get_meta();
1287-
replacement_right->range = replacement_right->get_meta();
12881396
return std::make_tuple(
12891397
replacement_left,
12901398
replacement_right,

0 commit comments

Comments
 (0)