Skip to content

Commit 9a2d281

Browse files
committed
crimson/os/seastore/omap_manager: handle the cases in which omap nodes
are rewritten before seen by users Fixes: https://tracker.ceph.com/issues/71383 Signed-off-by: Xuehan Xu <[email protected]>
1 parent c24cf67 commit 9a2d281

File tree

2 files changed

+38
-14
lines changed

2 files changed

+38
-14
lines changed

src/crimson/os/seastore/omap_manager/btree/omap_btree_node.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,10 @@ struct OMapNode : LogicalChildNode {
137137
return end;
138138
}
139139
bool is_btree_root() const { return root; }
140+
protected:
141+
void set_root(bool is_root) {
142+
root = is_root;
143+
}
140144
private:
141145
bool root = false;
142146
std::string begin;

src/crimson/os/seastore/omap_manager/btree/omap_btree_node_impl.h

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -76,19 +76,29 @@ struct OMapInnerNode
7676
}
7777

7878
void prepare_commit() final {
79+
if (unlikely(!is_seen_by_users())) {
80+
ceph_assert(is_rewrite());
81+
auto &prior = *get_prior_instance()->template cast<OMapInnerNode>();
82+
if (!prior.is_seen_by_users()) {
83+
return;
84+
}
85+
set_seen_by_users();
86+
}
7987
this->parent_node_t::prepare_commit();
80-
if (is_rewrite() && !is_btree_root()) {
88+
if (is_rewrite()) {
8189
auto &prior = *get_prior_instance()->template cast<OMapInnerNode>();
82-
if (prior.base_child_t::has_parent_tracker()) {
83-
assert(prior.is_seen_by_users());
90+
assert(prior.is_seen_by_users());
91+
// Chances are that this transaction is in parallel with another
92+
// user transaction that set the prior's root to true, so we need
93+
// to do this.
94+
set_root(prior.is_btree_root());
95+
if (!is_btree_root()) {
96+
assert(prior.base_child_t::has_parent_tracker());
97+
assert(prior.is_seen_by_users());
8498
// unlike fixed-kv nodes, rewriting child nodes of the omap tree
8599
// won't affect parent nodes, so we have to manually take prior
86100
// instances' parent trackers here.
87101
this->child_node_t::take_parent_from_prior();
88-
} else {
89-
// dirty omap extent may not be accessed yet during rewrite,
90-
// this means the extent may not be initalized yet as linked.
91-
assert(!prior.is_seen_by_users());
92102
}
93103
}
94104
}
@@ -292,18 +302,28 @@ struct OMapLeafNode
292302
}
293303

294304
void prepare_commit() final {
295-
if (is_rewrite() && !is_btree_root()) {
305+
if (unlikely(!is_seen_by_users())) {
306+
ceph_assert(is_rewrite());
307+
auto &prior = *get_prior_instance()->template cast<OMapLeafNode>();
308+
if (!prior.is_seen_by_users()) {
309+
return;
310+
}
311+
set_seen_by_users();
312+
}
313+
if (is_rewrite()) {
296314
auto &prior = *get_prior_instance()->template cast<OMapLeafNode>();
297-
if (prior.base_child_t::has_parent_tracker()) {
298-
assert(prior.is_seen_by_users());
315+
assert(prior.is_seen_by_users());
316+
// Chances are that this transaction is in parallel with another
317+
// user transaction that set the prior's root to true, so we need
318+
// to do this.
319+
set_root(prior.is_btree_root());
320+
if (!is_btree_root()) {
321+
assert(prior.base_child_t::has_parent_tracker());
322+
assert(prior.is_seen_by_users());
299323
// unlike fixed-kv nodes, rewriting child nodes of the omap tree
300324
// won't affect parent nodes, so we have to manually take prior
301325
// instances' parent trackers here.
302326
this->child_node_t::take_parent_from_prior();
303-
} else {
304-
// dirty omap extent may not be accessed yet during rewrite,
305-
// this means the extent may not be initalized yet as linked.
306-
assert(!prior.is_seen_by_users());
307327
}
308328
}
309329
}

0 commit comments

Comments
 (0)