Skip to content

Commit 4328521

Browse files
committed
crimson/os/seastore/transaction: add interfaces for seperated Transaction::do_add_to_read_set()
The current implementation of Transaction::do_add_to_read_set() can be seperated into two steps: 1. attach the extent to the transaction, i.e. insert the extent into the transaction's read_set 2. attach the transaction to the extent, i.e. insert the transaction into the extent's read_transactions For initial pending and stable writing extents, we need to do the second step before doing "CachedExtent::wait_io()" and to do the first step after "CachedExtent::wait_io()". This commit add interfaces corresponding to those two steps. Fixes: https://tracker.ceph.com/issues/70976 Signed-off-by: Xuehan Xu <[email protected]> Signed-off-by: Yingxin Cheng <[email protected]>
1 parent 2388ab1 commit 4328521

File tree

2 files changed

+94
-16
lines changed

2 files changed

+94
-16
lines changed

src/crimson/os/seastore/cached_extent.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,14 @@ class read_set_item_t {
118118
T *t = nullptr;
119119
CachedExtentRef ref;
120120

121+
bool is_extent_attached_to_trans() const {
122+
return extent_hook.is_linked();
123+
}
124+
125+
bool is_trans_attached_to_extent() const {
126+
return trans_hook.is_linked();
127+
}
128+
121129
read_set_item_t(T *t, CachedExtentRef ref);
122130
read_set_item_t(const read_set_item_t &) = delete;
123131
read_set_item_t(read_set_item_t &&) = default;

src/crimson/os/seastore/transaction.h

Lines changed: 86 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -159,21 +159,34 @@ class Transaction {
159159
}
160160

161161
// Returns true if added, false if already added or weak
162-
bool maybe_add_to_read_set(CachedExtentRef ref) {
163-
assert(ref->get_paddr().is_absolute());
162+
struct maybe_add_readset_ret {
163+
bool added;
164+
bool is_paddr_known;
165+
};
166+
maybe_add_readset_ret maybe_add_to_read_set(CachedExtentRef ref) {
167+
assert(ref->get_paddr().is_absolute()
168+
|| ref->get_paddr().is_record_relative());
164169
if (is_weak()) {
165-
return false;
170+
return {false, true /* meaningless */};
171+
}
172+
if (ref->get_paddr().is_absolute()) {
173+
// paddr is known
174+
bool added = do_add_to_read_set(ref);
175+
return {added, true};
176+
} else {
177+
// paddr is unknown until wait_io() finished
178+
// to call maybe_add_to_read_set_step_2(ref)
179+
ceph_assert(ref->get_paddr().is_record_relative());
180+
bool added = maybe_add_to_read_set_step_1(ref);
181+
return {added, false};
166182
}
167-
return do_add_to_read_set(ref);
168183
}
169184

170185
bool is_in_read_set(CachedExtentRef extent) const {
171-
return lookup_read_set(extent).first;
186+
return lookup_trans_from_read_extent(extent).first;
172187
}
173188

174189
void add_to_read_set(CachedExtentRef ref) {
175-
assert(ref->get_paddr().is_absolute()
176-
|| ref->get_paddr().is_root());
177190
if (is_weak()) {
178191
return;
179192
}
@@ -292,9 +305,9 @@ class Transaction {
292305
auto where = read_set.find(placeholder.get_paddr(), extent_cmp_t{});
293306
assert(where != read_set.end());
294307
assert(where->ref.get() == &placeholder);
295-
where = read_set.erase(where);
296308
placeholder.read_transactions.erase(
297309
read_trans_set_t<Transaction>::s_iterator_to(*where));
310+
where = read_set.erase(where);
298311
// Note, the retired-placeholder is not removed from read_items after replace.
299312
read_items.emplace_back(this, &extent);
300313
auto it = read_set.insert_before(where, read_items.back());
@@ -436,7 +449,7 @@ class Transaction {
436449
root.reset();
437450
offset = 0;
438451
delayed_temp_offset = 0;
439-
read_items.clear();
452+
clear_read_set();
440453
fresh_backref_extents = 0;
441454
invalidate_clear_write_set();
442455
mutated_block_list.clear();
@@ -579,6 +592,15 @@ class Transaction {
579592
friend class Cache;
580593
friend Ref make_test_transaction();
581594

595+
void clear_read_set() {
596+
read_items.clear();
597+
assert(read_set.empty());
598+
#ifndef NDEBUG
599+
num_replace_placeholder = 0;
600+
#endif
601+
// Automatically unlink this transaction from CachedExtent::read_transactions
602+
}
603+
582604
std::pair<get_extent_ret, CachedExtentRef> do_get_extent(paddr_t addr) {
583605
LOG_PREFIX(Transaction::do_get_extent);
584606
// it's possible that both write_set and retired_set contain
@@ -606,8 +628,8 @@ class Transaction {
606628
}
607629
}
608630

609-
auto lookup_read_set(CachedExtentRef ref) const
610-
-> std::pair<bool, read_trans_set_t<Transaction>::const_iterator> {
631+
std::pair<bool, read_trans_set_t<Transaction>::iterator>
632+
lookup_trans_from_read_extent(CachedExtentRef ref) const {
611633
assert(ref->is_valid());
612634
assert(!is_weak());
613635
auto it = ref->read_transactions.lower_bound(
@@ -617,19 +639,67 @@ class Transaction {
617639
return std::make_pair(exists, it);
618640
}
619641

620-
bool do_add_to_read_set(CachedExtentRef ref) {
642+
bool maybe_add_to_read_set_step_1(CachedExtentRef ref) {
621643
assert(!is_weak());
622644
assert(ref->is_stable());
623-
auto [exists, it] = lookup_read_set(ref);
645+
auto [exists, it] = lookup_trans_from_read_extent(ref);
624646
if (exists) {
647+
// not added
625648
return false;
626649
}
627650

651+
// step 1: create read_item and attach transaction to extent
652+
// so that transaction invalidation can populate
653+
assert(!read_set.count(ref->get_paddr(), extent_cmp_t{}));
628654
read_items.emplace_back(this, ref);
629-
auto [iter, inserted] = read_set.insert(read_items.back());
630-
ceph_assert(inserted);
631655
ref->read_transactions.insert_before(
632-
it, const_cast<read_set_item_t<Transaction>&>(*iter));
656+
it, read_items.back());
657+
658+
// added
659+
return true;
660+
}
661+
662+
void maybe_add_to_read_set_step_2(CachedExtentRef ref) {
663+
// paddr must be known for read_set
664+
ceph_assert(ref->get_paddr().is_absolute());
665+
if (is_weak()) {
666+
return;
667+
}
668+
auto [exists, it] = lookup_trans_from_read_extent(ref);
669+
// step 1 must be complete
670+
assert(exists);
671+
// step 2 may be reordered after wait_io(),
672+
// so the extent may already be attached to the transaction.
673+
if (it->is_extent_attached_to_trans()) {
674+
assert(read_set.count(ref->get_paddr(), extent_cmp_t{}));
675+
return;
676+
}
677+
678+
// step 2: attach extent to transaction to become visible
679+
assert(!read_set.count(ref->get_paddr(), extent_cmp_t{}));
680+
auto [iter, inserted] = read_set.insert(*it);
681+
assert(inserted);
682+
}
683+
684+
bool do_add_to_read_set(CachedExtentRef ref) {
685+
assert(!is_weak());
686+
assert(ref->is_stable());
687+
// paddr must be known for read_set
688+
assert(ref->get_paddr().is_absolute()
689+
|| ref->get_paddr().is_root());
690+
691+
if (!maybe_add_to_read_set_step_1(ref)) {
692+
// step 2 must be complete if exist
693+
assert(read_set.count(ref->get_paddr(), extent_cmp_t{}));
694+
// not added
695+
return false;
696+
}
697+
698+
// step 2: attach extent to transaction to become visible
699+
auto [iter, inserted] = read_set.insert(read_items.back());
700+
assert(inserted);
701+
702+
// added
633703
return true;
634704
}
635705

0 commit comments

Comments
 (0)