Skip to content

Commit b5e4cd0

Browse files
author
Kent Overstreet
committed
bcachefs: Don't rely on snapshot_tree.master_subvol for reattaching
Previously, fsck used the snapshot tree's master subvol for finding the root inode number - but the master subvol might have been deleting, and setting a new one should be a user operation; meaning we can't rely on it existing. Fortunately, for finding the root inode number in a tree of snapshots, finding any associated subvolume works. Signed-off-by: Kent Overstreet <[email protected]>
1 parent 4541408 commit b5e4cd0

File tree

2 files changed

+46
-7
lines changed

2 files changed

+46
-7
lines changed

fs/bcachefs/errcode.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@
118118
x(ENOENT, ENOENT_dev_not_found) \
119119
x(ENOENT, ENOENT_dev_idx_not_found) \
120120
x(ENOENT, ENOENT_inode_no_backpointer) \
121+
x(ENOENT, ENOENT_no_snapshot_tree_subvol) \
121122
x(ENOTEMPTY, ENOTEMPTY_dir_not_empty) \
122123
x(ENOTEMPTY, ENOTEMPTY_subvol_not_empty) \
123124
x(EEXIST, EEXIST_str_hash_set) \

fs/bcachefs/fsck.c

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,36 @@ static int __remove_dirent(struct btree_trans *trans, struct bpos pos)
205205
return ret;
206206
}
207207

208+
/*
209+
* Find any subvolume associated with a tree of snapshots
210+
* We can't rely on master_subvol - it might have been deleted.
211+
*/
212+
static int find_snapshot_tree_subvol(struct btree_trans *trans,
213+
u32 tree_id, u32 *subvol)
214+
{
215+
struct btree_iter iter;
216+
struct bkey_s_c k;
217+
int ret;
218+
219+
for_each_btree_key_norestart(trans, iter, BTREE_ID_snapshots, POS_MIN, 0, k, ret) {
220+
if (k.k->type != KEY_TYPE_snapshot)
221+
continue;
222+
223+
struct bkey_s_c_snapshot s = bkey_s_c_to_snapshot(k);
224+
if (le32_to_cpu(s.v->tree) != tree_id)
225+
continue;
226+
227+
if (s.v->subvol) {
228+
*subvol = le32_to_cpu(s.v->subvol);
229+
goto found;
230+
}
231+
}
232+
ret = -BCH_ERR_ENOENT_no_snapshot_tree_subvol;
233+
found:
234+
bch2_trans_iter_exit(trans, &iter);
235+
return ret;
236+
}
237+
208238
/* Get lost+found, create if it doesn't exist: */
209239
static int lookup_lostfound(struct btree_trans *trans, u32 snapshot,
210240
struct bch_inode_unpacked *lostfound,
@@ -223,19 +253,24 @@ static int lookup_lostfound(struct btree_trans *trans, u32 snapshot,
223253
if (ret)
224254
return ret;
225255

226-
subvol_inum root_inum = { .subvol = le32_to_cpu(st.master_subvol) };
256+
u32 subvolid;
257+
ret = find_snapshot_tree_subvol(trans,
258+
bch2_snapshot_tree(c, snapshot), &subvolid);
259+
bch_err_msg(c, ret, "finding subvol associated with snapshot tree %u",
260+
bch2_snapshot_tree(c, snapshot));
261+
if (ret)
262+
return ret;
227263

228264
struct bch_subvolume subvol;
229-
ret = bch2_subvolume_get(trans, le32_to_cpu(st.master_subvol), false, &subvol);
230-
bch_err_msg(c, ret, "looking up root subvol %u for snapshot %u",
231-
le32_to_cpu(st.master_subvol), snapshot);
265+
ret = bch2_subvolume_get(trans, subvolid, false, &subvol);
266+
bch_err_msg(c, ret, "looking up subvol %u for snapshot %u", subvolid, snapshot);
232267
if (ret)
233268
return ret;
234269

235270
if (!subvol.inode) {
236271
struct btree_iter iter;
237272
struct bkey_i_subvolume *subvol = bch2_bkey_get_mut_typed(trans, &iter,
238-
BTREE_ID_subvolumes, POS(0, le32_to_cpu(st.master_subvol)),
273+
BTREE_ID_subvolumes, POS(0, subvolid),
239274
0, subvolume);
240275
ret = PTR_ERR_OR_ZERO(subvol);
241276
if (ret)
@@ -245,13 +280,16 @@ static int lookup_lostfound(struct btree_trans *trans, u32 snapshot,
245280
bch2_trans_iter_exit(trans, &iter);
246281
}
247282

248-
root_inum.inum = le64_to_cpu(subvol.inode);
283+
subvol_inum root_inum = {
284+
.subvol = subvolid,
285+
.inum = le64_to_cpu(subvol.inode)
286+
};
249287

250288
struct bch_inode_unpacked root_inode;
251289
struct bch_hash_info root_hash_info;
252290
ret = lookup_inode(trans, root_inum.inum, snapshot, &root_inode);
253291
bch_err_msg(c, ret, "looking up root inode %llu for subvol %u",
254-
root_inum.inum, le32_to_cpu(st.master_subvol));
292+
root_inum.inum, subvolid);
255293
if (ret)
256294
return ret;
257295

0 commit comments

Comments
 (0)