Skip to content

Commit 4bd06f0

Browse files
author
Kent Overstreet
committed
bcachefs: Fixes for snapshot_tree.master_subvol
Ensure that snapshot_tree.master_subvol is cleared when we delete the master subvolume in a tree of snapshots, and allow for snapshot trees that don't have a master subvolume in fsck. Signed-off-by: Kent Overstreet <[email protected]>
1 parent b5e4cd0 commit 4bd06f0

File tree

2 files changed

+47
-15
lines changed

2 files changed

+47
-15
lines changed

fs/bcachefs/snapshot.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,9 @@ static int check_snapshot_tree(struct btree_trans *trans,
495495
goto err;
496496
}
497497

498+
if (!st.v->master_subvol)
499+
goto out;
500+
498501
ret = bch2_subvolume_get(trans, le32_to_cpu(st.v->master_subvol), false, &subvol);
499502
if (ret && !bch2_err_matches(ret, ENOENT))
500503
goto err;
@@ -538,6 +541,7 @@ static int check_snapshot_tree(struct btree_trans *trans,
538541
u->v.master_subvol = cpu_to_le32(subvol_id);
539542
st = snapshot_tree_i_to_s_c(u);
540543
}
544+
out:
541545
err:
542546
fsck_err:
543547
bch2_trans_iter_exit(trans, &snapshot_iter);
@@ -1037,13 +1041,11 @@ int bch2_check_key_has_snapshot(struct btree_trans *trans,
10371041
int bch2_snapshot_node_set_deleted(struct btree_trans *trans, u32 id)
10381042
{
10391043
struct btree_iter iter;
1040-
struct bkey_i_snapshot *s;
1041-
int ret = 0;
1042-
1043-
s = bch2_bkey_get_mut_typed(trans, &iter,
1044+
struct bkey_i_snapshot *s =
1045+
bch2_bkey_get_mut_typed(trans, &iter,
10441046
BTREE_ID_snapshots, POS(0, id),
10451047
0, snapshot);
1046-
ret = PTR_ERR_OR_ZERO(s);
1048+
int ret = PTR_ERR_OR_ZERO(s);
10471049
if (unlikely(ret)) {
10481050
bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT),
10491051
trans->c, "missing snapshot %u", id);

fs/bcachefs/subvolume.c

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -409,26 +409,56 @@ static int bch2_subvolumes_reparent(struct btree_trans *trans, u32 subvolid_to_d
409409
*/
410410
static int __bch2_subvolume_delete(struct btree_trans *trans, u32 subvolid)
411411
{
412-
struct btree_iter iter;
413-
struct bkey_s_c_subvolume subvol;
414-
u32 snapid;
415-
int ret = 0;
412+
struct btree_iter subvol_iter = {}, snapshot_iter = {}, snapshot_tree_iter = {};
416413

417-
subvol = bch2_bkey_get_iter_typed(trans, &iter,
414+
struct bkey_s_c_subvolume subvol =
415+
bch2_bkey_get_iter_typed(trans, &subvol_iter,
418416
BTREE_ID_subvolumes, POS(0, subvolid),
419417
BTREE_ITER_cached|BTREE_ITER_intent,
420418
subvolume);
421-
ret = bkey_err(subvol);
419+
int ret = bkey_err(subvol);
422420
bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT), trans->c,
423421
"missing subvolume %u", subvolid);
424422
if (ret)
425-
return ret;
423+
goto err;
426424

427-
snapid = le32_to_cpu(subvol.v->snapshot);
425+
u32 snapid = le32_to_cpu(subvol.v->snapshot);
426+
427+
struct bkey_s_c_snapshot snapshot =
428+
bch2_bkey_get_iter_typed(trans, &snapshot_iter,
429+
BTREE_ID_snapshots, POS(0, snapid),
430+
0, snapshot);
431+
ret = bkey_err(subvol);
432+
bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT), trans->c,
433+
"missing snapshot %u", snapid);
434+
if (ret)
435+
goto err;
436+
437+
u32 treeid = le32_to_cpu(snapshot.v->tree);
428438

429-
ret = bch2_btree_delete_at(trans, &iter, 0) ?:
439+
struct bkey_s_c_snapshot_tree snapshot_tree =
440+
bch2_bkey_get_iter_typed(trans, &snapshot_tree_iter,
441+
BTREE_ID_snapshot_trees, POS(0, treeid),
442+
0, snapshot_tree);
443+
444+
if (le32_to_cpu(snapshot_tree.v->master_subvol) == subvolid) {
445+
struct bkey_i_snapshot_tree *snapshot_tree_mut =
446+
bch2_bkey_make_mut_typed(trans, &snapshot_tree_iter,
447+
&snapshot_tree.s_c,
448+
0, snapshot_tree);
449+
ret = PTR_ERR_OR_ZERO(snapshot_tree_mut);
450+
if (ret)
451+
goto err;
452+
453+
snapshot_tree_mut->v.master_subvol = 0;
454+
}
455+
456+
ret = bch2_btree_delete_at(trans, &subvol_iter, 0) ?:
430457
bch2_snapshot_node_set_deleted(trans, snapid);
431-
bch2_trans_iter_exit(trans, &iter);
458+
err:
459+
bch2_trans_iter_exit(trans, &snapshot_tree_iter);
460+
bch2_trans_iter_exit(trans, &snapshot_iter);
461+
bch2_trans_iter_exit(trans, &subvol_iter);
432462
return ret;
433463
}
434464

0 commit comments

Comments
 (0)