Skip to content

Commit b87f614

Browse files
committed
crimson/os/seastore/btree: add copy_source->pending links to FixedKVNode
Signed-off-by: Xuehan Xu <[email protected]>
1 parent 5b6f1ee commit b87f614

File tree

7 files changed

+143
-41
lines changed

7 files changed

+143
-41
lines changed

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

Lines changed: 1 addition & 1 deletion
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,

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

Lines changed: 117 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,56 @@ 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+
92137
bool is_linked() {
93138
assert(!has_parent_tracker() || !(bool)root_block);
94139
return (bool)has_parent_tracker() || (bool)root_block;
@@ -161,19 +206,22 @@ struct FixedKVNode : ChildableCachedExtent {
161206

162207
virtual bool have_children() const = 0;
163208

164-
void on_rewrite(CachedExtent &extent, extent_len_t off) final {
209+
void on_rewrite(Transaction &t, CachedExtent &extent, extent_len_t off) final {
165210
assert(get_type() == extent.get_type());
166211
assert(off == 0);
167212
auto &foreign_extent = (FixedKVNode&)extent;
168213
range = get_node_meta();
169214

170215
if (have_children()) {
171216
if (!foreign_extent.is_pending()) {
217+
foreign_extent.add_copy_dest(t, this);
172218
copy_sources.emplace(&foreign_extent);
173219
} else {
174220
ceph_assert(foreign_extent.is_mutation_pending());
175-
copy_sources.emplace(
176-
foreign_extent.get_prior_instance()->template cast<FixedKVNode>());
221+
auto copy_source =
222+
foreign_extent.get_prior_instance()->template cast<FixedKVNode>();
223+
copy_source->add_copy_dest(t, this);
224+
copy_sources.emplace(copy_source);
177225
children = std::move(foreign_extent.children);
178226
adjust_ptracker_for_children();
179227
}
@@ -211,17 +259,24 @@ struct FixedKVNode : ChildableCachedExtent {
211259
}
212260

213261
static void push_copy_sources(
262+
Transaction &t,
214263
FixedKVNode &dest,
215264
FixedKVNode &src)
216265
{
217266
ceph_assert(dest.is_initial_pending());
218267
if (!src.is_pending()) {
268+
src.add_copy_dest(t, &dest);
219269
dest.copy_sources.emplace(&src);
220270
} else if (src.is_mutation_pending()) {
221-
dest.copy_sources.emplace(
222-
src.get_prior_instance()->template cast<FixedKVNode>());
271+
auto copy_src =
272+
src.get_prior_instance()->template cast<FixedKVNode>();
273+
copy_src->add_copy_dest(t, &dest);
274+
dest.copy_sources.emplace(copy_src);
223275
} else {
224276
ceph_assert(src.is_initial_pending());
277+
for (auto &cs : src.copy_sources) {
278+
cs->add_copy_dest(t, &dest);
279+
}
225280
dest.copy_sources.insert(
226281
src.copy_sources.begin(),
227282
src.copy_sources.end());
@@ -306,13 +361,20 @@ struct FixedKVNode : ChildableCachedExtent {
306361
}
307362

308363
void split_child_ptrs(
364+
Transaction &t,
309365
FixedKVNode &left,
310366
FixedKVNode &right)
311367
{
312368
assert(!left.my_tracker);
313369
assert(!right.my_tracker);
314-
push_copy_sources(left, *this);
315-
push_copy_sources(right, *this);
370+
if (is_initial_pending()) {
371+
for (auto &cs : copy_sources) {
372+
cs->del_copy_dest(t, this);
373+
}
374+
}
375+
376+
push_copy_sources(t, left, *this);
377+
push_copy_sources(t, right, *this);
316378
if (is_pending()) {
317379
uint16_t pivot = get_node_split_pivot();
318380
move_child_ptrs(left, *this, 0, 0, pivot);
@@ -322,12 +384,24 @@ struct FixedKVNode : ChildableCachedExtent {
322384
}
323385

324386
void merge_child_ptrs(
387+
Transaction &t,
325388
FixedKVNode &left,
326389
FixedKVNode &right)
327390
{
328391
ceph_assert(!my_tracker);
329-
push_copy_sources(*this, left);
330-
push_copy_sources(*this, right);
392+
393+
if (left.is_initial_pending()) {
394+
for (auto &cs : left.copy_sources) {
395+
cs->del_copy_dest(t, &left);
396+
}
397+
}
398+
if (right.is_initial_pending()) {
399+
for (auto &cs : right.copy_sources) {
400+
cs->del_copy_dest(t, &right);
401+
}
402+
}
403+
push_copy_sources(t, *this, left);
404+
push_copy_sources(t, *this, right);
331405

332406
if (left.is_pending()) {
333407
move_child_ptrs(*this, left, 0, 0, left.get_node_size());
@@ -341,6 +415,7 @@ struct FixedKVNode : ChildableCachedExtent {
341415
}
342416

343417
static void balance_child_ptrs(
418+
Transaction &t,
344419
FixedKVNode &left,
345420
FixedKVNode &right,
346421
bool prefer_left,
@@ -355,35 +430,46 @@ struct FixedKVNode : ChildableCachedExtent {
355430
pivot_idx++;
356431
}
357432

433+
if (left.is_initial_pending()) {
434+
for (auto &cs : left.copy_sources) {
435+
cs->del_copy_dest(t, &left);
436+
}
437+
}
438+
if (right.is_initial_pending()) {
439+
for (auto &cs : right.copy_sources) {
440+
cs->del_copy_dest(t, &right);
441+
}
442+
}
443+
358444
assert(!replacement_left.my_tracker);
359445
assert(!replacement_right.my_tracker);
360446
if (pivot_idx < l_size) {
361447
// deal with left
362-
push_copy_sources(replacement_left, left);
363-
push_copy_sources(replacement_right, left);
448+
push_copy_sources(t, replacement_left, left);
449+
push_copy_sources(t, replacement_right, left);
364450
if (left.is_pending()) {
365451
move_child_ptrs(replacement_left, left, 0, 0, pivot_idx);
366452
move_child_ptrs(replacement_right, left, 0, pivot_idx, l_size);
367453
left.my_tracker = nullptr;
368454
}
369455

370456
// deal with right
371-
push_copy_sources(replacement_right, right);
457+
push_copy_sources(t, replacement_right, right);
372458
if (right.is_pending()) {
373459
move_child_ptrs(replacement_right, right, l_size - pivot_idx, 0, r_size);
374460
right.my_tracker= nullptr;
375461
}
376462
} else {
377463
// deal with left
378-
push_copy_sources(replacement_left, left);
464+
push_copy_sources(t, replacement_left, left);
379465
if (left.is_pending()) {
380466
move_child_ptrs(replacement_left, left, 0, 0, l_size);
381467
left.my_tracker = nullptr;
382468
}
383469

384470
// deal with right
385-
push_copy_sources(replacement_left, right);
386-
push_copy_sources(replacement_right, right);
471+
push_copy_sources(t, replacement_left, right);
472+
push_copy_sources(t, replacement_right, right);
387473
if (right.is_pending()) {
388474
move_child_ptrs(replacement_left, right, l_size, 0, pivot_idx - l_size);
389475
move_child_ptrs(replacement_right, right, 0, pivot_idx - l_size, r_size);
@@ -821,10 +907,10 @@ struct FixedKVInternalNode
821907
c.trans, node_size, placement_hint_t::HOT, INIT_GENERATION);
822908
auto right = c.cache.template alloc_new_non_data_extent<node_type_t>(
823909
c.trans, node_size, placement_hint_t::HOT, INIT_GENERATION);
824-
this->split_child_ptrs(*left, *right);
825910
auto pivot = this->split_into(*left, *right);
826911
left->range = left->get_meta();
827912
right->range = right->get_meta();
913+
this->split_child_ptrs(c.trans, *left, *right);
828914
return std::make_tuple(
829915
left,
830916
right,
@@ -836,9 +922,9 @@ struct FixedKVInternalNode
836922
Ref &right) {
837923
auto replacement = c.cache.template alloc_new_non_data_extent<node_type_t>(
838924
c.trans, node_size, placement_hint_t::HOT, INIT_GENERATION);
839-
replacement->merge_child_ptrs(*this, *right);
840925
replacement->merge_from(*this, *right->template cast<node_type_t>());
841926
replacement->range = replacement->get_meta();
927+
replacement->merge_child_ptrs(c.trans, *this, *right);
842928
return replacement;
843929
}
844930

@@ -860,15 +946,15 @@ struct FixedKVInternalNode
860946
prefer_left,
861947
*replacement_left,
862948
*replacement_right);
949+
replacement_left->range = replacement_left->get_meta();
950+
replacement_right->range = replacement_right->get_meta();
863951
this->balance_child_ptrs(
952+
c.trans,
864953
*this,
865954
right,
866955
prefer_left,
867956
*replacement_left,
868957
*replacement_right);
869-
870-
replacement_left->range = replacement_left->get_meta();
871-
replacement_right->range = replacement_right->get_meta();
872958
return std::make_tuple(
873959
replacement_left,
874960
replacement_right,
@@ -1231,12 +1317,12 @@ struct FixedKVLeafNode
12311317
c.trans, node_size, placement_hint_t::HOT, INIT_GENERATION);
12321318
auto right = c.cache.template alloc_new_non_data_extent<node_type_t>(
12331319
c.trans, node_size, placement_hint_t::HOT, INIT_GENERATION);
1234-
if constexpr (has_children) {
1235-
this->split_child_ptrs(*left, *right);
1236-
}
12371320
auto pivot = this->split_into(*left, *right);
12381321
left->range = left->get_meta();
12391322
right->range = right->get_meta();
1323+
if constexpr (has_children) {
1324+
this->split_child_ptrs(c.trans, *left, *right);
1325+
}
12401326
return std::make_tuple(
12411327
left,
12421328
right,
@@ -1248,11 +1334,11 @@ struct FixedKVLeafNode
12481334
Ref &right) {
12491335
auto replacement = c.cache.template alloc_new_non_data_extent<node_type_t>(
12501336
c.trans, node_size, placement_hint_t::HOT, INIT_GENERATION);
1251-
if constexpr (has_children) {
1252-
replacement->merge_child_ptrs(*this, *right);
1253-
}
12541337
replacement->merge_from(*this, *right->template cast<node_type_t>());
12551338
replacement->range = replacement->get_meta();
1339+
if constexpr (has_children) {
1340+
replacement->merge_child_ptrs(c.trans, *this, *right);
1341+
}
12561342
return replacement;
12571343
}
12581344

@@ -1274,17 +1360,17 @@ struct FixedKVLeafNode
12741360
prefer_left,
12751361
*replacement_left,
12761362
*replacement_right);
1363+
replacement_left->range = replacement_left->get_meta();
1364+
replacement_right->range = replacement_right->get_meta();
12771365
if constexpr (has_children) {
12781366
this->balance_child_ptrs(
1367+
c.trans,
12791368
*this,
12801369
right,
12811370
prefer_left,
12821371
*replacement_left,
12831372
*replacement_right);
12841373
}
1285-
1286-
replacement_left->range = replacement_left->get_meta();
1287-
replacement_right->range = replacement_right->get_meta();
12881374
return std::make_tuple(
12891375
replacement_left,
12901376
replacement_right,

src/crimson/os/seastore/cached_extent.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,9 @@ struct trans_spec_view_t {
112112
// if the extent is pending, contains the id of the owning transaction;
113113
// TRANS_ID_NULL otherwise
114114
transaction_id_t pending_for_transaction = TRANS_ID_NULL;
115+
trans_spec_view_t() = default;
116+
trans_spec_view_t(transaction_id_t id) : pending_for_transaction(id) {}
117+
virtual ~trans_spec_view_t() = default;
115118

116119
struct cmp_t {
117120
bool operator()(
@@ -307,7 +310,7 @@ class CachedExtent
307310
return true;
308311
}
309312

310-
void rewrite(CachedExtent &e, extent_len_t o) {
313+
void rewrite(Transaction &t, CachedExtent &e, extent_len_t o) {
311314
assert(is_initial_pending());
312315
if (!e.is_pending()) {
313316
prior_instance = &e;
@@ -321,7 +324,7 @@ class CachedExtent
321324
get_bptr().c_str());
322325
set_modify_time(e.get_modify_time());
323326
set_last_committed_crc(e.get_last_committed_crc());
324-
on_rewrite(e, o);
327+
on_rewrite(t, e, o);
325328
}
326329

327330
/**
@@ -330,7 +333,7 @@ class CachedExtent
330333
* Called when this extent is rewriting another one.
331334
*
332335
*/
333-
virtual void on_rewrite(CachedExtent &, extent_len_t) = 0;
336+
virtual void on_rewrite(Transaction &, CachedExtent &, extent_len_t) = 0;
334337

335338
friend std::ostream &operator<<(std::ostream &, extent_state_t);
336339
virtual std::ostream &print_detail(std::ostream &out) const { return out; }
@@ -1221,7 +1224,7 @@ class RetiredExtentPlaceholder : public CachedExtent {
12211224
return false;
12221225
}
12231226

1224-
void on_rewrite(CachedExtent&, extent_len_t) final {}
1227+
void on_rewrite(Transaction &, CachedExtent&, extent_len_t) final {}
12251228

12261229
std::ostream &print_detail(std::ostream &out) const final {
12271230
return out << ", RetiredExtentPlaceholder";
@@ -1308,7 +1311,7 @@ class LogicalCachedExtent : public ChildableCachedExtent {
13081311
: ChildableCachedExtent(std::forward<T>(t)...)
13091312
{}
13101313

1311-
void on_rewrite(CachedExtent &extent, extent_len_t off) final {
1314+
void on_rewrite(Transaction&, CachedExtent &extent, extent_len_t off) final {
13121315
assert(get_type() == extent.get_type());
13131316
auto &lextent = (LogicalCachedExtent&)extent;
13141317
set_laddr(lextent.get_laddr() + off);

src/crimson/os/seastore/root_block.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ struct RootBlock : CachedExtent {
5050
backref_root_node(nullptr)
5151
{}
5252

53-
void on_rewrite(CachedExtent&, extent_len_t) final {}
53+
void on_rewrite(Transaction&, CachedExtent&, extent_len_t) final {}
5454

5555
CachedExtentRef duplicate_for_write(Transaction&) final {
5656
return CachedExtentRef(new RootBlock(*this));

0 commit comments

Comments
 (0)