Skip to content

Commit 1c31b83

Browse files
author
Kent Overstreet
committed
bcachefs: bch2_snapshot_is_ancestor() now safe to call in early recovery
this fixes an assertion pop in bch2_check_snapshot_trees() -> check_snapshot_tree() -> bch2_snapshot_tree_master_subvol() -> bch2_snapshot_is_ancestor() Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
1 parent 1ba6f48 commit 1c31b83

File tree

1 file changed

+18
-14
lines changed

1 file changed

+18
-14
lines changed

fs/bcachefs/snapshot.c

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -91,18 +91,20 @@ static int bch2_snapshot_tree_create(struct btree_trans *trans,
9191

9292
/* Snapshot nodes: */
9393

94-
static bool bch2_snapshot_is_ancestor_early(struct bch_fs *c, u32 id, u32 ancestor)
94+
static bool __bch2_snapshot_is_ancestor_early(struct snapshot_table *t, u32 id, u32 ancestor)
9595
{
96-
struct snapshot_table *t;
97-
98-
rcu_read_lock();
99-
t = rcu_dereference(c->snapshots);
100-
10196
while (id && id < ancestor)
10297
id = __snapshot_t(t, id)->parent;
98+
return id == ancestor;
99+
}
100+
101+
static bool bch2_snapshot_is_ancestor_early(struct bch_fs *c, u32 id, u32 ancestor)
102+
{
103+
rcu_read_lock();
104+
bool ret = __bch2_snapshot_is_ancestor_early(rcu_dereference(c->snapshots), id, ancestor);
103105
rcu_read_unlock();
104106

105-
return id == ancestor;
107+
return ret;
106108
}
107109

108110
static inline u32 get_ancestor_below(struct snapshot_table *t, u32 id, u32 ancestor)
@@ -120,25 +122,27 @@ static inline u32 get_ancestor_below(struct snapshot_table *t, u32 id, u32 ances
120122

121123
bool __bch2_snapshot_is_ancestor(struct bch_fs *c, u32 id, u32 ancestor)
122124
{
123-
struct snapshot_table *t;
124125
bool ret;
125126

126-
EBUG_ON(c->recovery_pass_done <= BCH_RECOVERY_PASS_check_snapshots);
127-
128127
rcu_read_lock();
129-
t = rcu_dereference(c->snapshots);
128+
struct snapshot_table *t = rcu_dereference(c->snapshots);
129+
130+
if (unlikely(c->recovery_pass_done <= BCH_RECOVERY_PASS_check_snapshots)) {
131+
ret = __bch2_snapshot_is_ancestor_early(t, id, ancestor);
132+
goto out;
133+
}
130134

131135
while (id && id < ancestor - IS_ANCESTOR_BITMAP)
132136
id = get_ancestor_below(t, id, ancestor);
133137

134138
if (id && id < ancestor) {
135139
ret = test_bit(ancestor - id - 1, __snapshot_t(t, id)->is_ancestor);
136140

137-
EBUG_ON(ret != bch2_snapshot_is_ancestor_early(c, id, ancestor));
141+
EBUG_ON(ret != __bch2_snapshot_is_ancestor_early(t, id, ancestor));
138142
} else {
139143
ret = id == ancestor;
140144
}
141-
145+
out:
142146
rcu_read_unlock();
143147

144148
return ret;
@@ -547,7 +551,7 @@ static int check_snapshot_tree(struct btree_trans *trans,
547551
"snapshot tree points to missing subvolume:\n %s",
548552
(printbuf_reset(&buf),
549553
bch2_bkey_val_to_text(&buf, c, st.s_c), buf.buf)) ||
550-
fsck_err_on(!bch2_snapshot_is_ancestor_early(c,
554+
fsck_err_on(!bch2_snapshot_is_ancestor(c,
551555
le32_to_cpu(subvol.snapshot),
552556
root_id),
553557
c, snapshot_tree_to_wrong_subvol,

0 commit comments

Comments
 (0)