Commit 4bd06f07 authored by Kent Overstreet's avatar Kent Overstreet
Browse files

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: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent b5e4cd08
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -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 @@ int bch2_check_key_has_snapshot(struct btree_trans *trans,
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);
+40 −10
Original line number Diff line number Diff line
@@ -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);

	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);

	ret =   bch2_btree_delete_at(trans, &iter, 0) ?:
	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;
}