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 <kent.overstreet@linux.dev>
This commit is contained in:
parent
b5e4cd0871
commit
4bd06f07bc
2 changed files with 47 additions and 15 deletions
|
@ -495,6 +495,9 @@ static int check_snapshot_tree(struct btree_trans *trans,
|
|||
goto err;
|
||||
}
|
||||
|
||||
if (!st.v->master_subvol)
|
||||
goto out;
|
||||
|
||||
ret = bch2_subvolume_get(trans, le32_to_cpu(st.v->master_subvol), false, &subvol);
|
||||
if (ret && !bch2_err_matches(ret, ENOENT))
|
||||
goto err;
|
||||
|
@ -538,6 +541,7 @@ static int check_snapshot_tree(struct btree_trans *trans,
|
|||
u->v.master_subvol = cpu_to_le32(subvol_id);
|
||||
st = snapshot_tree_i_to_s_c(u);
|
||||
}
|
||||
out:
|
||||
err:
|
||||
fsck_err:
|
||||
bch2_trans_iter_exit(trans, &snapshot_iter);
|
||||
|
@ -1037,13 +1041,11 @@ fsck_err:
|
|||
int bch2_snapshot_node_set_deleted(struct btree_trans *trans, u32 id)
|
||||
{
|
||||
struct btree_iter iter;
|
||||
struct bkey_i_snapshot *s;
|
||||
int ret = 0;
|
||||
|
||||
s = bch2_bkey_get_mut_typed(trans, &iter,
|
||||
struct bkey_i_snapshot *s =
|
||||
bch2_bkey_get_mut_typed(trans, &iter,
|
||||
BTREE_ID_snapshots, POS(0, id),
|
||||
0, snapshot);
|
||||
ret = PTR_ERR_OR_ZERO(s);
|
||||
int ret = PTR_ERR_OR_ZERO(s);
|
||||
if (unlikely(ret)) {
|
||||
bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT),
|
||||
trans->c, "missing snapshot %u", id);
|
||||
|
|
|
@ -409,26 +409,56 @@ static int bch2_subvolumes_reparent(struct btree_trans *trans, u32 subvolid_to_d
|
|||
*/
|
||||
static int __bch2_subvolume_delete(struct btree_trans *trans, u32 subvolid)
|
||||
{
|
||||
struct btree_iter iter;
|
||||
struct bkey_s_c_subvolume subvol;
|
||||
u32 snapid;
|
||||
int ret = 0;
|
||||
struct btree_iter subvol_iter = {}, snapshot_iter = {}, snapshot_tree_iter = {};
|
||||
|
||||
subvol = bch2_bkey_get_iter_typed(trans, &iter,
|
||||
struct bkey_s_c_subvolume subvol =
|
||||
bch2_bkey_get_iter_typed(trans, &subvol_iter,
|
||||
BTREE_ID_subvolumes, POS(0, subvolid),
|
||||
BTREE_ITER_cached|BTREE_ITER_intent,
|
||||
subvolume);
|
||||
ret = bkey_err(subvol);
|
||||
int ret = bkey_err(subvol);
|
||||
bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT), trans->c,
|
||||
"missing subvolume %u", subvolid);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err;
|
||||
|
||||
snapid = le32_to_cpu(subvol.v->snapshot);
|
||||
u32 snapid = le32_to_cpu(subvol.v->snapshot);
|
||||
|
||||
ret = bch2_btree_delete_at(trans, &iter, 0) ?:
|
||||
struct bkey_s_c_snapshot snapshot =
|
||||
bch2_bkey_get_iter_typed(trans, &snapshot_iter,
|
||||
BTREE_ID_snapshots, POS(0, snapid),
|
||||
0, snapshot);
|
||||
ret = bkey_err(subvol);
|
||||
bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT), trans->c,
|
||||
"missing snapshot %u", snapid);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
u32 treeid = le32_to_cpu(snapshot.v->tree);
|
||||
|
||||
struct bkey_s_c_snapshot_tree snapshot_tree =
|
||||
bch2_bkey_get_iter_typed(trans, &snapshot_tree_iter,
|
||||
BTREE_ID_snapshot_trees, POS(0, treeid),
|
||||
0, snapshot_tree);
|
||||
|
||||
if (le32_to_cpu(snapshot_tree.v->master_subvol) == subvolid) {
|
||||
struct bkey_i_snapshot_tree *snapshot_tree_mut =
|
||||
bch2_bkey_make_mut_typed(trans, &snapshot_tree_iter,
|
||||
&snapshot_tree.s_c,
|
||||
0, snapshot_tree);
|
||||
ret = PTR_ERR_OR_ZERO(snapshot_tree_mut);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
snapshot_tree_mut->v.master_subvol = 0;
|
||||
}
|
||||
|
||||
ret = bch2_btree_delete_at(trans, &subvol_iter, 0) ?:
|
||||
bch2_snapshot_node_set_deleted(trans, snapid);
|
||||
bch2_trans_iter_exit(trans, &iter);
|
||||
err:
|
||||
bch2_trans_iter_exit(trans, &snapshot_tree_iter);
|
||||
bch2_trans_iter_exit(trans, &snapshot_iter);
|
||||
bch2_trans_iter_exit(trans, &subvol_iter);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue