xref: /linux/fs/bcachefs/subvolume.c (revision 067d228bb0c40542620398ef1d79f00f47c05cbb)
114b393eeSKent Overstreet // SPDX-License-Identifier: GPL-2.0
214b393eeSKent Overstreet 
314b393eeSKent Overstreet #include "bcachefs.h"
414b393eeSKent Overstreet #include "btree_key_cache.h"
514b393eeSKent Overstreet #include "btree_update.h"
6d4bf5eecSKent Overstreet #include "errcode.h"
714b393eeSKent Overstreet #include "error.h"
82027875bSKent Overstreet #include "fs.h"
914b393eeSKent Overstreet #include "subvolume.h"
1014b393eeSKent Overstreet 
11653693beSKent Overstreet static int bch2_subvolume_delete(struct btree_trans *, u32);
12653693beSKent Overstreet 
1314b393eeSKent Overstreet /* Snapshot tree: */
1414b393eeSKent Overstreet 
151c59b483SKent Overstreet void bch2_snapshot_tree_to_text(struct printbuf *out, struct bch_fs *c,
161c59b483SKent Overstreet 				struct bkey_s_c k)
171c59b483SKent Overstreet {
181c59b483SKent Overstreet 	struct bkey_s_c_snapshot_tree t = bkey_s_c_to_snapshot_tree(k);
191c59b483SKent Overstreet 
201c59b483SKent Overstreet 	prt_printf(out, "subvol %u root snapshot %u",
211c59b483SKent Overstreet 		   le32_to_cpu(t.v->master_subvol),
221c59b483SKent Overstreet 		   le32_to_cpu(t.v->root_snapshot));
231c59b483SKent Overstreet }
241c59b483SKent Overstreet 
251c59b483SKent Overstreet int bch2_snapshot_tree_invalid(const struct bch_fs *c, struct bkey_s_c k,
268726dc93SKent Overstreet 			       enum bkey_invalid_flags flags,
278726dc93SKent Overstreet 			       struct printbuf *err)
281c59b483SKent Overstreet {
291c59b483SKent Overstreet 	if (bkey_gt(k.k->p, POS(0, U32_MAX)) ||
301c59b483SKent Overstreet 	    bkey_lt(k.k->p, POS(0, 1))) {
311c59b483SKent Overstreet 		prt_printf(err, "bad pos");
321c59b483SKent Overstreet 		return -BCH_ERR_invalid_bkey;
331c59b483SKent Overstreet 	}
341c59b483SKent Overstreet 
351c59b483SKent Overstreet 	return 0;
361c59b483SKent Overstreet }
371c59b483SKent Overstreet 
38cb1b479dSKent Overstreet int bch2_snapshot_tree_lookup(struct btree_trans *trans, u32 id,
391c59b483SKent Overstreet 			      struct bch_snapshot_tree *s)
401c59b483SKent Overstreet {
41e47a390aSKent Overstreet 	int ret = bch2_bkey_get_val_typed(trans, BTREE_ID_snapshot_trees, POS(0, id),
421c59b483SKent Overstreet 					  BTREE_ITER_WITH_UPDATES, snapshot_tree, s);
43e47a390aSKent Overstreet 
44e47a390aSKent Overstreet 	if (bch2_err_matches(ret, ENOENT))
45e47a390aSKent Overstreet 		ret = -BCH_ERR_ENOENT_snapshot_tree;
46e47a390aSKent Overstreet 	return ret;
471c59b483SKent Overstreet }
481c59b483SKent Overstreet 
491c59b483SKent Overstreet static struct bkey_i_snapshot_tree *
501c59b483SKent Overstreet __snapshot_tree_create(struct btree_trans *trans)
511c59b483SKent Overstreet {
521c59b483SKent Overstreet 	struct btree_iter iter;
531c59b483SKent Overstreet 	int ret = bch2_bkey_get_empty_slot(trans, &iter,
541c59b483SKent Overstreet 			BTREE_ID_snapshot_trees, POS(0, U32_MAX));
551c59b483SKent Overstreet 	struct bkey_i_snapshot_tree *s_t;
561c59b483SKent Overstreet 
571c59b483SKent Overstreet 	if (ret == -BCH_ERR_ENOSPC_btree_slot)
581c59b483SKent Overstreet 		ret = -BCH_ERR_ENOSPC_snapshot_tree;
591c59b483SKent Overstreet 	if (ret)
601c59b483SKent Overstreet 		return ERR_PTR(ret);
611c59b483SKent Overstreet 
621c59b483SKent Overstreet 	s_t = bch2_bkey_alloc(trans, &iter, 0, snapshot_tree);
631c59b483SKent Overstreet 	ret = PTR_ERR_OR_ZERO(s_t);
641c59b483SKent Overstreet 	bch2_trans_iter_exit(trans, &iter);
651c59b483SKent Overstreet 	return ret ? ERR_PTR(ret) : s_t;
661c59b483SKent Overstreet }
671c59b483SKent Overstreet 
681c59b483SKent Overstreet static int snapshot_tree_create(struct btree_trans *trans,
691c59b483SKent Overstreet 				u32 root_id, u32 subvol_id, u32 *tree_id)
701c59b483SKent Overstreet {
711c59b483SKent Overstreet 	struct bkey_i_snapshot_tree *n_tree =
721c59b483SKent Overstreet 		__snapshot_tree_create(trans);
731c59b483SKent Overstreet 
741c59b483SKent Overstreet 	if (IS_ERR(n_tree))
751c59b483SKent Overstreet 		return PTR_ERR(n_tree);
761c59b483SKent Overstreet 
771c59b483SKent Overstreet 	n_tree->v.master_subvol	= cpu_to_le32(subvol_id);
781c59b483SKent Overstreet 	n_tree->v.root_snapshot	= cpu_to_le32(root_id);
791c59b483SKent Overstreet 	*tree_id = n_tree->k.p.offset;
801c59b483SKent Overstreet 	return 0;
811c59b483SKent Overstreet }
821c59b483SKent Overstreet 
831c59b483SKent Overstreet /* Snapshot nodes: */
841c59b483SKent Overstreet 
8514b393eeSKent Overstreet void bch2_snapshot_to_text(struct printbuf *out, struct bch_fs *c,
8614b393eeSKent Overstreet 			   struct bkey_s_c k)
8714b393eeSKent Overstreet {
8814b393eeSKent Overstreet 	struct bkey_s_c_snapshot s = bkey_s_c_to_snapshot(k);
8914b393eeSKent Overstreet 
90253748a2SKent Overstreet 	prt_printf(out, "is_subvol %llu deleted %llu parent %10u children %10u %10u subvol %u tree %u",
9114b393eeSKent Overstreet 	       BCH_SNAPSHOT_SUBVOL(s.v),
9214b393eeSKent Overstreet 	       BCH_SNAPSHOT_DELETED(s.v),
9314b393eeSKent Overstreet 	       le32_to_cpu(s.v->parent),
9414b393eeSKent Overstreet 	       le32_to_cpu(s.v->children[0]),
9514b393eeSKent Overstreet 	       le32_to_cpu(s.v->children[1]),
96253748a2SKent Overstreet 	       le32_to_cpu(s.v->subvol),
97253748a2SKent Overstreet 	       le32_to_cpu(s.v->tree));
9814b393eeSKent Overstreet }
9914b393eeSKent Overstreet 
100f0ac7df2SKent Overstreet int bch2_snapshot_invalid(const struct bch_fs *c, struct bkey_s_c k,
1018726dc93SKent Overstreet 			  enum bkey_invalid_flags flags,
1028726dc93SKent Overstreet 			  struct printbuf *err)
10314b393eeSKent Overstreet {
10414b393eeSKent Overstreet 	struct bkey_s_c_snapshot s;
10514b393eeSKent Overstreet 	u32 i, id;
10614b393eeSKent Overstreet 
107e88a75ebSKent Overstreet 	if (bkey_gt(k.k->p, POS(0, U32_MAX)) ||
108e88a75ebSKent Overstreet 	    bkey_lt(k.k->p, POS(0, 1))) {
109401ec4dbSKent Overstreet 		prt_printf(err, "bad pos");
11078c0b75cSKent Overstreet 		return -BCH_ERR_invalid_bkey;
111f0ac7df2SKent Overstreet 	}
11214b393eeSKent Overstreet 
11314b393eeSKent Overstreet 	s = bkey_s_c_to_snapshot(k);
11414b393eeSKent Overstreet 
11514b393eeSKent Overstreet 	id = le32_to_cpu(s.v->parent);
116f0ac7df2SKent Overstreet 	if (id && id <= k.k->p.offset) {
117401ec4dbSKent Overstreet 		prt_printf(err, "bad parent node (%u <= %llu)",
118f0ac7df2SKent Overstreet 		       id, k.k->p.offset);
11978c0b75cSKent Overstreet 		return -BCH_ERR_invalid_bkey;
120f0ac7df2SKent Overstreet 	}
12114b393eeSKent Overstreet 
122f0ac7df2SKent Overstreet 	if (le32_to_cpu(s.v->children[0]) < le32_to_cpu(s.v->children[1])) {
123401ec4dbSKent Overstreet 		prt_printf(err, "children not normalized");
12478c0b75cSKent Overstreet 		return -BCH_ERR_invalid_bkey;
125f0ac7df2SKent Overstreet 	}
12614b393eeSKent Overstreet 
12714b393eeSKent Overstreet 	if (s.v->children[0] &&
128f0ac7df2SKent Overstreet 	    s.v->children[0] == s.v->children[1]) {
129401ec4dbSKent Overstreet 		prt_printf(err, "duplicate child nodes");
13078c0b75cSKent Overstreet 		return -BCH_ERR_invalid_bkey;
131f0ac7df2SKent Overstreet 	}
13214b393eeSKent Overstreet 
13314b393eeSKent Overstreet 	for (i = 0; i < 2; i++) {
13414b393eeSKent Overstreet 		id = le32_to_cpu(s.v->children[i]);
13514b393eeSKent Overstreet 
136f0ac7df2SKent Overstreet 		if (id >= k.k->p.offset) {
137401ec4dbSKent Overstreet 			prt_printf(err, "bad child node (%u >= %llu)",
138f0ac7df2SKent Overstreet 			       id, k.k->p.offset);
13978c0b75cSKent Overstreet 			return -BCH_ERR_invalid_bkey;
140f0ac7df2SKent Overstreet 		}
14114b393eeSKent Overstreet 	}
14214b393eeSKent Overstreet 
143f0ac7df2SKent Overstreet 	return 0;
14414b393eeSKent Overstreet }
14514b393eeSKent Overstreet 
146904823deSKent Overstreet int bch2_mark_snapshot(struct btree_trans *trans,
1472611a041SKent Overstreet 		       enum btree_id btree, unsigned level,
14814b393eeSKent Overstreet 		       struct bkey_s_c old, struct bkey_s_c new,
149904823deSKent Overstreet 		       unsigned flags)
15014b393eeSKent Overstreet {
151904823deSKent Overstreet 	struct bch_fs *c = trans->c;
15214b393eeSKent Overstreet 	struct snapshot_t *t;
15314b393eeSKent Overstreet 
15414b393eeSKent Overstreet 	t = genradix_ptr_alloc(&c->snapshots,
15514b393eeSKent Overstreet 			       U32_MAX - new.k->p.offset,
15614b393eeSKent Overstreet 			       GFP_KERNEL);
15714b393eeSKent Overstreet 	if (!t)
15865d48e35SKent Overstreet 		return -BCH_ERR_ENOMEM_mark_snapshot;
15914b393eeSKent Overstreet 
16014b393eeSKent Overstreet 	if (new.k->type == KEY_TYPE_snapshot) {
16114b393eeSKent Overstreet 		struct bkey_s_c_snapshot s = bkey_s_c_to_snapshot(new);
16214b393eeSKent Overstreet 
16314b393eeSKent Overstreet 		t->parent	= le32_to_cpu(s.v->parent);
16414b393eeSKent Overstreet 		t->children[0]	= le32_to_cpu(s.v->children[0]);
16514b393eeSKent Overstreet 		t->children[1]	= le32_to_cpu(s.v->children[1]);
16614b393eeSKent Overstreet 		t->subvol	= BCH_SNAPSHOT_SUBVOL(s.v) ? le32_to_cpu(s.v->subvol) : 0;
1671c59b483SKent Overstreet 		t->tree		= le32_to_cpu(s.v->tree);
16814b393eeSKent Overstreet 	} else {
16914b393eeSKent Overstreet 		t->parent	= 0;
17014b393eeSKent Overstreet 		t->children[0]	= 0;
17114b393eeSKent Overstreet 		t->children[1]	= 0;
17214b393eeSKent Overstreet 		t->subvol	= 0;
1731c59b483SKent Overstreet 		t->tree		= 0;
17414b393eeSKent Overstreet 	}
17514b393eeSKent Overstreet 
17614b393eeSKent Overstreet 	return 0;
17714b393eeSKent Overstreet }
17814b393eeSKent Overstreet 
17914b393eeSKent Overstreet static int snapshot_lookup(struct btree_trans *trans, u32 id,
18014b393eeSKent Overstreet 			   struct bch_snapshot *s)
18114b393eeSKent Overstreet {
182bcb79a51SKent Overstreet 	return bch2_bkey_get_val_typed(trans, BTREE_ID_snapshots, POS(0, id),
183bcb79a51SKent Overstreet 				       BTREE_ITER_WITH_UPDATES, snapshot, s);
18414b393eeSKent Overstreet }
18514b393eeSKent Overstreet 
18614b393eeSKent Overstreet static int snapshot_live(struct btree_trans *trans, u32 id)
18714b393eeSKent Overstreet {
18814b393eeSKent Overstreet 	struct bch_snapshot v;
18914b393eeSKent Overstreet 	int ret;
19014b393eeSKent Overstreet 
19114b393eeSKent Overstreet 	if (!id)
19214b393eeSKent Overstreet 		return 0;
19314b393eeSKent Overstreet 
194a1783320SKent Overstreet 	ret = snapshot_lookup(trans, id, &v);
1951c59b483SKent Overstreet 	if (bch2_err_matches(ret, ENOENT))
19614b393eeSKent Overstreet 		bch_err(trans->c, "snapshot node %u not found", id);
19714b393eeSKent Overstreet 	if (ret)
19814b393eeSKent Overstreet 		return ret;
19914b393eeSKent Overstreet 
20014b393eeSKent Overstreet 	return !BCH_SNAPSHOT_DELETED(&v);
20114b393eeSKent Overstreet }
20214b393eeSKent Overstreet 
203a1783320SKent Overstreet static int bch2_snapshot_set_equiv(struct btree_trans *trans, struct bkey_s_c k)
20414b393eeSKent Overstreet {
20514b393eeSKent Overstreet 	struct bch_fs *c = trans->c;
20635f1a503SKent Overstreet 	unsigned i, nr_live = 0, live_idx = 0;
207a1783320SKent Overstreet 	struct bkey_s_c_snapshot snap;
208a1783320SKent Overstreet 	u32 id = k.k->p.offset, child[2];
209a1783320SKent Overstreet 
210a1783320SKent Overstreet 	if (k.k->type != KEY_TYPE_snapshot)
211a1783320SKent Overstreet 		return 0;
212a1783320SKent Overstreet 
213a1783320SKent Overstreet 	snap = bkey_s_c_to_snapshot(k);
214a1783320SKent Overstreet 
215a1783320SKent Overstreet 	child[0] = le32_to_cpu(snap.v->children[0]);
216a1783320SKent Overstreet 	child[1] = le32_to_cpu(snap.v->children[1]);
21714b393eeSKent Overstreet 
21814b393eeSKent Overstreet 	for (i = 0; i < 2; i++) {
21935f1a503SKent Overstreet 		int ret = snapshot_live(trans, child[i]);
220a1019576SKent Overstreet 
22114b393eeSKent Overstreet 		if (ret < 0)
22235f1a503SKent Overstreet 			return ret;
22314b393eeSKent Overstreet 
22414b393eeSKent Overstreet 		if (ret)
22514b393eeSKent Overstreet 			live_idx = i;
22614b393eeSKent Overstreet 		nr_live += ret;
22714b393eeSKent Overstreet 	}
22814b393eeSKent Overstreet 
22914b393eeSKent Overstreet 	snapshot_t(c, id)->equiv = nr_live == 1
23014b393eeSKent Overstreet 		? snapshot_t(c, child[live_idx])->equiv
23114b393eeSKent Overstreet 		: id;
23235f1a503SKent Overstreet 	return 0;
23314b393eeSKent Overstreet }
23435f1a503SKent Overstreet 
23514b393eeSKent Overstreet /* fsck: */
2361c59b483SKent Overstreet 
2371c59b483SKent Overstreet static u32 bch2_snapshot_child(struct bch_fs *c, u32 id, unsigned child)
2381c59b483SKent Overstreet {
2391c59b483SKent Overstreet 	return snapshot_t(c, id)->children[child];
2401c59b483SKent Overstreet }
2411c59b483SKent Overstreet 
2421c59b483SKent Overstreet static u32 bch2_snapshot_left_child(struct bch_fs *c, u32 id)
2431c59b483SKent Overstreet {
2441c59b483SKent Overstreet 	return bch2_snapshot_child(c, id, 0);
2451c59b483SKent Overstreet }
2461c59b483SKent Overstreet 
2471c59b483SKent Overstreet static u32 bch2_snapshot_right_child(struct bch_fs *c, u32 id)
2481c59b483SKent Overstreet {
2491c59b483SKent Overstreet 	return bch2_snapshot_child(c, id, 1);
2501c59b483SKent Overstreet }
2511c59b483SKent Overstreet 
2521c59b483SKent Overstreet static u32 bch2_snapshot_tree_next(struct bch_fs *c, u32 id)
2531c59b483SKent Overstreet {
2541c59b483SKent Overstreet 	u32 n, parent;
2551c59b483SKent Overstreet 
2561c59b483SKent Overstreet 	n = bch2_snapshot_left_child(c, id);
2571c59b483SKent Overstreet 	if (n)
2581c59b483SKent Overstreet 		return n;
2591c59b483SKent Overstreet 
2601c59b483SKent Overstreet 	while ((parent = bch2_snapshot_parent(c, id))) {
2611c59b483SKent Overstreet 		n = bch2_snapshot_right_child(c, parent);
2621c59b483SKent Overstreet 		if (n && n != id)
2631c59b483SKent Overstreet 			return n;
2641c59b483SKent Overstreet 		id = parent;
2651c59b483SKent Overstreet 	}
2661c59b483SKent Overstreet 
2671c59b483SKent Overstreet 	return 0;
2681c59b483SKent Overstreet }
2691c59b483SKent Overstreet 
2701c59b483SKent Overstreet static u32 bch2_snapshot_tree_oldest_subvol(struct bch_fs *c, u32 snapshot_root)
2711c59b483SKent Overstreet {
2721c59b483SKent Overstreet 	u32 id = snapshot_root;
2731c59b483SKent Overstreet 	u32 subvol = 0, s;
2741c59b483SKent Overstreet 
2751c59b483SKent Overstreet 	while (id) {
2761c59b483SKent Overstreet 		s = snapshot_t(c, id)->subvol;
2771c59b483SKent Overstreet 
2781c59b483SKent Overstreet 		if (s && (!subvol || s < subvol))
2791c59b483SKent Overstreet 			subvol = s;
2801c59b483SKent Overstreet 
2811c59b483SKent Overstreet 		id = bch2_snapshot_tree_next(c, id);
2821c59b483SKent Overstreet 	}
2831c59b483SKent Overstreet 
2841c59b483SKent Overstreet 	return subvol;
2851c59b483SKent Overstreet }
2861c59b483SKent Overstreet 
2871c59b483SKent Overstreet static int bch2_snapshot_tree_master_subvol(struct btree_trans *trans,
2881c59b483SKent Overstreet 					    u32 snapshot_root, u32 *subvol_id)
2891c59b483SKent Overstreet {
2901c59b483SKent Overstreet 	struct bch_fs *c = trans->c;
2911c59b483SKent Overstreet 	struct btree_iter iter;
2921c59b483SKent Overstreet 	struct bkey_s_c k;
2931c59b483SKent Overstreet 	struct bkey_s_c_subvolume s;
294e47a390aSKent Overstreet 	bool found = false;
2951c59b483SKent Overstreet 	int ret;
2961c59b483SKent Overstreet 
2971c59b483SKent Overstreet 	for_each_btree_key_norestart(trans, iter, BTREE_ID_subvolumes, POS_MIN,
2981c59b483SKent Overstreet 				     0, k, ret) {
2991c59b483SKent Overstreet 		if (k.k->type != KEY_TYPE_subvolume)
3001c59b483SKent Overstreet 			continue;
3011c59b483SKent Overstreet 
3021c59b483SKent Overstreet 		s = bkey_s_c_to_subvolume(k);
3031c59b483SKent Overstreet 		if (!bch2_snapshot_is_ancestor(c, le32_to_cpu(s.v->snapshot), snapshot_root))
3041c59b483SKent Overstreet 			continue;
3051c59b483SKent Overstreet 		if (!BCH_SUBVOLUME_SNAP(s.v)) {
3061c59b483SKent Overstreet 			*subvol_id = s.k->p.offset;
307e47a390aSKent Overstreet 			found = true;
308e47a390aSKent Overstreet 			break;
3091c59b483SKent Overstreet 		}
3101c59b483SKent Overstreet 	}
311e47a390aSKent Overstreet 
3121c59b483SKent Overstreet 	bch2_trans_iter_exit(trans, &iter);
3131c59b483SKent Overstreet 
314e47a390aSKent Overstreet 	if (!ret && !found) {
3151c59b483SKent Overstreet 		struct bkey_i_subvolume *s;
3161c59b483SKent Overstreet 
3171c59b483SKent Overstreet 		*subvol_id = bch2_snapshot_tree_oldest_subvol(c, snapshot_root);
3181c59b483SKent Overstreet 
3191c59b483SKent Overstreet 		s = bch2_bkey_get_mut_typed(trans, &iter,
3201c59b483SKent Overstreet 					    BTREE_ID_subvolumes, POS(0, *subvol_id),
3211c59b483SKent Overstreet 					    0, subvolume);
3221c59b483SKent Overstreet 		ret = PTR_ERR_OR_ZERO(s);
3231c59b483SKent Overstreet 		if (ret)
3241c59b483SKent Overstreet 			return ret;
3251c59b483SKent Overstreet 
3261c59b483SKent Overstreet 		SET_BCH_SUBVOLUME_SNAP(&s->v, false);
3271c59b483SKent Overstreet 	}
3281c59b483SKent Overstreet 
3291c59b483SKent Overstreet 	return ret;
3301c59b483SKent Overstreet }
3311c59b483SKent Overstreet 
3321c59b483SKent Overstreet static int check_snapshot_tree(struct btree_trans *trans,
3331c59b483SKent Overstreet 			       struct btree_iter *iter,
3341c59b483SKent Overstreet 			       struct bkey_s_c k)
3351c59b483SKent Overstreet {
3361c59b483SKent Overstreet 	struct bch_fs *c = trans->c;
3371c59b483SKent Overstreet 	struct bkey_s_c_snapshot_tree st;
3381c59b483SKent Overstreet 	struct bch_snapshot s;
3391c59b483SKent Overstreet 	struct bch_subvolume subvol;
3401c59b483SKent Overstreet 	struct printbuf buf = PRINTBUF;
3411c59b483SKent Overstreet 	u32 root_id;
3421c59b483SKent Overstreet 	int ret;
3431c59b483SKent Overstreet 
3441c59b483SKent Overstreet 	if (k.k->type != KEY_TYPE_snapshot_tree)
3451c59b483SKent Overstreet 		return 0;
3461c59b483SKent Overstreet 
3471c59b483SKent Overstreet 	st = bkey_s_c_to_snapshot_tree(k);
3481c59b483SKent Overstreet 	root_id = le32_to_cpu(st.v->root_snapshot);
3491c59b483SKent Overstreet 
3501c59b483SKent Overstreet 	ret = snapshot_lookup(trans, root_id, &s);
3511c59b483SKent Overstreet 	if (ret && !bch2_err_matches(ret, ENOENT))
3521c59b483SKent Overstreet 		goto err;
3531c59b483SKent Overstreet 
3541c59b483SKent Overstreet 	if (fsck_err_on(ret ||
3551c59b483SKent Overstreet 			root_id != bch2_snapshot_root(c, root_id) ||
3561c59b483SKent Overstreet 			st.k->p.offset != le32_to_cpu(s.tree),
3571c59b483SKent Overstreet 			c,
3581c59b483SKent Overstreet 			"snapshot tree points to missing/incorrect snapshot:\n  %s",
3591c59b483SKent Overstreet 			(bch2_bkey_val_to_text(&buf, c, st.s_c), buf.buf))) {
3601c59b483SKent Overstreet 		ret = bch2_btree_delete_at(trans, iter, 0);
3611c59b483SKent Overstreet 		goto err;
3621c59b483SKent Overstreet 	}
3631c59b483SKent Overstreet 
3641c59b483SKent Overstreet 	ret = bch2_subvolume_get(trans, le32_to_cpu(st.v->master_subvol),
3651c59b483SKent Overstreet 				 false, 0, &subvol);
3661c59b483SKent Overstreet 	if (ret && !bch2_err_matches(ret, ENOENT))
3671c59b483SKent Overstreet 		goto err;
3681c59b483SKent Overstreet 
3691c59b483SKent Overstreet 	if (fsck_err_on(ret, c,
3701c59b483SKent Overstreet 			"snapshot tree points to missing subvolume:\n  %s",
3711c59b483SKent Overstreet 			(printbuf_reset(&buf),
3721c59b483SKent Overstreet 			 bch2_bkey_val_to_text(&buf, c, st.s_c), buf.buf)) ||
3731c59b483SKent Overstreet 	    fsck_err_on(!bch2_snapshot_is_ancestor(c,
3741c59b483SKent Overstreet 						   le32_to_cpu(subvol.snapshot),
3751c59b483SKent Overstreet 						   root_id), c,
3761c59b483SKent Overstreet 			"snapshot tree points to subvolume that does not point to snapshot in this tree:\n  %s",
3771c59b483SKent Overstreet 			(printbuf_reset(&buf),
3781c59b483SKent Overstreet 			 bch2_bkey_val_to_text(&buf, c, st.s_c), buf.buf)) ||
3791c59b483SKent Overstreet 	    fsck_err_on(BCH_SUBVOLUME_SNAP(&subvol), c,
3801c59b483SKent Overstreet 			"snapshot tree points to snapshot subvolume:\n  %s",
3811c59b483SKent Overstreet 			(printbuf_reset(&buf),
3821c59b483SKent Overstreet 			 bch2_bkey_val_to_text(&buf, c, st.s_c), buf.buf))) {
3831c59b483SKent Overstreet 		struct bkey_i_snapshot_tree *u;
3841c59b483SKent Overstreet 		u32 subvol_id;
3851c59b483SKent Overstreet 
3861c59b483SKent Overstreet 		ret = bch2_snapshot_tree_master_subvol(trans, root_id, &subvol_id);
3871c59b483SKent Overstreet 		if (ret)
3881c59b483SKent Overstreet 			goto err;
3891c59b483SKent Overstreet 
3900fb3355dSKent Overstreet 		u = bch2_bkey_make_mut_typed(trans, iter, &k, 0, snapshot_tree);
3911c59b483SKent Overstreet 		ret = PTR_ERR_OR_ZERO(u);
3921c59b483SKent Overstreet 		if (ret)
3931c59b483SKent Overstreet 			goto err;
3941c59b483SKent Overstreet 
3951c59b483SKent Overstreet 		u->v.master_subvol = cpu_to_le32(subvol_id);
3961c59b483SKent Overstreet 		st = snapshot_tree_i_to_s_c(u);
3971c59b483SKent Overstreet 	}
3981c59b483SKent Overstreet err:
3991c59b483SKent Overstreet fsck_err:
4001c59b483SKent Overstreet 	printbuf_exit(&buf);
4011c59b483SKent Overstreet 	return ret;
4021c59b483SKent Overstreet }
4031c59b483SKent Overstreet 
4041c59b483SKent Overstreet /*
4051c59b483SKent Overstreet  * For each snapshot_tree, make sure it points to the root of a snapshot tree
4061c59b483SKent Overstreet  * and that snapshot entry points back to it, or delete it.
4071c59b483SKent Overstreet  *
4081c59b483SKent Overstreet  * And, make sure it points to a subvolume within that snapshot tree, or correct
4091c59b483SKent Overstreet  * it to point to the oldest subvolume within that snapshot tree.
4101c59b483SKent Overstreet  */
411*067d228bSKent Overstreet int bch2_check_snapshot_trees(struct bch_fs *c)
4121c59b483SKent Overstreet {
4131c59b483SKent Overstreet 	struct btree_iter iter;
4141c59b483SKent Overstreet 	struct bkey_s_c k;
4151c59b483SKent Overstreet 	int ret;
4161c59b483SKent Overstreet 
4171c59b483SKent Overstreet 	ret = bch2_trans_run(c,
4181c59b483SKent Overstreet 		for_each_btree_key_commit(&trans, iter,
4191c59b483SKent Overstreet 			BTREE_ID_snapshot_trees, POS_MIN,
4201c59b483SKent Overstreet 			BTREE_ITER_PREFETCH, k,
4211c59b483SKent Overstreet 			NULL, NULL, BTREE_INSERT_LAZY_RW|BTREE_INSERT_NOFAIL,
4221c59b483SKent Overstreet 		check_snapshot_tree(&trans, &iter, k)));
4231c59b483SKent Overstreet 
4241c59b483SKent Overstreet 	if (ret)
4251c59b483SKent Overstreet 		bch_err(c, "error %i checking snapshot trees", ret);
4261c59b483SKent Overstreet 	return ret;
4271c59b483SKent Overstreet }
4281c59b483SKent Overstreet 
4291c59b483SKent Overstreet /*
4301c59b483SKent Overstreet  * Look up snapshot tree for @tree_id and find root,
4311c59b483SKent Overstreet  * make sure @snap_id is a descendent:
4321c59b483SKent Overstreet  */
4331c59b483SKent Overstreet static int snapshot_tree_ptr_good(struct btree_trans *trans,
4341c59b483SKent Overstreet 				  u32 snap_id, u32 tree_id)
4351c59b483SKent Overstreet {
4361c59b483SKent Overstreet 	struct bch_snapshot_tree s_t;
437cb1b479dSKent Overstreet 	int ret = bch2_snapshot_tree_lookup(trans, tree_id, &s_t);
4381c59b483SKent Overstreet 
4391c59b483SKent Overstreet 	if (bch2_err_matches(ret, ENOENT))
4401c59b483SKent Overstreet 		return 0;
4411c59b483SKent Overstreet 	if (ret)
4421c59b483SKent Overstreet 		return ret;
4431c59b483SKent Overstreet 
4441c59b483SKent Overstreet 	return bch2_snapshot_is_ancestor(trans->c, snap_id, le32_to_cpu(s_t.root_snapshot));
4451c59b483SKent Overstreet }
4461c59b483SKent Overstreet 
4471c59b483SKent Overstreet /*
4481c59b483SKent Overstreet  * snapshot_tree pointer was incorrect: look up root snapshot node, make sure
4491c59b483SKent Overstreet  * its snapshot_tree pointer is correct (allocate new one if necessary), then
4501c59b483SKent Overstreet  * update this node's pointer to root node's pointer:
4511c59b483SKent Overstreet  */
4521c59b483SKent Overstreet static int snapshot_tree_ptr_repair(struct btree_trans *trans,
4531c59b483SKent Overstreet 				    struct btree_iter *iter,
4541c59b483SKent Overstreet 				    struct bkey_s_c_snapshot *s)
4551c59b483SKent Overstreet {
4561c59b483SKent Overstreet 	struct bch_fs *c = trans->c;
4571c59b483SKent Overstreet 	struct btree_iter root_iter;
4581c59b483SKent Overstreet 	struct bch_snapshot_tree s_t;
4591c59b483SKent Overstreet 	struct bkey_s_c_snapshot root;
4601c59b483SKent Overstreet 	struct bkey_i_snapshot *u;
4611c59b483SKent Overstreet 	u32 root_id = bch2_snapshot_root(c, s->k->p.offset), tree_id;
4621c59b483SKent Overstreet 	int ret;
4631c59b483SKent Overstreet 
4641c59b483SKent Overstreet 	root = bch2_bkey_get_iter_typed(trans, &root_iter,
4651c59b483SKent Overstreet 			       BTREE_ID_snapshots, POS(0, root_id),
4661c59b483SKent Overstreet 			       BTREE_ITER_WITH_UPDATES, snapshot);
4671c59b483SKent Overstreet 	ret = bkey_err(root);
4681c59b483SKent Overstreet 	if (ret)
4691c59b483SKent Overstreet 		goto err;
4701c59b483SKent Overstreet 
4711c59b483SKent Overstreet 	tree_id = le32_to_cpu(root.v->tree);
4721c59b483SKent Overstreet 
473cb1b479dSKent Overstreet 	ret = bch2_snapshot_tree_lookup(trans, tree_id, &s_t);
4741c59b483SKent Overstreet 	if (ret && !bch2_err_matches(ret, ENOENT))
4751c59b483SKent Overstreet 		return ret;
4761c59b483SKent Overstreet 
4771c59b483SKent Overstreet 	if (ret || le32_to_cpu(s_t.root_snapshot) != root_id) {
4780fb3355dSKent Overstreet 		u = bch2_bkey_make_mut_typed(trans, &root_iter, &root.s_c, 0, snapshot);
4791c59b483SKent Overstreet 		ret =   PTR_ERR_OR_ZERO(u) ?:
4801c59b483SKent Overstreet 			snapshot_tree_create(trans, root_id,
4811c59b483SKent Overstreet 				bch2_snapshot_tree_oldest_subvol(c, root_id),
4821c59b483SKent Overstreet 				&tree_id);
4831c59b483SKent Overstreet 		if (ret)
4841c59b483SKent Overstreet 			goto err;
4851c59b483SKent Overstreet 
4861c59b483SKent Overstreet 		u->v.tree = cpu_to_le32(tree_id);
4871c59b483SKent Overstreet 		if (s->k->p.snapshot == root_id)
4881c59b483SKent Overstreet 			*s = snapshot_i_to_s_c(u);
4891c59b483SKent Overstreet 	}
4901c59b483SKent Overstreet 
4911c59b483SKent Overstreet 	if (s->k->p.snapshot != root_id) {
4920fb3355dSKent Overstreet 		u = bch2_bkey_make_mut_typed(trans, iter, &s->s_c, 0, snapshot);
4931c59b483SKent Overstreet 		ret = PTR_ERR_OR_ZERO(u);
4941c59b483SKent Overstreet 		if (ret)
4951c59b483SKent Overstreet 			goto err;
4961c59b483SKent Overstreet 
4971c59b483SKent Overstreet 		u->v.tree = cpu_to_le32(tree_id);
4981c59b483SKent Overstreet 		*s = snapshot_i_to_s_c(u);
4991c59b483SKent Overstreet 	}
5001c59b483SKent Overstreet err:
5011c59b483SKent Overstreet 	bch2_trans_iter_exit(trans, &root_iter);
5021c59b483SKent Overstreet 	return ret;
5031c59b483SKent Overstreet }
5041c59b483SKent Overstreet 
50535f1a503SKent Overstreet static int check_snapshot(struct btree_trans *trans,
506a1783320SKent Overstreet 			  struct btree_iter *iter,
507a1783320SKent Overstreet 			  struct bkey_s_c k)
50814b393eeSKent Overstreet {
50935f1a503SKent Overstreet 	struct bch_fs *c = trans->c;
51035f1a503SKent Overstreet 	struct bkey_s_c_snapshot s;
51114b393eeSKent Overstreet 	struct bch_subvolume subvol;
51214b393eeSKent Overstreet 	struct bch_snapshot v;
51335f1a503SKent Overstreet 	struct printbuf buf = PRINTBUF;
51435f1a503SKent Overstreet 	bool should_have_subvol;
51514b393eeSKent Overstreet 	u32 i, id;
51635f1a503SKent Overstreet 	int ret = 0;
51714b393eeSKent Overstreet 
51835f1a503SKent Overstreet 	if (k.k->type != KEY_TYPE_snapshot)
51935f1a503SKent Overstreet 		return 0;
52014b393eeSKent Overstreet 
52135f1a503SKent Overstreet 	s = bkey_s_c_to_snapshot(k);
52214b393eeSKent Overstreet 	id = le32_to_cpu(s.v->parent);
52314b393eeSKent Overstreet 	if (id) {
524a1783320SKent Overstreet 		ret = snapshot_lookup(trans, id, &v);
5251c59b483SKent Overstreet 		if (bch2_err_matches(ret, ENOENT))
52635f1a503SKent Overstreet 			bch_err(c, "snapshot with nonexistent parent:\n  %s",
52735f1a503SKent Overstreet 				(bch2_bkey_val_to_text(&buf, c, s.s_c), buf.buf));
52814b393eeSKent Overstreet 		if (ret)
52935f1a503SKent Overstreet 			goto err;
53014b393eeSKent Overstreet 
53114b393eeSKent Overstreet 		if (le32_to_cpu(v.children[0]) != s.k->p.offset &&
53214b393eeSKent Overstreet 		    le32_to_cpu(v.children[1]) != s.k->p.offset) {
53335f1a503SKent Overstreet 			bch_err(c, "snapshot parent %u missing pointer to child %llu",
53414b393eeSKent Overstreet 				id, s.k->p.offset);
53535f1a503SKent Overstreet 			ret = -EINVAL;
53635f1a503SKent Overstreet 			goto err;
53714b393eeSKent Overstreet 		}
53814b393eeSKent Overstreet 	}
53914b393eeSKent Overstreet 
54014b393eeSKent Overstreet 	for (i = 0; i < 2 && s.v->children[i]; i++) {
54114b393eeSKent Overstreet 		id = le32_to_cpu(s.v->children[i]);
54214b393eeSKent Overstreet 
543a1783320SKent Overstreet 		ret = snapshot_lookup(trans, id, &v);
5441c59b483SKent Overstreet 		if (bch2_err_matches(ret, ENOENT))
54535f1a503SKent Overstreet 			bch_err(c, "snapshot node %llu has nonexistent child %u",
54614b393eeSKent Overstreet 				s.k->p.offset, id);
54714b393eeSKent Overstreet 		if (ret)
54835f1a503SKent Overstreet 			goto err;
54914b393eeSKent Overstreet 
55014b393eeSKent Overstreet 		if (le32_to_cpu(v.parent) != s.k->p.offset) {
55135f1a503SKent Overstreet 			bch_err(c, "snapshot child %u has wrong parent (got %u should be %llu)",
55214b393eeSKent Overstreet 				id, le32_to_cpu(v.parent), s.k->p.offset);
55335f1a503SKent Overstreet 			ret = -EINVAL;
55435f1a503SKent Overstreet 			goto err;
55514b393eeSKent Overstreet 		}
55614b393eeSKent Overstreet 	}
55714b393eeSKent Overstreet 
55835f1a503SKent Overstreet 	should_have_subvol = BCH_SNAPSHOT_SUBVOL(s.v) &&
55935f1a503SKent Overstreet 		!BCH_SNAPSHOT_DELETED(s.v);
56035f1a503SKent Overstreet 
56135f1a503SKent Overstreet 	if (should_have_subvol) {
56235f1a503SKent Overstreet 		id = le32_to_cpu(s.v->subvol);
563a1783320SKent Overstreet 		ret = bch2_subvolume_get(trans, id, 0, false, &subvol);
5641c59b483SKent Overstreet 		if (bch2_err_matches(ret, ENOENT))
56535f1a503SKent Overstreet 			bch_err(c, "snapshot points to nonexistent subvolume:\n  %s",
56635f1a503SKent Overstreet 				(bch2_bkey_val_to_text(&buf, c, s.s_c), buf.buf));
56735f1a503SKent Overstreet 		if (ret)
56835f1a503SKent Overstreet 			goto err;
56935f1a503SKent Overstreet 
57035f1a503SKent Overstreet 		if (BCH_SNAPSHOT_SUBVOL(s.v) != (le32_to_cpu(subvol.snapshot) == s.k->p.offset)) {
57135f1a503SKent Overstreet 			bch_err(c, "snapshot node %llu has wrong BCH_SNAPSHOT_SUBVOL",
57235f1a503SKent Overstreet 				s.k->p.offset);
57335f1a503SKent Overstreet 			ret = -EINVAL;
57435f1a503SKent Overstreet 			goto err;
57535f1a503SKent Overstreet 		}
57635f1a503SKent Overstreet 	} else {
57735f1a503SKent Overstreet 		if (fsck_err_on(s.v->subvol, c, "snapshot should not point to subvol:\n  %s",
57835f1a503SKent Overstreet 				(bch2_bkey_val_to_text(&buf, c, s.s_c), buf.buf))) {
57935f1a503SKent Overstreet 			struct bkey_i_snapshot *u = bch2_trans_kmalloc(trans, sizeof(*u));
58035f1a503SKent Overstreet 
58135f1a503SKent Overstreet 			ret = PTR_ERR_OR_ZERO(u);
58235f1a503SKent Overstreet 			if (ret)
58335f1a503SKent Overstreet 				goto err;
58435f1a503SKent Overstreet 
58535f1a503SKent Overstreet 			bkey_reassemble(&u->k_i, s.s_c);
58635f1a503SKent Overstreet 			u->v.subvol = 0;
58735f1a503SKent Overstreet 			ret = bch2_trans_update(trans, iter, &u->k_i, 0);
58835f1a503SKent Overstreet 			if (ret)
58935f1a503SKent Overstreet 				goto err;
5901c59b483SKent Overstreet 
5911c59b483SKent Overstreet 			s = snapshot_i_to_s_c(u);
59235f1a503SKent Overstreet 		}
59335f1a503SKent Overstreet 	}
59435f1a503SKent Overstreet 
5951c59b483SKent Overstreet 	ret = snapshot_tree_ptr_good(trans, s.k->p.offset, le32_to_cpu(s.v->tree));
5961c59b483SKent Overstreet 	if (ret < 0)
5971c59b483SKent Overstreet 		goto err;
5981c59b483SKent Overstreet 
5991c59b483SKent Overstreet 	if (fsck_err_on(!ret, c, "snapshot points to missing/incorrect tree:\n  %s",
6001c59b483SKent Overstreet 			(bch2_bkey_val_to_text(&buf, c, s.s_c), buf.buf))) {
6011c59b483SKent Overstreet 		ret = snapshot_tree_ptr_repair(trans, iter, &s);
6021c59b483SKent Overstreet 		if (ret)
6031c59b483SKent Overstreet 			goto err;
6041c59b483SKent Overstreet 	}
6051c59b483SKent Overstreet 	ret = 0;
6061c59b483SKent Overstreet 
60735f1a503SKent Overstreet 	if (BCH_SNAPSHOT_DELETED(s.v))
60835f1a503SKent Overstreet 		set_bit(BCH_FS_HAVE_DELETED_SNAPSHOTS, &c->flags);
60935f1a503SKent Overstreet err:
61035f1a503SKent Overstreet fsck_err:
61135f1a503SKent Overstreet 	printbuf_exit(&buf);
61235f1a503SKent Overstreet 	return ret;
61314b393eeSKent Overstreet }
61414b393eeSKent Overstreet 
615*067d228bSKent Overstreet int bch2_check_snapshots(struct bch_fs *c)
61614b393eeSKent Overstreet {
61714b393eeSKent Overstreet 	struct btree_iter iter;
618a1783320SKent Overstreet 	struct bkey_s_c k;
61914b393eeSKent Overstreet 	int ret;
62014b393eeSKent Overstreet 
6211c59b483SKent Overstreet 	ret = bch2_trans_run(c,
6221c59b483SKent Overstreet 		for_each_btree_key_commit(&trans, iter,
623c59d66b5SKent Overstreet 			BTREE_ID_snapshots, POS_MIN,
624a1783320SKent Overstreet 			BTREE_ITER_PREFETCH, k,
625a1783320SKent Overstreet 			NULL, NULL, BTREE_INSERT_LAZY_RW|BTREE_INSERT_NOFAIL,
6261c59b483SKent Overstreet 		check_snapshot(&trans, &iter, k)));
62735f1a503SKent Overstreet 	if (ret)
6281bb3c2a9SKent Overstreet 		bch_err_fn(c, ret);
62914b393eeSKent Overstreet 	return ret;
63014b393eeSKent Overstreet }
63114b393eeSKent Overstreet 
6324ab35c34SKent Overstreet static int check_subvol(struct btree_trans *trans,
6336738dd19SKent Overstreet 			struct btree_iter *iter,
6346738dd19SKent Overstreet 			struct bkey_s_c k)
6354ab35c34SKent Overstreet {
6361c59b483SKent Overstreet 	struct bch_fs *c = trans->c;
6374ab35c34SKent Overstreet 	struct bkey_s_c_subvolume subvol;
63835f1a503SKent Overstreet 	struct bch_snapshot snapshot;
63935f1a503SKent Overstreet 	unsigned snapid;
6401c59b483SKent Overstreet 	int ret = 0;
6414ab35c34SKent Overstreet 
6424ab35c34SKent Overstreet 	if (k.k->type != KEY_TYPE_subvolume)
6434ab35c34SKent Overstreet 		return 0;
6444ab35c34SKent Overstreet 
6454ab35c34SKent Overstreet 	subvol = bkey_s_c_to_subvolume(k);
64635f1a503SKent Overstreet 	snapid = le32_to_cpu(subvol.v->snapshot);
64735f1a503SKent Overstreet 	ret = snapshot_lookup(trans, snapid, &snapshot);
64835f1a503SKent Overstreet 
6491c59b483SKent Overstreet 	if (bch2_err_matches(ret, ENOENT))
6501c59b483SKent Overstreet 		bch_err(c, "subvolume %llu points to nonexistent snapshot %u",
65135f1a503SKent Overstreet 			k.k->p.offset, snapid);
65235f1a503SKent Overstreet 	if (ret)
65335f1a503SKent Overstreet 		return ret;
6544ab35c34SKent Overstreet 
6554ab35c34SKent Overstreet 	if (BCH_SUBVOLUME_UNLINKED(subvol.v)) {
656653693beSKent Overstreet 		bch2_fs_lazy_rw(c);
657653693beSKent Overstreet 
6584ab35c34SKent Overstreet 		ret = bch2_subvolume_delete(trans, iter->pos.offset);
659653693beSKent Overstreet 		if (ret)
6601c59b483SKent Overstreet 			bch_err(c, "error deleting subvolume %llu: %s",
661d4bf5eecSKent Overstreet 				iter->pos.offset, bch2_err_str(ret));
662653693beSKent Overstreet 		return ret ?: -BCH_ERR_transaction_restart_nested;
6634ab35c34SKent Overstreet 	}
6644ab35c34SKent Overstreet 
6651c59b483SKent Overstreet 	if (!BCH_SUBVOLUME_SNAP(subvol.v)) {
6661c59b483SKent Overstreet 		u32 snapshot_root = bch2_snapshot_root(c, le32_to_cpu(subvol.v->snapshot));
6671c59b483SKent Overstreet 		u32 snapshot_tree = snapshot_t(c, snapshot_root)->tree;
6681c59b483SKent Overstreet 		struct bch_snapshot_tree st;
6691c59b483SKent Overstreet 
670cb1b479dSKent Overstreet 		ret = bch2_snapshot_tree_lookup(trans, snapshot_tree, &st);
6711c59b483SKent Overstreet 
6721c59b483SKent Overstreet 		bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT), c,
6731c59b483SKent Overstreet 				"%s: snapshot tree %u not found", __func__, snapshot_tree);
6741c59b483SKent Overstreet 
6751c59b483SKent Overstreet 		if (ret)
6761c59b483SKent Overstreet 			return ret;
6771c59b483SKent Overstreet 
6781c59b483SKent Overstreet 		if (fsck_err_on(le32_to_cpu(st.master_subvol) != subvol.k->p.offset, c,
6791c59b483SKent Overstreet 				"subvolume %llu is not set as snapshot but is not master subvolume",
6801c59b483SKent Overstreet 				k.k->p.offset)) {
6811c59b483SKent Overstreet 			struct bkey_i_subvolume *s =
6820fb3355dSKent Overstreet 				bch2_bkey_make_mut_typed(trans, iter, &subvol.s_c, 0, subvolume);
6831c59b483SKent Overstreet 			ret = PTR_ERR_OR_ZERO(s);
6841c59b483SKent Overstreet 			if (ret)
6851c59b483SKent Overstreet 				return ret;
6861c59b483SKent Overstreet 
6871c59b483SKent Overstreet 			SET_BCH_SUBVOLUME_SNAP(&s->v, true);
6881c59b483SKent Overstreet 		}
6891c59b483SKent Overstreet 	}
6901c59b483SKent Overstreet 
6911c59b483SKent Overstreet fsck_err:
6921c59b483SKent Overstreet 	return ret;
6934ab35c34SKent Overstreet }
6944ab35c34SKent Overstreet 
695*067d228bSKent Overstreet int bch2_check_subvols(struct bch_fs *c)
6964ab35c34SKent Overstreet {
6974ab35c34SKent Overstreet 	struct btree_iter iter;
6986738dd19SKent Overstreet 	struct bkey_s_c k;
6994ab35c34SKent Overstreet 	int ret;
7004ab35c34SKent Overstreet 
7011c59b483SKent Overstreet 	ret = bch2_trans_run(c,
7021c59b483SKent Overstreet 		for_each_btree_key_commit(&trans, iter,
7036738dd19SKent Overstreet 			BTREE_ID_subvolumes, POS_MIN, BTREE_ITER_PREFETCH, k,
7046738dd19SKent Overstreet 			NULL, NULL, BTREE_INSERT_LAZY_RW|BTREE_INSERT_NOFAIL,
7051c59b483SKent Overstreet 		check_subvol(&trans, &iter, k)));
7061c59b483SKent Overstreet 	if (ret)
7071bb3c2a9SKent Overstreet 		bch_err_fn(c, ret);
7084ab35c34SKent Overstreet 	return ret;
7094ab35c34SKent Overstreet }
7104ab35c34SKent Overstreet 
71114b393eeSKent Overstreet void bch2_fs_snapshots_exit(struct bch_fs *c)
71214b393eeSKent Overstreet {
71314b393eeSKent Overstreet 	genradix_free(&c->snapshots);
71414b393eeSKent Overstreet }
71514b393eeSKent Overstreet 
716*067d228bSKent Overstreet int bch2_snapshots_read(struct bch_fs *c)
71714b393eeSKent Overstreet {
71814b393eeSKent Overstreet 	struct btree_iter iter;
71914b393eeSKent Overstreet 	struct bkey_s_c k;
72014b393eeSKent Overstreet 	int ret = 0;
72114b393eeSKent Overstreet 
7221c59b483SKent Overstreet 	ret = bch2_trans_run(c,
723a1783320SKent Overstreet 		for_each_btree_key2(&trans, iter, BTREE_ID_snapshots,
724a1783320SKent Overstreet 			   POS_MIN, 0, k,
7252611a041SKent Overstreet 			bch2_mark_snapshot(&trans, BTREE_ID_snapshots, 0, bkey_s_c_null, k, 0) ?:
7261c59b483SKent Overstreet 			bch2_snapshot_set_equiv(&trans, k)));
72735f1a503SKent Overstreet 	if (ret)
7281bb3c2a9SKent Overstreet 		bch_err_fn(c, ret);
72914b393eeSKent Overstreet 	return ret;
73014b393eeSKent Overstreet }
73114b393eeSKent Overstreet 
73214b393eeSKent Overstreet /*
73314b393eeSKent Overstreet  * Mark a snapshot as deleted, for future cleanup:
73414b393eeSKent Overstreet  */
73514b393eeSKent Overstreet static int bch2_snapshot_node_set_deleted(struct btree_trans *trans, u32 id)
73614b393eeSKent Overstreet {
73714b393eeSKent Overstreet 	struct btree_iter iter;
73814b393eeSKent Overstreet 	struct bkey_i_snapshot *s;
73914b393eeSKent Overstreet 	int ret = 0;
74014b393eeSKent Overstreet 
74134dfa5dbSKent Overstreet 	s = bch2_bkey_get_mut_typed(trans, &iter,
74234dfa5dbSKent Overstreet 				    BTREE_ID_snapshots, POS(0, id),
74334dfa5dbSKent Overstreet 				    0, snapshot);
744994ba475SKent Overstreet 	ret = PTR_ERR_OR_ZERO(s);
745994ba475SKent Overstreet 	if (unlikely(ret)) {
7461c59b483SKent Overstreet 		bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT),
7471c59b483SKent Overstreet 					trans->c, "missing snapshot %u", id);
748f12a798aSKent Overstreet 		return ret;
74914b393eeSKent Overstreet 	}
75014b393eeSKent Overstreet 
75114b393eeSKent Overstreet 	/* already deleted? */
752994ba475SKent Overstreet 	if (BCH_SNAPSHOT_DELETED(&s->v))
75314b393eeSKent Overstreet 		goto err;
75414b393eeSKent Overstreet 
75514b393eeSKent Overstreet 	SET_BCH_SNAPSHOT_DELETED(&s->v, true);
756416cc426SKent Overstreet 	SET_BCH_SNAPSHOT_SUBVOL(&s->v, false);
757416cc426SKent Overstreet 	s->v.subvol = 0;
75814b393eeSKent Overstreet err:
75914b393eeSKent Overstreet 	bch2_trans_iter_exit(trans, &iter);
76014b393eeSKent Overstreet 	return ret;
76114b393eeSKent Overstreet }
76214b393eeSKent Overstreet 
76314b393eeSKent Overstreet static int bch2_snapshot_node_delete(struct btree_trans *trans, u32 id)
76414b393eeSKent Overstreet {
765bcb79a51SKent Overstreet 	struct bch_fs *c = trans->c;
76614b393eeSKent Overstreet 	struct btree_iter iter, p_iter = (struct btree_iter) { NULL };
7671c59b483SKent Overstreet 	struct btree_iter tree_iter = (struct btree_iter) { NULL };
76814b393eeSKent Overstreet 	struct bkey_s_c_snapshot s;
76914b393eeSKent Overstreet 	u32 parent_id;
77014b393eeSKent Overstreet 	unsigned i;
77114b393eeSKent Overstreet 	int ret = 0;
77214b393eeSKent Overstreet 
773bcb79a51SKent Overstreet 	s = bch2_bkey_get_iter_typed(trans, &iter, BTREE_ID_snapshots, POS(0, id),
774bcb79a51SKent Overstreet 				     BTREE_ITER_INTENT, snapshot);
775bcb79a51SKent Overstreet 	ret = bkey_err(s);
7761c59b483SKent Overstreet 	bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT), c,
7771c59b483SKent Overstreet 				"missing snapshot %u", id);
778bcb79a51SKent Overstreet 
77914b393eeSKent Overstreet 	if (ret)
78014b393eeSKent Overstreet 		goto err;
78114b393eeSKent Overstreet 
78214b393eeSKent Overstreet 	BUG_ON(!BCH_SNAPSHOT_DELETED(s.v));
78314b393eeSKent Overstreet 	parent_id = le32_to_cpu(s.v->parent);
78414b393eeSKent Overstreet 
78514b393eeSKent Overstreet 	if (parent_id) {
786994ba475SKent Overstreet 		struct bkey_i_snapshot *parent;
787994ba475SKent Overstreet 
78834dfa5dbSKent Overstreet 		parent = bch2_bkey_get_mut_typed(trans, &p_iter,
78934dfa5dbSKent Overstreet 				     BTREE_ID_snapshots, POS(0, parent_id),
79034dfa5dbSKent Overstreet 				     0, snapshot);
791994ba475SKent Overstreet 		ret = PTR_ERR_OR_ZERO(parent);
792994ba475SKent Overstreet 		if (unlikely(ret)) {
7931c59b483SKent Overstreet 			bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT), c,
7941c59b483SKent Overstreet 						"missing snapshot %u", parent_id);
79514b393eeSKent Overstreet 			goto err;
79614b393eeSKent Overstreet 		}
79714b393eeSKent Overstreet 
79814b393eeSKent Overstreet 		for (i = 0; i < 2; i++)
79914b393eeSKent Overstreet 			if (le32_to_cpu(parent->v.children[i]) == id)
80014b393eeSKent Overstreet 				break;
80114b393eeSKent Overstreet 
80214b393eeSKent Overstreet 		if (i == 2)
803bcb79a51SKent Overstreet 			bch_err(c, "snapshot %u missing child pointer to %u",
80414b393eeSKent Overstreet 				parent_id, id);
80514b393eeSKent Overstreet 		else
80614b393eeSKent Overstreet 			parent->v.children[i] = 0;
80714b393eeSKent Overstreet 
80814b393eeSKent Overstreet 		if (le32_to_cpu(parent->v.children[0]) <
80914b393eeSKent Overstreet 		    le32_to_cpu(parent->v.children[1]))
81014b393eeSKent Overstreet 			swap(parent->v.children[0],
81114b393eeSKent Overstreet 			     parent->v.children[1]);
8121c59b483SKent Overstreet 	} else {
8131c59b483SKent Overstreet 		/*
8141c59b483SKent Overstreet 		 * We're deleting the root of a snapshot tree: update the
8151c59b483SKent Overstreet 		 * snapshot_tree entry to point to the new root, or delete it if
8161c59b483SKent Overstreet 		 * this is the last snapshot ID in this tree:
8171c59b483SKent Overstreet 		 */
8181c59b483SKent Overstreet 		struct bkey_i_snapshot_tree *s_t;
8191c59b483SKent Overstreet 
8201c59b483SKent Overstreet 		BUG_ON(s.v->children[1]);
8211c59b483SKent Overstreet 
8221c59b483SKent Overstreet 		s_t = bch2_bkey_get_mut_typed(trans, &tree_iter,
8231c59b483SKent Overstreet 				BTREE_ID_snapshot_trees, POS(0, le32_to_cpu(s.v->tree)),
8241c59b483SKent Overstreet 				0, snapshot_tree);
8251c59b483SKent Overstreet 		ret = PTR_ERR_OR_ZERO(s_t);
8261c59b483SKent Overstreet 		if (ret)
8271c59b483SKent Overstreet 			goto err;
8281c59b483SKent Overstreet 
8291c59b483SKent Overstreet 		if (s.v->children[0]) {
83073bd774dSKent Overstreet 			s_t->v.root_snapshot = s.v->children[0];
8311c59b483SKent Overstreet 		} else {
8321c59b483SKent Overstreet 			s_t->k.type = KEY_TYPE_deleted;
8331c59b483SKent Overstreet 			set_bkey_val_u64s(&s_t->k, 0);
8341c59b483SKent Overstreet 		}
83514b393eeSKent Overstreet 	}
83614b393eeSKent Overstreet 
83714b393eeSKent Overstreet 	ret = bch2_btree_delete_at(trans, &iter, 0);
83814b393eeSKent Overstreet err:
8391c59b483SKent Overstreet 	bch2_trans_iter_exit(trans, &tree_iter);
84014b393eeSKent Overstreet 	bch2_trans_iter_exit(trans, &p_iter);
84114b393eeSKent Overstreet 	bch2_trans_iter_exit(trans, &iter);
84214b393eeSKent Overstreet 	return ret;
84314b393eeSKent Overstreet }
84414b393eeSKent Overstreet 
8451c59b483SKent Overstreet static int create_snapids(struct btree_trans *trans, u32 parent, u32 tree,
84614b393eeSKent Overstreet 			  u32 *new_snapids,
84714b393eeSKent Overstreet 			  u32 *snapshot_subvols,
84814b393eeSKent Overstreet 			  unsigned nr_snapids)
84914b393eeSKent Overstreet {
8501c59b483SKent Overstreet 	struct btree_iter iter;
85114b393eeSKent Overstreet 	struct bkey_i_snapshot *n;
85214b393eeSKent Overstreet 	struct bkey_s_c k;
85314b393eeSKent Overstreet 	unsigned i;
8541c59b483SKent Overstreet 	int ret;
85514b393eeSKent Overstreet 
85614b393eeSKent Overstreet 	bch2_trans_iter_init(trans, &iter, BTREE_ID_snapshots,
85714b393eeSKent Overstreet 			     POS_MIN, BTREE_ITER_INTENT);
85814b393eeSKent Overstreet 	k = bch2_btree_iter_peek(&iter);
85914b393eeSKent Overstreet 	ret = bkey_err(k);
86014b393eeSKent Overstreet 	if (ret)
86114b393eeSKent Overstreet 		goto err;
86214b393eeSKent Overstreet 
86314b393eeSKent Overstreet 	for (i = 0; i < nr_snapids; i++) {
86414b393eeSKent Overstreet 		k = bch2_btree_iter_prev_slot(&iter);
86514b393eeSKent Overstreet 		ret = bkey_err(k);
86614b393eeSKent Overstreet 		if (ret)
86714b393eeSKent Overstreet 			goto err;
86814b393eeSKent Overstreet 
86914b393eeSKent Overstreet 		if (!k.k || !k.k->p.offset) {
870098ef98dSKent Overstreet 			ret = -BCH_ERR_ENOSPC_snapshot_create;
87114b393eeSKent Overstreet 			goto err;
87214b393eeSKent Overstreet 		}
87314b393eeSKent Overstreet 
874f8cb35fdSKent Overstreet 		n = bch2_bkey_alloc(trans, &iter, 0, snapshot);
87514b393eeSKent Overstreet 		ret = PTR_ERR_OR_ZERO(n);
87614b393eeSKent Overstreet 		if (ret)
87794a3e1a6SKent Overstreet 			goto err;
87814b393eeSKent Overstreet 
87914b393eeSKent Overstreet 		n->v.flags	= 0;
88014b393eeSKent Overstreet 		n->v.parent	= cpu_to_le32(parent);
88114b393eeSKent Overstreet 		n->v.subvol	= cpu_to_le32(snapshot_subvols[i]);
8821c59b483SKent Overstreet 		n->v.tree	= cpu_to_le32(tree);
88314b393eeSKent Overstreet 		SET_BCH_SNAPSHOT_SUBVOL(&n->v, true);
88414b393eeSKent Overstreet 
885f8cb35fdSKent Overstreet 		ret = bch2_mark_snapshot(trans, BTREE_ID_snapshots, 0,
886ae1f5623SKent Overstreet 					 bkey_s_c_null, bkey_i_to_s_c(&n->k_i), 0);
88714b393eeSKent Overstreet 		if (ret)
88894a3e1a6SKent Overstreet 			goto err;
88914b393eeSKent Overstreet 
89014b393eeSKent Overstreet 		new_snapids[i]	= iter.pos.offset;
89114b393eeSKent Overstreet 	}
8921c59b483SKent Overstreet err:
8931c59b483SKent Overstreet 	bch2_trans_iter_exit(trans, &iter);
8941c59b483SKent Overstreet 	return ret;
89514b393eeSKent Overstreet }
89614b393eeSKent Overstreet 
8971c59b483SKent Overstreet /*
8981c59b483SKent Overstreet  * Create new snapshot IDs as children of an existing snapshot ID:
8991c59b483SKent Overstreet  */
9001c59b483SKent Overstreet static int bch2_snapshot_node_create_children(struct btree_trans *trans, u32 parent,
9011c59b483SKent Overstreet 			      u32 *new_snapids,
9021c59b483SKent Overstreet 			      u32 *snapshot_subvols,
9031c59b483SKent Overstreet 			      unsigned nr_snapids)
9041c59b483SKent Overstreet {
9051c59b483SKent Overstreet 	struct btree_iter iter;
9061c59b483SKent Overstreet 	struct bkey_i_snapshot *n_parent;
9071c59b483SKent Overstreet 	int ret = 0;
9081c59b483SKent Overstreet 
9091c59b483SKent Overstreet 	n_parent = bch2_bkey_get_mut_typed(trans, &iter,
9101c59b483SKent Overstreet 			BTREE_ID_snapshots, POS(0, parent),
9111c59b483SKent Overstreet 			0, snapshot);
9121c59b483SKent Overstreet 	ret = PTR_ERR_OR_ZERO(n_parent);
9131c59b483SKent Overstreet 	if (unlikely(ret)) {
9141c59b483SKent Overstreet 		if (bch2_err_matches(ret, ENOENT))
9151c59b483SKent Overstreet 			bch_err(trans->c, "snapshot %u not found", parent);
9161c59b483SKent Overstreet 		return ret;
9171c59b483SKent Overstreet 	}
9181c59b483SKent Overstreet 
9191c59b483SKent Overstreet 	if (n_parent->v.children[0] || n_parent->v.children[1]) {
92014b393eeSKent Overstreet 		bch_err(trans->c, "Trying to add child snapshot nodes to parent that already has children");
92114b393eeSKent Overstreet 		ret = -EINVAL;
92214b393eeSKent Overstreet 		goto err;
92314b393eeSKent Overstreet 	}
92414b393eeSKent Overstreet 
9251c59b483SKent Overstreet 	ret = create_snapids(trans, parent, le32_to_cpu(n_parent->v.tree),
9261c59b483SKent Overstreet 			     new_snapids, snapshot_subvols, nr_snapids);
92794a3e1a6SKent Overstreet 	if (ret)
92894a3e1a6SKent Overstreet 		goto err;
9291c59b483SKent Overstreet 
9301c59b483SKent Overstreet 	n_parent->v.children[0] = cpu_to_le32(new_snapids[0]);
9311c59b483SKent Overstreet 	n_parent->v.children[1] = cpu_to_le32(new_snapids[1]);
9321c59b483SKent Overstreet 	n_parent->v.subvol = 0;
9331c59b483SKent Overstreet 	SET_BCH_SNAPSHOT_SUBVOL(&n_parent->v, false);
93414b393eeSKent Overstreet err:
93514b393eeSKent Overstreet 	bch2_trans_iter_exit(trans, &iter);
93614b393eeSKent Overstreet 	return ret;
93714b393eeSKent Overstreet }
93814b393eeSKent Overstreet 
9391c59b483SKent Overstreet /*
9401c59b483SKent Overstreet  * Create a snapshot node that is the root of a new tree:
9411c59b483SKent Overstreet  */
9421c59b483SKent Overstreet static int bch2_snapshot_node_create_tree(struct btree_trans *trans,
9431c59b483SKent Overstreet 			      u32 *new_snapids,
9441c59b483SKent Overstreet 			      u32 *snapshot_subvols,
9451c59b483SKent Overstreet 			      unsigned nr_snapids)
9461c59b483SKent Overstreet {
9471c59b483SKent Overstreet 	struct bkey_i_snapshot_tree *n_tree;
9481c59b483SKent Overstreet 	int ret;
9491c59b483SKent Overstreet 
9501c59b483SKent Overstreet 	n_tree = __snapshot_tree_create(trans);
9511c59b483SKent Overstreet 	ret =   PTR_ERR_OR_ZERO(n_tree) ?:
9521c59b483SKent Overstreet 		create_snapids(trans, 0, n_tree->k.p.offset,
9531c59b483SKent Overstreet 			     new_snapids, snapshot_subvols, nr_snapids);
9541c59b483SKent Overstreet 	if (ret)
9551c59b483SKent Overstreet 		return ret;
9561c59b483SKent Overstreet 
9571c59b483SKent Overstreet 	n_tree->v.master_subvol	= cpu_to_le32(snapshot_subvols[0]);
9581c59b483SKent Overstreet 	n_tree->v.root_snapshot	= cpu_to_le32(new_snapids[0]);
9591c59b483SKent Overstreet 	return 0;
9601c59b483SKent Overstreet }
9611c59b483SKent Overstreet 
9621c59b483SKent Overstreet int bch2_snapshot_node_create(struct btree_trans *trans, u32 parent,
9631c59b483SKent Overstreet 			      u32 *new_snapids,
9641c59b483SKent Overstreet 			      u32 *snapshot_subvols,
9651c59b483SKent Overstreet 			      unsigned nr_snapids)
9661c59b483SKent Overstreet {
9671c59b483SKent Overstreet 	BUG_ON((parent == 0) != (nr_snapids == 1));
9681c59b483SKent Overstreet 	BUG_ON((parent != 0) != (nr_snapids == 2));
9691c59b483SKent Overstreet 
9701c59b483SKent Overstreet 	return parent
9711c59b483SKent Overstreet 		? bch2_snapshot_node_create_children(trans, parent,
9721c59b483SKent Overstreet 				new_snapids, snapshot_subvols, nr_snapids)
9731c59b483SKent Overstreet 		: bch2_snapshot_node_create_tree(trans,
9741c59b483SKent Overstreet 				new_snapids, snapshot_subvols, nr_snapids);
9751c59b483SKent Overstreet 
9761c59b483SKent Overstreet }
9771c59b483SKent Overstreet 
9786738dd19SKent Overstreet static int snapshot_delete_key(struct btree_trans *trans,
9796738dd19SKent Overstreet 			       struct btree_iter *iter,
9806738dd19SKent Overstreet 			       struct bkey_s_c k,
98191d961baSKent Overstreet 			       snapshot_id_list *deleted,
9826738dd19SKent Overstreet 			       snapshot_id_list *equiv_seen,
9836738dd19SKent Overstreet 			       struct bpos *last_pos)
98414b393eeSKent Overstreet {
98514b393eeSKent Overstreet 	struct bch_fs *c = trans->c;
98614b393eeSKent Overstreet 	u32 equiv = snapshot_t(c, k.k->p.snapshot)->equiv;
98714b393eeSKent Overstreet 
988e88a75ebSKent Overstreet 	if (!bkey_eq(k.k->p, *last_pos))
9896738dd19SKent Overstreet 		equiv_seen->nr = 0;
9906738dd19SKent Overstreet 	*last_pos = k.k->p;
99114b393eeSKent Overstreet 
99214b393eeSKent Overstreet 	if (snapshot_list_has_id(deleted, k.k->p.snapshot) ||
9936738dd19SKent Overstreet 	    snapshot_list_has_id(equiv_seen, equiv)) {
9946738dd19SKent Overstreet 		return bch2_btree_delete_at(trans, iter,
9956738dd19SKent Overstreet 					    BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE);
99614b393eeSKent Overstreet 	} else {
9976738dd19SKent Overstreet 		return snapshot_list_add(c, equiv_seen, equiv);
99814b393eeSKent Overstreet 	}
99914b393eeSKent Overstreet }
100014b393eeSKent Overstreet 
1001a1783320SKent Overstreet static int bch2_delete_redundant_snapshot(struct btree_trans *trans, struct btree_iter *iter,
1002a1783320SKent Overstreet 					  struct bkey_s_c k)
1003a1783320SKent Overstreet {
1004a1783320SKent Overstreet 	struct bkey_s_c_snapshot snap;
1005a1783320SKent Overstreet 	u32 children[2];
1006a1783320SKent Overstreet 	int ret;
1007a1783320SKent Overstreet 
1008a1783320SKent Overstreet 	if (k.k->type != KEY_TYPE_snapshot)
1009a1783320SKent Overstreet 		return 0;
1010a1783320SKent Overstreet 
1011a1783320SKent Overstreet 	snap = bkey_s_c_to_snapshot(k);
1012a1783320SKent Overstreet 	if (BCH_SNAPSHOT_DELETED(snap.v) ||
1013a1783320SKent Overstreet 	    BCH_SNAPSHOT_SUBVOL(snap.v))
1014a1783320SKent Overstreet 		return 0;
1015a1783320SKent Overstreet 
1016a1783320SKent Overstreet 	children[0] = le32_to_cpu(snap.v->children[0]);
1017a1783320SKent Overstreet 	children[1] = le32_to_cpu(snap.v->children[1]);
1018a1783320SKent Overstreet 
1019a1783320SKent Overstreet 	ret   = snapshot_live(trans, children[0]) ?:
1020a1783320SKent Overstreet 		snapshot_live(trans, children[1]);
1021a1783320SKent Overstreet 	if (ret < 0)
1022a1783320SKent Overstreet 		return ret;
1023a1783320SKent Overstreet 
1024a1783320SKent Overstreet 	if (!ret)
1025a1783320SKent Overstreet 		return bch2_snapshot_node_set_deleted(trans, k.k->p.offset);
1026a1783320SKent Overstreet 	return 0;
1027a1783320SKent Overstreet }
1028a1783320SKent Overstreet 
10294ab35c34SKent Overstreet int bch2_delete_dead_snapshots(struct bch_fs *c)
103014b393eeSKent Overstreet {
103114b393eeSKent Overstreet 	struct btree_trans trans;
103214b393eeSKent Overstreet 	struct btree_iter iter;
103314b393eeSKent Overstreet 	struct bkey_s_c k;
103414b393eeSKent Overstreet 	struct bkey_s_c_snapshot snap;
103591d961baSKent Overstreet 	snapshot_id_list deleted = { 0 };
1036a1783320SKent Overstreet 	u32 i, id;
103714b393eeSKent Overstreet 	int ret = 0;
103814b393eeSKent Overstreet 
10394ab35c34SKent Overstreet 	if (!test_bit(BCH_FS_HAVE_DELETED_SNAPSHOTS, &c->flags))
10404ab35c34SKent Overstreet 		return 0;
10414ab35c34SKent Overstreet 
10424ab35c34SKent Overstreet 	if (!test_bit(BCH_FS_STARTED, &c->flags)) {
10434ab35c34SKent Overstreet 		ret = bch2_fs_read_write_early(c);
10444ab35c34SKent Overstreet 		if (ret) {
1045d4bf5eecSKent Overstreet 			bch_err(c, "error deleleting dead snapshots: error going rw: %s", bch2_err_str(ret));
10464ab35c34SKent Overstreet 			return ret;
10474ab35c34SKent Overstreet 		}
10484ab35c34SKent Overstreet 	}
10494ab35c34SKent Overstreet 
105014b393eeSKent Overstreet 	bch2_trans_init(&trans, c, 0, 0);
105114b393eeSKent Overstreet 
105214b393eeSKent Overstreet 	/*
105314b393eeSKent Overstreet 	 * For every snapshot node: If we have no live children and it's not
105414b393eeSKent Overstreet 	 * pointed to by a subvolume, delete it:
105514b393eeSKent Overstreet 	 */
1056a1783320SKent Overstreet 	ret = for_each_btree_key_commit(&trans, iter, BTREE_ID_snapshots,
1057a1783320SKent Overstreet 			POS_MIN, 0, k,
1058a1783320SKent Overstreet 			NULL, NULL, 0,
1059a1783320SKent Overstreet 		bch2_delete_redundant_snapshot(&trans, &iter, k));
106014b393eeSKent Overstreet 	if (ret) {
1061d4bf5eecSKent Overstreet 		bch_err(c, "error deleting redundant snapshots: %s", bch2_err_str(ret));
106214b393eeSKent Overstreet 		goto err;
106314b393eeSKent Overstreet 	}
106414b393eeSKent Overstreet 
1065a1783320SKent Overstreet 	for_each_btree_key2(&trans, iter, BTREE_ID_snapshots,
1066a1783320SKent Overstreet 			   POS_MIN, 0, k,
1067a1783320SKent Overstreet 		bch2_snapshot_set_equiv(&trans, k));
1068a1783320SKent Overstreet 	if (ret) {
1069d4bf5eecSKent Overstreet 		bch_err(c, "error in bch2_snapshots_set_equiv: %s", bch2_err_str(ret));
107014b393eeSKent Overstreet 		goto err;
1071a1783320SKent Overstreet 	}
107214b393eeSKent Overstreet 
107314b393eeSKent Overstreet 	for_each_btree_key(&trans, iter, BTREE_ID_snapshots,
107414b393eeSKent Overstreet 			   POS_MIN, 0, k, ret) {
107514b393eeSKent Overstreet 		if (k.k->type != KEY_TYPE_snapshot)
107614b393eeSKent Overstreet 			continue;
107714b393eeSKent Overstreet 
107814b393eeSKent Overstreet 		snap = bkey_s_c_to_snapshot(k);
107914b393eeSKent Overstreet 		if (BCH_SNAPSHOT_DELETED(snap.v)) {
1080597dee1cSKent Overstreet 			ret = snapshot_list_add(c, &deleted, k.k->p.offset);
108114b393eeSKent Overstreet 			if (ret)
108214b393eeSKent Overstreet 				break;
108314b393eeSKent Overstreet 		}
108414b393eeSKent Overstreet 	}
108514b393eeSKent Overstreet 	bch2_trans_iter_exit(&trans, &iter);
108614b393eeSKent Overstreet 
108714b393eeSKent Overstreet 	if (ret) {
1088d4bf5eecSKent Overstreet 		bch_err(c, "error walking snapshots: %s", bch2_err_str(ret));
108914b393eeSKent Overstreet 		goto err;
109014b393eeSKent Overstreet 	}
109114b393eeSKent Overstreet 
109214b393eeSKent Overstreet 	for (id = 0; id < BTREE_ID_NR; id++) {
10936738dd19SKent Overstreet 		struct bpos last_pos = POS_MIN;
10946738dd19SKent Overstreet 		snapshot_id_list equiv_seen = { 0 };
10956738dd19SKent Overstreet 
109614b393eeSKent Overstreet 		if (!btree_type_has_snapshots(id))
109714b393eeSKent Overstreet 			continue;
109814b393eeSKent Overstreet 
10996738dd19SKent Overstreet 		ret = for_each_btree_key_commit(&trans, iter,
11006738dd19SKent Overstreet 				id, POS_MIN,
11016738dd19SKent Overstreet 				BTREE_ITER_PREFETCH|BTREE_ITER_ALL_SNAPSHOTS, k,
11026738dd19SKent Overstreet 				NULL, NULL, BTREE_INSERT_NOFAIL,
11036738dd19SKent Overstreet 			snapshot_delete_key(&trans, &iter, k, &deleted, &equiv_seen, &last_pos));
11046738dd19SKent Overstreet 
11056738dd19SKent Overstreet 		darray_exit(&equiv_seen);
11066738dd19SKent Overstreet 
110714b393eeSKent Overstreet 		if (ret) {
1108d4bf5eecSKent Overstreet 			bch_err(c, "error deleting snapshot keys: %s", bch2_err_str(ret));
110914b393eeSKent Overstreet 			goto err;
111014b393eeSKent Overstreet 		}
111114b393eeSKent Overstreet 	}
111214b393eeSKent Overstreet 
111314b393eeSKent Overstreet 	for (i = 0; i < deleted.nr; i++) {
1114e68914caSKent Overstreet 		ret = commit_do(&trans, NULL, NULL, 0,
111591d961baSKent Overstreet 			bch2_snapshot_node_delete(&trans, deleted.data[i]));
111614b393eeSKent Overstreet 		if (ret) {
1117d4bf5eecSKent Overstreet 			bch_err(c, "error deleting snapshot %u: %s",
1118d4bf5eecSKent Overstreet 				deleted.data[i], bch2_err_str(ret));
111914b393eeSKent Overstreet 			goto err;
112014b393eeSKent Overstreet 		}
112114b393eeSKent Overstreet 	}
11224ab35c34SKent Overstreet 
11234ab35c34SKent Overstreet 	clear_bit(BCH_FS_HAVE_DELETED_SNAPSHOTS, &c->flags);
112414b393eeSKent Overstreet err:
112591d961baSKent Overstreet 	darray_exit(&deleted);
112614b393eeSKent Overstreet 	bch2_trans_exit(&trans);
11271bb3c2a9SKent Overstreet 	if (ret)
11281bb3c2a9SKent Overstreet 		bch_err_fn(c, ret);
11294ab35c34SKent Overstreet 	return ret;
11304ab35c34SKent Overstreet }
11314ab35c34SKent Overstreet 
11324ab35c34SKent Overstreet static void bch2_delete_dead_snapshots_work(struct work_struct *work)
11334ab35c34SKent Overstreet {
11344ab35c34SKent Overstreet 	struct bch_fs *c = container_of(work, struct bch_fs, snapshot_delete_work);
11354ab35c34SKent Overstreet 
11364ab35c34SKent Overstreet 	bch2_delete_dead_snapshots(c);
1137d94189adSKent Overstreet 	bch2_write_ref_put(c, BCH_WRITE_REF_delete_dead_snapshots);
113814b393eeSKent Overstreet }
113914b393eeSKent Overstreet 
11404ab35c34SKent Overstreet void bch2_delete_dead_snapshots_async(struct bch_fs *c)
114114b393eeSKent Overstreet {
1142d94189adSKent Overstreet 	if (bch2_write_ref_tryget(c, BCH_WRITE_REF_delete_dead_snapshots) &&
11438bff9875SBrian Foster 	    !queue_work(c->write_ref_wq, &c->snapshot_delete_work))
1144d94189adSKent Overstreet 		bch2_write_ref_put(c, BCH_WRITE_REF_delete_dead_snapshots);
114514b393eeSKent Overstreet }
114614b393eeSKent Overstreet 
114714b393eeSKent Overstreet static int bch2_delete_dead_snapshots_hook(struct btree_trans *trans,
114814b393eeSKent Overstreet 					   struct btree_trans_commit_hook *h)
114914b393eeSKent Overstreet {
11504ab35c34SKent Overstreet 	struct bch_fs *c = trans->c;
11514ab35c34SKent Overstreet 
11524ab35c34SKent Overstreet 	set_bit(BCH_FS_HAVE_DELETED_SNAPSHOTS, &c->flags);
11534ab35c34SKent Overstreet 
1154*067d228bSKent Overstreet 	if (c->curr_recovery_pass <= BCH_RECOVERY_PASS_delete_dead_snapshots)
11554ab35c34SKent Overstreet 		return 0;
11564ab35c34SKent Overstreet 
11574ab35c34SKent Overstreet 	bch2_delete_dead_snapshots_async(c);
115814b393eeSKent Overstreet 	return 0;
115914b393eeSKent Overstreet }
116014b393eeSKent Overstreet 
116114b393eeSKent Overstreet /* Subvolumes: */
116214b393eeSKent Overstreet 
1163f0ac7df2SKent Overstreet int bch2_subvolume_invalid(const struct bch_fs *c, struct bkey_s_c k,
1164facafdcbSKent Overstreet 			   unsigned flags, struct printbuf *err)
116514b393eeSKent Overstreet {
1166e88a75ebSKent Overstreet 	if (bkey_lt(k.k->p, SUBVOL_POS_MIN) ||
1167e88a75ebSKent Overstreet 	    bkey_gt(k.k->p, SUBVOL_POS_MAX)) {
1168401ec4dbSKent Overstreet 		prt_printf(err, "invalid pos");
116978c0b75cSKent Overstreet 		return -BCH_ERR_invalid_bkey;
1170f0ac7df2SKent Overstreet 	}
117114b393eeSKent Overstreet 
1172f0ac7df2SKent Overstreet 	return 0;
117314b393eeSKent Overstreet }
117414b393eeSKent Overstreet 
117514b393eeSKent Overstreet void bch2_subvolume_to_text(struct printbuf *out, struct bch_fs *c,
117614b393eeSKent Overstreet 			    struct bkey_s_c k)
117714b393eeSKent Overstreet {
117814b393eeSKent Overstreet 	struct bkey_s_c_subvolume s = bkey_s_c_to_subvolume(k);
117914b393eeSKent Overstreet 
1180401ec4dbSKent Overstreet 	prt_printf(out, "root %llu snapshot id %u",
118114b393eeSKent Overstreet 		   le64_to_cpu(s.v->inode),
118214b393eeSKent Overstreet 		   le32_to_cpu(s.v->snapshot));
1183653693beSKent Overstreet 
1184653693beSKent Overstreet 	if (bkey_val_bytes(s.k) > offsetof(struct bch_subvolume, parent))
1185653693beSKent Overstreet 		prt_printf(out, " parent %u", le32_to_cpu(s.v->parent));
118614b393eeSKent Overstreet }
118714b393eeSKent Overstreet 
118898638ffaSKent Overstreet static __always_inline int
118998638ffaSKent Overstreet bch2_subvolume_get_inlined(struct btree_trans *trans, unsigned subvol,
119097996ddfSKent Overstreet 			   bool inconsistent_if_not_found,
119197996ddfSKent Overstreet 			   int iter_flags,
119297996ddfSKent Overstreet 			   struct bch_subvolume *s)
119314b393eeSKent Overstreet {
1194bcb79a51SKent Overstreet 	int ret = bch2_bkey_get_val_typed(trans, BTREE_ID_subvolumes, POS(0, subvol),
1195bcb79a51SKent Overstreet 					  iter_flags, subvolume, s);
11961c59b483SKent Overstreet 	bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT) &&
11971c59b483SKent Overstreet 				inconsistent_if_not_found,
1198bcb79a51SKent Overstreet 				trans->c, "missing subvolume %u", subvol);
119997996ddfSKent Overstreet 	return ret;
120014b393eeSKent Overstreet }
120114b393eeSKent Overstreet 
120298638ffaSKent Overstreet int bch2_subvolume_get(struct btree_trans *trans, unsigned subvol,
120398638ffaSKent Overstreet 		       bool inconsistent_if_not_found,
120498638ffaSKent Overstreet 		       int iter_flags,
120598638ffaSKent Overstreet 		       struct bch_subvolume *s)
120698638ffaSKent Overstreet {
120798638ffaSKent Overstreet 	return bch2_subvolume_get_inlined(trans, subvol, inconsistent_if_not_found, iter_flags, s);
120898638ffaSKent Overstreet }
120998638ffaSKent Overstreet 
12109ca4853bSKent Overstreet int bch2_snapshot_get_subvol(struct btree_trans *trans, u32 snapshot,
12119ca4853bSKent Overstreet 			     struct bch_subvolume *subvol)
12129ca4853bSKent Overstreet {
12139ca4853bSKent Overstreet 	struct bch_snapshot snap;
12149ca4853bSKent Overstreet 
12159ca4853bSKent Overstreet 	return  snapshot_lookup(trans, snapshot, &snap) ?:
12169ca4853bSKent Overstreet 		bch2_subvolume_get(trans, le32_to_cpu(snap.subvol), true, 0, subvol);
12179ca4853bSKent Overstreet }
12189ca4853bSKent Overstreet 
121997996ddfSKent Overstreet int bch2_subvolume_get_snapshot(struct btree_trans *trans, u32 subvol,
122097996ddfSKent Overstreet 				u32 *snapid)
122197996ddfSKent Overstreet {
1222653693beSKent Overstreet 	struct btree_iter iter;
1223653693beSKent Overstreet 	struct bkey_s_c k;
122497996ddfSKent Overstreet 	int ret;
122597996ddfSKent Overstreet 
1226653693beSKent Overstreet 	k = bch2_bkey_get_iter(trans, &iter, BTREE_ID_subvolumes, POS(0, subvol),
122797996ddfSKent Overstreet 			       BTREE_ITER_CACHED|
1228653693beSKent Overstreet 			       BTREE_ITER_WITH_UPDATES);
1229e47a390aSKent Overstreet 	ret = bkey_err(k) ?: k.k->type == KEY_TYPE_subvolume ? 0 : -BCH_ERR_ENOENT_subvolume;
1230653693beSKent Overstreet 
1231653693beSKent Overstreet 	if (likely(!ret))
1232653693beSKent Overstreet 		*snapid = le32_to_cpu(bkey_s_c_to_subvolume(k).v->snapshot);
1233653693beSKent Overstreet 	else if (bch2_err_matches(ret, ENOENT))
1234653693beSKent Overstreet 		bch2_fs_inconsistent(trans->c, "missing subvolume %u", subvol);
1235653693beSKent Overstreet 	bch2_trans_iter_exit(trans, &iter);
123614b393eeSKent Overstreet 	return ret;
123714b393eeSKent Overstreet }
123814b393eeSKent Overstreet 
1239653693beSKent Overstreet static int bch2_subvolume_reparent(struct btree_trans *trans,
1240653693beSKent Overstreet 				   struct btree_iter *iter,
1241653693beSKent Overstreet 				   struct bkey_s_c k,
1242653693beSKent Overstreet 				   u32 old_parent, u32 new_parent)
1243653693beSKent Overstreet {
1244653693beSKent Overstreet 	struct bkey_i_subvolume *s;
1245653693beSKent Overstreet 	int ret;
1246653693beSKent Overstreet 
1247653693beSKent Overstreet 	if (k.k->type != KEY_TYPE_subvolume)
1248653693beSKent Overstreet 		return 0;
1249653693beSKent Overstreet 
1250653693beSKent Overstreet 	if (bkey_val_bytes(k.k) > offsetof(struct bch_subvolume, parent) &&
1251653693beSKent Overstreet 	    le32_to_cpu(bkey_s_c_to_subvolume(k).v->parent) != old_parent)
1252653693beSKent Overstreet 		return 0;
1253653693beSKent Overstreet 
12540fb3355dSKent Overstreet 	s = bch2_bkey_make_mut_typed(trans, iter, &k, 0, subvolume);
1255653693beSKent Overstreet 	ret = PTR_ERR_OR_ZERO(s);
1256653693beSKent Overstreet 	if (ret)
1257653693beSKent Overstreet 		return ret;
1258653693beSKent Overstreet 
1259653693beSKent Overstreet 	s->v.parent = cpu_to_le32(new_parent);
1260653693beSKent Overstreet 	return 0;
1261653693beSKent Overstreet }
1262653693beSKent Overstreet 
1263653693beSKent Overstreet /*
1264653693beSKent Overstreet  * Scan for subvolumes with parent @subvolid_to_delete, reparent:
1265653693beSKent Overstreet  */
1266653693beSKent Overstreet static int bch2_subvolumes_reparent(struct btree_trans *trans, u32 subvolid_to_delete)
1267653693beSKent Overstreet {
1268653693beSKent Overstreet 	struct btree_iter iter;
1269653693beSKent Overstreet 	struct bkey_s_c k;
1270653693beSKent Overstreet 	struct bch_subvolume s;
1271653693beSKent Overstreet 
1272653693beSKent Overstreet 	return lockrestart_do(trans,
1273653693beSKent Overstreet 			bch2_subvolume_get(trans, subvolid_to_delete, true,
1274653693beSKent Overstreet 				   BTREE_ITER_CACHED, &s)) ?:
1275653693beSKent Overstreet 		for_each_btree_key_commit(trans, iter,
1276653693beSKent Overstreet 				BTREE_ID_subvolumes, POS_MIN, BTREE_ITER_PREFETCH, k,
1277653693beSKent Overstreet 				NULL, NULL, BTREE_INSERT_NOFAIL,
1278653693beSKent Overstreet 			bch2_subvolume_reparent(trans, &iter, k,
1279653693beSKent Overstreet 					subvolid_to_delete, le32_to_cpu(s.parent)));
1280653693beSKent Overstreet }
1281653693beSKent Overstreet 
12822027875bSKent Overstreet /*
12832027875bSKent Overstreet  * Delete subvolume, mark snapshot ID as deleted, queue up snapshot
12842027875bSKent Overstreet  * deletion/cleanup:
12852027875bSKent Overstreet  */
1286653693beSKent Overstreet static int __bch2_subvolume_delete(struct btree_trans *trans, u32 subvolid)
128714b393eeSKent Overstreet {
128814b393eeSKent Overstreet 	struct btree_iter iter;
128914b393eeSKent Overstreet 	struct bkey_s_c_subvolume subvol;
129014b393eeSKent Overstreet 	struct btree_trans_commit_hook *h;
129114b393eeSKent Overstreet 	u32 snapid;
129214b393eeSKent Overstreet 	int ret = 0;
129314b393eeSKent Overstreet 
1294bcb79a51SKent Overstreet 	subvol = bch2_bkey_get_iter_typed(trans, &iter,
1295bcb79a51SKent Overstreet 				BTREE_ID_subvolumes, POS(0, subvolid),
1296bcb79a51SKent Overstreet 				BTREE_ITER_CACHED|BTREE_ITER_INTENT,
1297bcb79a51SKent Overstreet 				subvolume);
1298bcb79a51SKent Overstreet 	ret = bkey_err(subvol);
12991c59b483SKent Overstreet 	bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT), trans->c,
13001c59b483SKent Overstreet 				"missing subvolume %u", subvolid);
130114b393eeSKent Overstreet 	if (ret)
1302bcb79a51SKent Overstreet 		return ret;
130314b393eeSKent Overstreet 
130414b393eeSKent Overstreet 	snapid = le32_to_cpu(subvol.v->snapshot);
130514b393eeSKent Overstreet 
1306416cc426SKent Overstreet 	ret = bch2_btree_delete_at(trans, &iter, 0);
130714b393eeSKent Overstreet 	if (ret)
130814b393eeSKent Overstreet 		goto err;
130914b393eeSKent Overstreet 
131014b393eeSKent Overstreet 	ret = bch2_snapshot_node_set_deleted(trans, snapid);
131131301dd4SKent Overstreet 	if (ret)
131231301dd4SKent Overstreet 		goto err;
131314b393eeSKent Overstreet 
131414b393eeSKent Overstreet 	h = bch2_trans_kmalloc(trans, sizeof(*h));
131514b393eeSKent Overstreet 	ret = PTR_ERR_OR_ZERO(h);
131614b393eeSKent Overstreet 	if (ret)
131714b393eeSKent Overstreet 		goto err;
131814b393eeSKent Overstreet 
131914b393eeSKent Overstreet 	h->fn = bch2_delete_dead_snapshots_hook;
132014b393eeSKent Overstreet 	bch2_trans_commit_hook(trans, h);
132114b393eeSKent Overstreet err:
132214b393eeSKent Overstreet 	bch2_trans_iter_exit(trans, &iter);
132314b393eeSKent Overstreet 	return ret;
132414b393eeSKent Overstreet }
132514b393eeSKent Overstreet 
1326653693beSKent Overstreet static int bch2_subvolume_delete(struct btree_trans *trans, u32 subvolid)
1327653693beSKent Overstreet {
1328653693beSKent Overstreet 	return bch2_subvolumes_reparent(trans, subvolid) ?:
1329653693beSKent Overstreet 		commit_do(trans, NULL, NULL, BTREE_INSERT_NOFAIL,
1330653693beSKent Overstreet 			  __bch2_subvolume_delete(trans, subvolid));
1331653693beSKent Overstreet }
1332653693beSKent Overstreet 
133373bd774dSKent Overstreet static void bch2_subvolume_wait_for_pagecache_and_delete(struct work_struct *work)
13342027875bSKent Overstreet {
13352027875bSKent Overstreet 	struct bch_fs *c = container_of(work, struct bch_fs,
13362027875bSKent Overstreet 				snapshot_wait_for_pagecache_and_delete_work);
133791d961baSKent Overstreet 	snapshot_id_list s;
13382027875bSKent Overstreet 	u32 *id;
13392027875bSKent Overstreet 	int ret = 0;
13402027875bSKent Overstreet 
13412027875bSKent Overstreet 	while (!ret) {
13422027875bSKent Overstreet 		mutex_lock(&c->snapshots_unlinked_lock);
13432027875bSKent Overstreet 		s = c->snapshots_unlinked;
134491d961baSKent Overstreet 		darray_init(&c->snapshots_unlinked);
13452027875bSKent Overstreet 		mutex_unlock(&c->snapshots_unlinked_lock);
13462027875bSKent Overstreet 
13472027875bSKent Overstreet 		if (!s.nr)
13482027875bSKent Overstreet 			break;
13492027875bSKent Overstreet 
13502027875bSKent Overstreet 		bch2_evict_subvolume_inodes(c, &s);
13512027875bSKent Overstreet 
135291d961baSKent Overstreet 		for (id = s.data; id < s.data + s.nr; id++) {
1353653693beSKent Overstreet 			ret = bch2_trans_run(c, bch2_subvolume_delete(&trans, *id));
13542027875bSKent Overstreet 			if (ret) {
1355d4bf5eecSKent Overstreet 				bch_err(c, "error deleting subvolume %u: %s", *id, bch2_err_str(ret));
13562027875bSKent Overstreet 				break;
13572027875bSKent Overstreet 			}
13582027875bSKent Overstreet 		}
13592027875bSKent Overstreet 
136091d961baSKent Overstreet 		darray_exit(&s);
13612027875bSKent Overstreet 	}
13622027875bSKent Overstreet 
1363d94189adSKent Overstreet 	bch2_write_ref_put(c, BCH_WRITE_REF_snapshot_delete_pagecache);
13642027875bSKent Overstreet }
13652027875bSKent Overstreet 
13662027875bSKent Overstreet struct subvolume_unlink_hook {
13672027875bSKent Overstreet 	struct btree_trans_commit_hook	h;
13682027875bSKent Overstreet 	u32				subvol;
13692027875bSKent Overstreet };
13702027875bSKent Overstreet 
137173bd774dSKent Overstreet static int bch2_subvolume_wait_for_pagecache_and_delete_hook(struct btree_trans *trans,
13722027875bSKent Overstreet 						      struct btree_trans_commit_hook *_h)
13732027875bSKent Overstreet {
13742027875bSKent Overstreet 	struct subvolume_unlink_hook *h = container_of(_h, struct subvolume_unlink_hook, h);
13752027875bSKent Overstreet 	struct bch_fs *c = trans->c;
13762027875bSKent Overstreet 	int ret = 0;
13772027875bSKent Overstreet 
13782027875bSKent Overstreet 	mutex_lock(&c->snapshots_unlinked_lock);
13792027875bSKent Overstreet 	if (!snapshot_list_has_id(&c->snapshots_unlinked, h->subvol))
1380597dee1cSKent Overstreet 		ret = snapshot_list_add(c, &c->snapshots_unlinked, h->subvol);
13812027875bSKent Overstreet 	mutex_unlock(&c->snapshots_unlinked_lock);
13822027875bSKent Overstreet 
13832027875bSKent Overstreet 	if (ret)
13842027875bSKent Overstreet 		return ret;
13852027875bSKent Overstreet 
1386d94189adSKent Overstreet 	if (!bch2_write_ref_tryget(c, BCH_WRITE_REF_snapshot_delete_pagecache))
13872027875bSKent Overstreet 		return -EROFS;
13882027875bSKent Overstreet 
13898bff9875SBrian Foster 	if (!queue_work(c->write_ref_wq, &c->snapshot_wait_for_pagecache_and_delete_work))
1390d94189adSKent Overstreet 		bch2_write_ref_put(c, BCH_WRITE_REF_snapshot_delete_pagecache);
13912027875bSKent Overstreet 	return 0;
13922027875bSKent Overstreet }
13932027875bSKent Overstreet 
13942027875bSKent Overstreet int bch2_subvolume_unlink(struct btree_trans *trans, u32 subvolid)
13952027875bSKent Overstreet {
13962027875bSKent Overstreet 	struct btree_iter iter;
13972027875bSKent Overstreet 	struct bkey_i_subvolume *n;
13982027875bSKent Overstreet 	struct subvolume_unlink_hook *h;
13992027875bSKent Overstreet 	int ret = 0;
14002027875bSKent Overstreet 
1401f12a798aSKent Overstreet 	h = bch2_trans_kmalloc(trans, sizeof(*h));
1402f12a798aSKent Overstreet 	ret = PTR_ERR_OR_ZERO(h);
1403f12a798aSKent Overstreet 	if (ret)
1404f12a798aSKent Overstreet 		return ret;
1405f12a798aSKent Overstreet 
1406f12a798aSKent Overstreet 	h->h.fn		= bch2_subvolume_wait_for_pagecache_and_delete_hook;
1407f12a798aSKent Overstreet 	h->subvol	= subvolid;
1408f12a798aSKent Overstreet 	bch2_trans_commit_hook(trans, &h->h);
1409f12a798aSKent Overstreet 
141034dfa5dbSKent Overstreet 	n = bch2_bkey_get_mut_typed(trans, &iter,
141134dfa5dbSKent Overstreet 			BTREE_ID_subvolumes, POS(0, subvolid),
141234dfa5dbSKent Overstreet 			BTREE_ITER_CACHED, subvolume);
1413994ba475SKent Overstreet 	ret = PTR_ERR_OR_ZERO(n);
1414994ba475SKent Overstreet 	if (unlikely(ret)) {
14151c59b483SKent Overstreet 		bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT), trans->c,
14161c59b483SKent Overstreet 					"missing subvolume %u", subvolid);
1417f12a798aSKent Overstreet 		return ret;
14182027875bSKent Overstreet 	}
14192027875bSKent Overstreet 
14202027875bSKent Overstreet 	SET_BCH_SUBVOLUME_UNLINKED(&n->v, true);
14212027875bSKent Overstreet 	bch2_trans_iter_exit(trans, &iter);
14222027875bSKent Overstreet 	return ret;
14232027875bSKent Overstreet }
14242027875bSKent Overstreet 
142514b393eeSKent Overstreet int bch2_subvolume_create(struct btree_trans *trans, u64 inode,
142614b393eeSKent Overstreet 			  u32 src_subvolid,
142714b393eeSKent Overstreet 			  u32 *new_subvolid,
142814b393eeSKent Overstreet 			  u32 *new_snapshotid,
142914b393eeSKent Overstreet 			  bool ro)
143014b393eeSKent Overstreet {
1431653693beSKent Overstreet 	struct bch_fs *c = trans->c;
143214b393eeSKent Overstreet 	struct btree_iter dst_iter, src_iter = (struct btree_iter) { NULL };
143314b393eeSKent Overstreet 	struct bkey_i_subvolume *new_subvol = NULL;
143414b393eeSKent Overstreet 	struct bkey_i_subvolume *src_subvol = NULL;
143514b393eeSKent Overstreet 	u32 parent = 0, new_nodes[2], snapshot_subvols[2];
143614b393eeSKent Overstreet 	int ret = 0;
143714b393eeSKent Overstreet 
143851e84d3bSKent Overstreet 	ret = bch2_bkey_get_empty_slot(trans, &dst_iter,
143951e84d3bSKent Overstreet 				BTREE_ID_subvolumes, POS(0, U32_MAX));
144051e84d3bSKent Overstreet 	if (ret == -BCH_ERR_ENOSPC_btree_slot)
1441098ef98dSKent Overstreet 		ret = -BCH_ERR_ENOSPC_subvolume_create;
144251e84d3bSKent Overstreet 	if (ret)
144351e84d3bSKent Overstreet 		return ret;
144451e84d3bSKent Overstreet 
144514b393eeSKent Overstreet 	snapshot_subvols[0] = dst_iter.pos.offset;
144614b393eeSKent Overstreet 	snapshot_subvols[1] = src_subvolid;
144714b393eeSKent Overstreet 
144814b393eeSKent Overstreet 	if (src_subvolid) {
144914b393eeSKent Overstreet 		/* Creating a snapshot: */
145014b393eeSKent Overstreet 
145134dfa5dbSKent Overstreet 		src_subvol = bch2_bkey_get_mut_typed(trans, &src_iter,
145234dfa5dbSKent Overstreet 				BTREE_ID_subvolumes, POS(0, src_subvolid),
145334dfa5dbSKent Overstreet 				BTREE_ITER_CACHED, subvolume);
1454994ba475SKent Overstreet 		ret = PTR_ERR_OR_ZERO(src_subvol);
1455994ba475SKent Overstreet 		if (unlikely(ret)) {
1456e47a390aSKent Overstreet 			bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT), c,
1457994ba475SKent Overstreet 						"subvolume %u not found", src_subvolid);
145814b393eeSKent Overstreet 			goto err;
145914b393eeSKent Overstreet 		}
146014b393eeSKent Overstreet 
146114b393eeSKent Overstreet 		parent = le32_to_cpu(src_subvol->v.snapshot);
146214b393eeSKent Overstreet 	}
146314b393eeSKent Overstreet 
146414b393eeSKent Overstreet 	ret = bch2_snapshot_node_create(trans, parent, new_nodes,
146514b393eeSKent Overstreet 					snapshot_subvols,
146614b393eeSKent Overstreet 					src_subvolid ? 2 : 1);
146714b393eeSKent Overstreet 	if (ret)
146814b393eeSKent Overstreet 		goto err;
146914b393eeSKent Overstreet 
147014b393eeSKent Overstreet 	if (src_subvolid) {
147114b393eeSKent Overstreet 		src_subvol->v.snapshot = cpu_to_le32(new_nodes[1]);
147294a3e1a6SKent Overstreet 		ret = bch2_trans_update(trans, &src_iter, &src_subvol->k_i, 0);
147394a3e1a6SKent Overstreet 		if (ret)
147494a3e1a6SKent Overstreet 			goto err;
147514b393eeSKent Overstreet 	}
147614b393eeSKent Overstreet 
1477f8cb35fdSKent Overstreet 	new_subvol = bch2_bkey_alloc(trans, &dst_iter, 0, subvolume);
147814b393eeSKent Overstreet 	ret = PTR_ERR_OR_ZERO(new_subvol);
147914b393eeSKent Overstreet 	if (ret)
148014b393eeSKent Overstreet 		goto err;
148114b393eeSKent Overstreet 
148214b393eeSKent Overstreet 	new_subvol->v.flags	= 0;
148314b393eeSKent Overstreet 	new_subvol->v.snapshot	= cpu_to_le32(new_nodes[0]);
148414b393eeSKent Overstreet 	new_subvol->v.inode	= cpu_to_le64(inode);
1485653693beSKent Overstreet 	new_subvol->v.parent	= cpu_to_le32(src_subvolid);
1486653693beSKent Overstreet 	new_subvol->v.otime.lo	= cpu_to_le64(bch2_current_time(c));
1487653693beSKent Overstreet 	new_subvol->v.otime.hi	= 0;
1488653693beSKent Overstreet 
148914b393eeSKent Overstreet 	SET_BCH_SUBVOLUME_RO(&new_subvol->v, ro);
149014b393eeSKent Overstreet 	SET_BCH_SUBVOLUME_SNAP(&new_subvol->v, src_subvolid != 0);
149114b393eeSKent Overstreet 
149214b393eeSKent Overstreet 	*new_subvolid	= new_subvol->k.p.offset;
149314b393eeSKent Overstreet 	*new_snapshotid	= new_nodes[0];
149414b393eeSKent Overstreet err:
149514b393eeSKent Overstreet 	bch2_trans_iter_exit(trans, &src_iter);
149614b393eeSKent Overstreet 	bch2_trans_iter_exit(trans, &dst_iter);
149714b393eeSKent Overstreet 	return ret;
149814b393eeSKent Overstreet }
149914b393eeSKent Overstreet 
150014b393eeSKent Overstreet int bch2_fs_subvolumes_init(struct bch_fs *c)
150114b393eeSKent Overstreet {
150214b393eeSKent Overstreet 	INIT_WORK(&c->snapshot_delete_work, bch2_delete_dead_snapshots_work);
15032027875bSKent Overstreet 	INIT_WORK(&c->snapshot_wait_for_pagecache_and_delete_work,
15042027875bSKent Overstreet 		  bch2_subvolume_wait_for_pagecache_and_delete);
15052027875bSKent Overstreet 	mutex_init(&c->snapshots_unlinked_lock);
150614b393eeSKent Overstreet 	return 0;
150714b393eeSKent Overstreet }
1508