Commit b5e4cd08 authored by Kent Overstreet's avatar Kent Overstreet
Browse files

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: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 45414083
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -118,6 +118,7 @@
	x(ENOENT,			ENOENT_dev_not_found)			\
	x(ENOENT,			ENOENT_dev_idx_not_found)		\
	x(ENOENT,			ENOENT_inode_no_backpointer)		\
	x(ENOENT,			ENOENT_no_snapshot_tree_subvol)		\
	x(ENOTEMPTY,			ENOTEMPTY_dir_not_empty)		\
	x(ENOTEMPTY,			ENOTEMPTY_subvol_not_empty)		\
	x(EEXIST,			EEXIST_str_hash_set)			\
+45 −7
Original line number Diff line number Diff line
@@ -205,6 +205,36 @@ static int __remove_dirent(struct btree_trans *trans, struct bpos pos)
	return ret;
}

/*
 * Find any subvolume associated with a tree of snapshots
 * We can't rely on master_subvol - it might have been deleted.
 */
static int find_snapshot_tree_subvol(struct btree_trans *trans,
				     u32 tree_id, u32 *subvol)
{
	struct btree_iter iter;
	struct bkey_s_c k;
	int ret;

	for_each_btree_key_norestart(trans, iter, BTREE_ID_snapshots, POS_MIN, 0, k, ret) {
		if (k.k->type != KEY_TYPE_snapshot)
			continue;

		struct bkey_s_c_snapshot s = bkey_s_c_to_snapshot(k);
		if (le32_to_cpu(s.v->tree) != tree_id)
			continue;

		if (s.v->subvol) {
			*subvol = le32_to_cpu(s.v->subvol);
			goto found;
		}
	}
	ret = -BCH_ERR_ENOENT_no_snapshot_tree_subvol;
found:
	bch2_trans_iter_exit(trans, &iter);
	return ret;
}

/* Get lost+found, create if it doesn't exist: */
static int lookup_lostfound(struct btree_trans *trans, u32 snapshot,
			    struct bch_inode_unpacked *lostfound,
@@ -223,19 +253,24 @@ static int lookup_lostfound(struct btree_trans *trans, u32 snapshot,
	if (ret)
		return ret;

	subvol_inum root_inum = { .subvol = le32_to_cpu(st.master_subvol) };
	u32 subvolid;
	ret = find_snapshot_tree_subvol(trans,
				bch2_snapshot_tree(c, snapshot), &subvolid);
	bch_err_msg(c, ret, "finding subvol associated with snapshot tree %u",
		    bch2_snapshot_tree(c, snapshot));
	if (ret)
		return ret;

	struct bch_subvolume subvol;
	ret = bch2_subvolume_get(trans, le32_to_cpu(st.master_subvol), false, &subvol);
	bch_err_msg(c, ret, "looking up root subvol %u for snapshot %u",
		    le32_to_cpu(st.master_subvol), snapshot);
	ret = bch2_subvolume_get(trans, subvolid, false, &subvol);
	bch_err_msg(c, ret, "looking up subvol %u for snapshot %u", subvolid, snapshot);
	if (ret)
		return ret;

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

	root_inum.inum = le64_to_cpu(subvol.inode);
	subvol_inum root_inum = {
		.subvol = subvolid,
		.inum = le64_to_cpu(subvol.inode)
	};

	struct bch_inode_unpacked root_inode;
	struct bch_hash_info root_hash_info;
	ret = lookup_inode(trans, root_inum.inum, snapshot, &root_inode);
	bch_err_msg(c, ret, "looking up root inode %llu for subvol %u",
		    root_inum.inum, le32_to_cpu(st.master_subvol));
		    root_inum.inum, subvolid);
	if (ret)
		return ret;