@@ -98,6 +98,17 @@ struct rbm_pending_ool_t {
9898 * - seastore_cache logs
9999 */
100100class Transaction {
101+ private:
102+ auto lookup_read_set (CachedExtentRef ref) const {
103+ assert (ref->is_valid ());
104+ assert (!is_weak ());
105+ auto it = ref->read_transactions .lower_bound (
106+ this , read_set_item_t <Transaction>::trans_cmp_t ());
107+ bool exists =
108+ (it != ref->read_transactions .end () && it->t == this );
109+ return std::make_pair (exists, it);
110+ }
111+
101112public:
102113 using Ref = std::unique_ptr<Transaction>;
103114 using on_destruct_func_t = std::function<void (Transaction&)>;
@@ -107,39 +118,29 @@ class Transaction {
107118 RETIRED
108119 };
109120 get_extent_ret get_extent (paddr_t addr, CachedExtentRef *out) {
110- LOG_PREFIX (Transaction::get_extent);
111- // it's possible that both write_set and retired_set contain
112- // this addr at the same time when addr is absolute and the
113- // corresponding extent is used to map existing extent on disk.
114- // So search write_set first.
115- if (auto iter = write_set.find_offset (addr);
116- iter != write_set.end ()) {
117- if (out)
118- *out = CachedExtentRef (&*iter);
119- SUBTRACET (seastore_cache, " {} is present in write_set -- {}" ,
120- *this , addr, *iter);
121- assert (!out || (*out)->is_valid ());
122- return get_extent_ret::PRESENT;
123- } else if (retired_set.count (addr)) {
124- return get_extent_ret::RETIRED;
125- } else if (
126- auto iter = read_set.find (addr);
127- iter != read_set.end ()) {
128- // placeholder in read-set should be in the retired-set
129- // at the same time.
130- assert (!is_retired_placeholder_type (iter->ref ->get_type ()));
131- if (out)
132- *out = iter->ref ;
133- SUBTRACET (seastore_cache, " {} is present in read_set -- {}" ,
134- *this , addr, *(iter->ref ));
135- return get_extent_ret::PRESENT;
136- } else {
137- return get_extent_ret::ABSENT;
121+ auto [result, ext] = do_get_extent (addr);
122+ // placeholder in read-set must be in the retired-set
123+ // at the same time, user should not see a placeholder.
124+ assert (result != get_extent_ret::PRESENT ||
125+ !is_retired_placeholder_type (ext->get_type ()));
126+ if (out && result == get_extent_ret::PRESENT) {
127+ *out = ext;
138128 }
129+ return result;
139130 }
140131
141- void add_to_retired_set (CachedExtentRef ref) {
142- ceph_assert (!is_weak ());
132+ void add_absent_to_retired_set (CachedExtentRef ref) {
133+ add_to_read_set (ref);
134+ add_present_to_retired_set (ref);
135+ }
136+
137+ void add_present_to_retired_set (CachedExtentRef ref) {
138+ assert (!is_weak ());
139+ #ifndef NDEBUG
140+ auto [result, ext] = do_get_extent (ref->get_paddr ());
141+ assert (result == get_extent_ret::PRESENT);
142+ assert (ext == ref);
143+ #endif
143144 if (ref->is_exist_clean () ||
144145 ref->is_exist_mutation_pending ()) {
145146 existing_block_stats.dec (ref);
@@ -169,11 +170,8 @@ class Transaction {
169170 return false ;
170171 }
171172
172- assert (ref->is_valid ());
173-
174- auto it = ref->read_transactions .lower_bound (
175- this , read_set_item_t <Transaction>::trans_cmp_t ());
176- if (it != ref->read_transactions .end () && it->t == this ) {
173+ auto [exists, it] = lookup_read_set (ref);
174+ if (exists) {
177175 return false ;
178176 }
179177
@@ -189,11 +187,8 @@ class Transaction {
189187 return ;
190188 }
191189
192- assert (ref->is_valid ());
193-
194- auto it = ref->read_transactions .lower_bound (
195- this , read_set_item_t <Transaction>::trans_cmp_t ());
196- assert (it == ref->read_transactions .end () || it->t != this );
190+ auto [exists, it] = lookup_read_set (ref);
191+ assert (!exists);
197192
198193 auto [iter, inserted] = read_set.emplace (this , ref);
199194 ceph_assert (inserted);
@@ -583,6 +578,33 @@ class Transaction {
583578 friend class Cache ;
584579 friend Ref make_test_transaction ();
585580
581+ std::pair<get_extent_ret, CachedExtentRef> do_get_extent (paddr_t addr) {
582+ LOG_PREFIX (Transaction::do_get_extent);
583+ // it's possible that both write_set and retired_set contain
584+ // this addr at the same time when addr is absolute and the
585+ // corresponding extent is used to map existing extent on disk.
586+ // So search write_set first.
587+ if (auto iter = write_set.find_offset (addr);
588+ iter != write_set.end ()) {
589+ auto ret = CachedExtentRef (&*iter);
590+ SUBTRACET (seastore_cache, " {} is present in write_set -- {}" ,
591+ *this , addr, *ret);
592+ assert (ret->is_valid ());
593+ return {get_extent_ret::PRESENT, ret};
594+ } else if (retired_set.count (addr)) {
595+ return {get_extent_ret::RETIRED, nullptr };
596+ } else if (
597+ auto iter = read_set.find (addr);
598+ iter != read_set.end ()) {
599+ auto ret = iter->ref ;
600+ SUBTRACET (seastore_cache, " {} is present in read_set -- {}" ,
601+ *this , addr, *ret);
602+ return {get_extent_ret::PRESENT, ret};
603+ } else {
604+ return {get_extent_ret::ABSENT, nullptr };
605+ }
606+ }
607+
586608 void set_backref_entries (backref_entry_refs_t && entries) {
587609 assert (backref_entries.empty ());
588610 backref_entries = std::move (entries);
0 commit comments