xref: /linux/fs/bcachefs/subvolume.c (revision cb1b479dc1c78d1d224e4aa6aba212a7bd3263a4)
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,
261c59b483SKent Overstreet 			       unsigned flags, struct printbuf *err)
271c59b483SKent Overstreet {
281c59b483SKent Overstreet 	if (bkey_gt(k.k->p, POS(0, U32_MAX)) ||
291c59b483SKent Overstreet 	    bkey_lt(k.k->p, POS(0, 1))) {
301c59b483SKent Overstreet 		prt_printf(err, "bad pos");
311c59b483SKent Overstreet 		return -BCH_ERR_invalid_bkey;
321c59b483SKent Overstreet 	}
331c59b483SKent Overstreet 
341c59b483SKent Overstreet 	return 0;
351c59b483SKent Overstreet }
361c59b483SKent Overstreet 
37*cb1b479dSKent Overstreet int bch2_snapshot_tree_lookup(struct btree_trans *trans, u32 id,
381c59b483SKent Overstreet 			      struct bch_snapshot_tree *s)
391c59b483SKent Overstreet {
401c59b483SKent Overstreet 	return bch2_bkey_get_val_typed(trans, BTREE_ID_snapshot_trees, POS(0, id),
411c59b483SKent Overstreet 				       BTREE_ITER_WITH_UPDATES, snapshot_tree, s);
421c59b483SKent Overstreet }
431c59b483SKent Overstreet 
441c59b483SKent Overstreet static struct bkey_i_snapshot_tree *
451c59b483SKent Overstreet __snapshot_tree_create(struct btree_trans *trans)
461c59b483SKent Overstreet {
471c59b483SKent Overstreet 	struct btree_iter iter;
481c59b483SKent Overstreet 	int ret = bch2_bkey_get_empty_slot(trans, &iter,
491c59b483SKent Overstreet 			BTREE_ID_snapshot_trees, POS(0, U32_MAX));
501c59b483SKent Overstreet 	struct bkey_i_snapshot_tree *s_t;
511c59b483SKent Overstreet 
521c59b483SKent Overstreet 	if (ret == -BCH_ERR_ENOSPC_btree_slot)
531c59b483SKent Overstreet 		ret = -BCH_ERR_ENOSPC_snapshot_tree;
541c59b483SKent Overstreet 	if (ret)
551c59b483SKent Overstreet 		return ERR_PTR(ret);
561c59b483SKent Overstreet 
571c59b483SKent Overstreet 	s_t = bch2_bkey_alloc(trans, &iter, 0, snapshot_tree);
581c59b483SKent Overstreet 	ret = PTR_ERR_OR_ZERO(s_t);
591c59b483SKent Overstreet 	bch2_trans_iter_exit(trans, &iter);
601c59b483SKent Overstreet 	return ret ? ERR_PTR(ret) : s_t;
611c59b483SKent Overstreet }
621c59b483SKent Overstreet 
631c59b483SKent Overstreet static int snapshot_tree_create(struct btree_trans *trans,
641c59b483SKent Overstreet 				u32 root_id, u32 subvol_id, u32 *tree_id)
651c59b483SKent Overstreet {
661c59b483SKent Overstreet 	struct bkey_i_snapshot_tree *n_tree =
671c59b483SKent Overstreet 		__snapshot_tree_create(trans);
681c59b483SKent Overstreet 
691c59b483SKent Overstreet 	if (IS_ERR(n_tree))
701c59b483SKent Overstreet 		return PTR_ERR(n_tree);
711c59b483SKent Overstreet 
721c59b483SKent Overstreet 	n_tree->v.master_subvol	= cpu_to_le32(subvol_id);
731c59b483SKent Overstreet 	n_tree->v.root_snapshot	= cpu_to_le32(root_id);
741c59b483SKent Overstreet 	*tree_id = n_tree->k.p.offset;
751c59b483SKent Overstreet 	return 0;
761c59b483SKent Overstreet }
771c59b483SKent Overstreet 
781c59b483SKent Overstreet /* Snapshot nodes: */
791c59b483SKent Overstreet 
8014b393eeSKent Overstreet void bch2_snapshot_to_text(struct printbuf *out, struct bch_fs *c,
8114b393eeSKent Overstreet 			   struct bkey_s_c k)
8214b393eeSKent Overstreet {
8314b393eeSKent Overstreet 	struct bkey_s_c_snapshot s = bkey_s_c_to_snapshot(k);
8414b393eeSKent Overstreet 
85416cc426SKent Overstreet 	prt_printf(out, "is_subvol %llu deleted %llu parent %10u children %10u %10u subvol %u",
8614b393eeSKent Overstreet 	       BCH_SNAPSHOT_SUBVOL(s.v),
8714b393eeSKent Overstreet 	       BCH_SNAPSHOT_DELETED(s.v),
8814b393eeSKent Overstreet 	       le32_to_cpu(s.v->parent),
8914b393eeSKent Overstreet 	       le32_to_cpu(s.v->children[0]),
9014b393eeSKent Overstreet 	       le32_to_cpu(s.v->children[1]),
9114b393eeSKent Overstreet 	       le32_to_cpu(s.v->subvol));
9214b393eeSKent Overstreet }
9314b393eeSKent Overstreet 
94f0ac7df2SKent Overstreet int bch2_snapshot_invalid(const struct bch_fs *c, struct bkey_s_c k,
95facafdcbSKent Overstreet 			  unsigned flags, struct printbuf *err)
9614b393eeSKent Overstreet {
9714b393eeSKent Overstreet 	struct bkey_s_c_snapshot s;
9814b393eeSKent Overstreet 	u32 i, id;
9914b393eeSKent Overstreet 
100e88a75ebSKent Overstreet 	if (bkey_gt(k.k->p, POS(0, U32_MAX)) ||
101e88a75ebSKent Overstreet 	    bkey_lt(k.k->p, POS(0, 1))) {
102401ec4dbSKent Overstreet 		prt_printf(err, "bad pos");
10378c0b75cSKent Overstreet 		return -BCH_ERR_invalid_bkey;
104f0ac7df2SKent Overstreet 	}
10514b393eeSKent Overstreet 
10614b393eeSKent Overstreet 	s = bkey_s_c_to_snapshot(k);
10714b393eeSKent Overstreet 
10814b393eeSKent Overstreet 	id = le32_to_cpu(s.v->parent);
109f0ac7df2SKent Overstreet 	if (id && id <= k.k->p.offset) {
110401ec4dbSKent Overstreet 		prt_printf(err, "bad parent node (%u <= %llu)",
111f0ac7df2SKent Overstreet 		       id, k.k->p.offset);
11278c0b75cSKent Overstreet 		return -BCH_ERR_invalid_bkey;
113f0ac7df2SKent Overstreet 	}
11414b393eeSKent Overstreet 
115f0ac7df2SKent Overstreet 	if (le32_to_cpu(s.v->children[0]) < le32_to_cpu(s.v->children[1])) {
116401ec4dbSKent Overstreet 		prt_printf(err, "children not normalized");
11778c0b75cSKent Overstreet 		return -BCH_ERR_invalid_bkey;
118f0ac7df2SKent Overstreet 	}
11914b393eeSKent Overstreet 
12014b393eeSKent Overstreet 	if (s.v->children[0] &&
121f0ac7df2SKent Overstreet 	    s.v->children[0] == s.v->children[1]) {
122401ec4dbSKent Overstreet 		prt_printf(err, "duplicate child nodes");
12378c0b75cSKent Overstreet 		return -BCH_ERR_invalid_bkey;
124f0ac7df2SKent Overstreet 	}
12514b393eeSKent Overstreet 
12614b393eeSKent Overstreet 	for (i = 0; i < 2; i++) {
12714b393eeSKent Overstreet 		id = le32_to_cpu(s.v->children[i]);
12814b393eeSKent Overstreet 
129f0ac7df2SKent Overstreet 		if (id >= k.k->p.offset) {
130401ec4dbSKent Overstreet 			prt_printf(err, "bad child node (%u >= %llu)",
131f0ac7df2SKent Overstreet 			       id, k.k->p.offset);
13278c0b75cSKent Overstreet 			return -BCH_ERR_invalid_bkey;
133f0ac7df2SKent Overstreet 		}
13414b393eeSKent Overstreet 	}
13514b393eeSKent Overstreet 
136f0ac7df2SKent Overstreet 	return 0;
13714b393eeSKent Overstreet }
13814b393eeSKent Overstreet 
139904823deSKent Overstreet int bch2_mark_snapshot(struct btree_trans *trans,
1402611a041SKent Overstreet 		       enum btree_id btree, unsigned level,
14114b393eeSKent Overstreet 		       struct bkey_s_c old, struct bkey_s_c new,
142904823deSKent Overstreet 		       unsigned flags)
14314b393eeSKent Overstreet {
144904823deSKent Overstreet 	struct bch_fs *c = trans->c;
14514b393eeSKent Overstreet 	struct snapshot_t *t;
14614b393eeSKent Overstreet 
14714b393eeSKent Overstreet 	t = genradix_ptr_alloc(&c->snapshots,
14814b393eeSKent Overstreet 			       U32_MAX - new.k->p.offset,
14914b393eeSKent Overstreet 			       GFP_KERNEL);
15014b393eeSKent Overstreet 	if (!t)
15165d48e35SKent Overstreet 		return -BCH_ERR_ENOMEM_mark_snapshot;
15214b393eeSKent Overstreet 
15314b393eeSKent Overstreet 	if (new.k->type == KEY_TYPE_snapshot) {
15414b393eeSKent Overstreet 		struct bkey_s_c_snapshot s = bkey_s_c_to_snapshot(new);
15514b393eeSKent Overstreet 
15614b393eeSKent Overstreet 		t->parent	= le32_to_cpu(s.v->parent);
15714b393eeSKent Overstreet 		t->children[0]	= le32_to_cpu(s.v->children[0]);
15814b393eeSKent Overstreet 		t->children[1]	= le32_to_cpu(s.v->children[1]);
15914b393eeSKent Overstreet 		t->subvol	= BCH_SNAPSHOT_SUBVOL(s.v) ? le32_to_cpu(s.v->subvol) : 0;
1601c59b483SKent Overstreet 		t->tree		= le32_to_cpu(s.v->tree);
16114b393eeSKent Overstreet 	} else {
16214b393eeSKent Overstreet 		t->parent	= 0;
16314b393eeSKent Overstreet 		t->children[0]	= 0;
16414b393eeSKent Overstreet 		t->children[1]	= 0;
16514b393eeSKent Overstreet 		t->subvol	= 0;
1661c59b483SKent Overstreet 		t->tree		= 0;
16714b393eeSKent Overstreet 	}
16814b393eeSKent Overstreet 
16914b393eeSKent Overstreet 	return 0;
17014b393eeSKent Overstreet }
17114b393eeSKent Overstreet 
17214b393eeSKent Overstreet static int snapshot_lookup(struct btree_trans *trans, u32 id,
17314b393eeSKent Overstreet 			   struct bch_snapshot *s)
17414b393eeSKent Overstreet {
175bcb79a51SKent Overstreet 	return bch2_bkey_get_val_typed(trans, BTREE_ID_snapshots, POS(0, id),
176bcb79a51SKent Overstreet 				       BTREE_ITER_WITH_UPDATES, snapshot, s);
17714b393eeSKent Overstreet }
17814b393eeSKent Overstreet 
17914b393eeSKent Overstreet static int snapshot_live(struct btree_trans *trans, u32 id)
18014b393eeSKent Overstreet {
18114b393eeSKent Overstreet 	struct bch_snapshot v;
18214b393eeSKent Overstreet 	int ret;
18314b393eeSKent Overstreet 
18414b393eeSKent Overstreet 	if (!id)
18514b393eeSKent Overstreet 		return 0;
18614b393eeSKent Overstreet 
187a1783320SKent Overstreet 	ret = snapshot_lookup(trans, id, &v);
1881c59b483SKent Overstreet 	if (bch2_err_matches(ret, ENOENT))
18914b393eeSKent Overstreet 		bch_err(trans->c, "snapshot node %u not found", id);
19014b393eeSKent Overstreet 	if (ret)
19114b393eeSKent Overstreet 		return ret;
19214b393eeSKent Overstreet 
19314b393eeSKent Overstreet 	return !BCH_SNAPSHOT_DELETED(&v);
19414b393eeSKent Overstreet }
19514b393eeSKent Overstreet 
196a1783320SKent Overstreet static int bch2_snapshot_set_equiv(struct btree_trans *trans, struct bkey_s_c k)
19714b393eeSKent Overstreet {
19814b393eeSKent Overstreet 	struct bch_fs *c = trans->c;
19935f1a503SKent Overstreet 	unsigned i, nr_live = 0, live_idx = 0;
200a1783320SKent Overstreet 	struct bkey_s_c_snapshot snap;
201a1783320SKent Overstreet 	u32 id = k.k->p.offset, child[2];
202a1783320SKent Overstreet 
203a1783320SKent Overstreet 	if (k.k->type != KEY_TYPE_snapshot)
204a1783320SKent Overstreet 		return 0;
205a1783320SKent Overstreet 
206a1783320SKent Overstreet 	snap = bkey_s_c_to_snapshot(k);
207a1783320SKent Overstreet 
208a1783320SKent Overstreet 	child[0] = le32_to_cpu(snap.v->children[0]);
209a1783320SKent Overstreet 	child[1] = le32_to_cpu(snap.v->children[1]);
21014b393eeSKent Overstreet 
21114b393eeSKent Overstreet 	for (i = 0; i < 2; i++) {
21235f1a503SKent Overstreet 		int ret = snapshot_live(trans, child[i]);
213a1019576SKent Overstreet 
21414b393eeSKent Overstreet 		if (ret < 0)
21535f1a503SKent Overstreet 			return ret;
21614b393eeSKent Overstreet 
21714b393eeSKent Overstreet 		if (ret)
21814b393eeSKent Overstreet 			live_idx = i;
21914b393eeSKent Overstreet 		nr_live += ret;
22014b393eeSKent Overstreet 	}
22114b393eeSKent Overstreet 
22214b393eeSKent Overstreet 	snapshot_t(c, id)->equiv = nr_live == 1
22314b393eeSKent Overstreet 		? snapshot_t(c, child[live_idx])->equiv
22414b393eeSKent Overstreet 		: id;
22535f1a503SKent Overstreet 	return 0;
22614b393eeSKent Overstreet }
22735f1a503SKent Overstreet 
22814b393eeSKent Overstreet /* fsck: */
2291c59b483SKent Overstreet 
2301c59b483SKent Overstreet static u32 bch2_snapshot_child(struct bch_fs *c, u32 id, unsigned child)
2311c59b483SKent Overstreet {
2321c59b483SKent Overstreet 	return snapshot_t(c, id)->children[child];
2331c59b483SKent Overstreet }
2341c59b483SKent Overstreet 
2351c59b483SKent Overstreet static u32 bch2_snapshot_left_child(struct bch_fs *c, u32 id)
2361c59b483SKent Overstreet {
2371c59b483SKent Overstreet 	return bch2_snapshot_child(c, id, 0);
2381c59b483SKent Overstreet }
2391c59b483SKent Overstreet 
2401c59b483SKent Overstreet static u32 bch2_snapshot_right_child(struct bch_fs *c, u32 id)
2411c59b483SKent Overstreet {
2421c59b483SKent Overstreet 	return bch2_snapshot_child(c, id, 1);
2431c59b483SKent Overstreet }
2441c59b483SKent Overstreet 
2451c59b483SKent Overstreet static u32 bch2_snapshot_tree_next(struct bch_fs *c, u32 id)
2461c59b483SKent Overstreet {
2471c59b483SKent Overstreet 	u32 n, parent;
2481c59b483SKent Overstreet 
2491c59b483SKent Overstreet 	n = bch2_snapshot_left_child(c, id);
2501c59b483SKent Overstreet 	if (n)
2511c59b483SKent Overstreet 		return n;
2521c59b483SKent Overstreet 
2531c59b483SKent Overstreet 	while ((parent = bch2_snapshot_parent(c, id))) {
2541c59b483SKent Overstreet 		n = bch2_snapshot_right_child(c, parent);
2551c59b483SKent Overstreet 		if (n && n != id)
2561c59b483SKent Overstreet 			return n;
2571c59b483SKent Overstreet 		id = parent;
2581c59b483SKent Overstreet 	}
2591c59b483SKent Overstreet 
2601c59b483SKent Overstreet 	return 0;
2611c59b483SKent Overstreet }
2621c59b483SKent Overstreet 
2631c59b483SKent Overstreet static u32 bch2_snapshot_tree_oldest_subvol(struct bch_fs *c, u32 snapshot_root)
2641c59b483SKent Overstreet {
2651c59b483SKent Overstreet 	u32 id = snapshot_root;
2661c59b483SKent Overstreet 	u32 subvol = 0, s;
2671c59b483SKent Overstreet 
2681c59b483SKent Overstreet 	while (id) {
2691c59b483SKent Overstreet 		s = snapshot_t(c, id)->subvol;
2701c59b483SKent Overstreet 
2711c59b483SKent Overstreet 		if (s && (!subvol || s < subvol))
2721c59b483SKent Overstreet 			subvol = s;
2731c59b483SKent Overstreet 
2741c59b483SKent Overstreet 		id = bch2_snapshot_tree_next(c, id);
2751c59b483SKent Overstreet 	}
2761c59b483SKent Overstreet 
2771c59b483SKent Overstreet 	return subvol;
2781c59b483SKent Overstreet }
2791c59b483SKent Overstreet 
2801c59b483SKent Overstreet static int bch2_snapshot_tree_master_subvol(struct btree_trans *trans,
2811c59b483SKent Overstreet 					    u32 snapshot_root, u32 *subvol_id)
2821c59b483SKent Overstreet {
2831c59b483SKent Overstreet 	struct bch_fs *c = trans->c;
2841c59b483SKent Overstreet 	struct btree_iter iter;
2851c59b483SKent Overstreet 	struct bkey_s_c k;
2861c59b483SKent Overstreet 	struct bkey_s_c_subvolume s;
2871c59b483SKent Overstreet 	int ret;
2881c59b483SKent Overstreet 
2891c59b483SKent Overstreet 	for_each_btree_key_norestart(trans, iter, BTREE_ID_subvolumes, POS_MIN,
2901c59b483SKent Overstreet 				     0, k, ret) {
2911c59b483SKent Overstreet 		if (k.k->type != KEY_TYPE_subvolume)
2921c59b483SKent Overstreet 			continue;
2931c59b483SKent Overstreet 
2941c59b483SKent Overstreet 		s = bkey_s_c_to_subvolume(k);
2951c59b483SKent Overstreet 		if (!bch2_snapshot_is_ancestor(c, le32_to_cpu(s.v->snapshot), snapshot_root))
2961c59b483SKent Overstreet 			continue;
2971c59b483SKent Overstreet 		if (!BCH_SUBVOLUME_SNAP(s.v)) {
2981c59b483SKent Overstreet 			*subvol_id = s.k->p.offset;
2991c59b483SKent Overstreet 			goto found;
3001c59b483SKent Overstreet 		}
3011c59b483SKent Overstreet 	}
3021c59b483SKent Overstreet 	ret = ret ?: -ENOENT;
3031c59b483SKent Overstreet found:
3041c59b483SKent Overstreet 	bch2_trans_iter_exit(trans, &iter);
3051c59b483SKent Overstreet 
3061c59b483SKent Overstreet 	if (bch2_err_matches(ret, ENOENT)) {
3071c59b483SKent Overstreet 		struct bkey_i_subvolume *s;
3081c59b483SKent Overstreet 
3091c59b483SKent Overstreet 		*subvol_id = bch2_snapshot_tree_oldest_subvol(c, snapshot_root);
3101c59b483SKent Overstreet 
3111c59b483SKent Overstreet 		s = bch2_bkey_get_mut_typed(trans, &iter,
3121c59b483SKent Overstreet 					    BTREE_ID_subvolumes, POS(0, *subvol_id),
3131c59b483SKent Overstreet 					    0, subvolume);
3141c59b483SKent Overstreet 		ret = PTR_ERR_OR_ZERO(s);
3151c59b483SKent Overstreet 		if (ret)
3161c59b483SKent Overstreet 			return ret;
3171c59b483SKent Overstreet 
3181c59b483SKent Overstreet 		SET_BCH_SUBVOLUME_SNAP(&s->v, false);
3191c59b483SKent Overstreet 	}
3201c59b483SKent Overstreet 
3211c59b483SKent Overstreet 	return ret;
3221c59b483SKent Overstreet }
3231c59b483SKent Overstreet 
3241c59b483SKent Overstreet static int check_snapshot_tree(struct btree_trans *trans,
3251c59b483SKent Overstreet 			       struct btree_iter *iter,
3261c59b483SKent Overstreet 			       struct bkey_s_c k)
3271c59b483SKent Overstreet {
3281c59b483SKent Overstreet 	struct bch_fs *c = trans->c;
3291c59b483SKent Overstreet 	struct bkey_s_c_snapshot_tree st;
3301c59b483SKent Overstreet 	struct bch_snapshot s;
3311c59b483SKent Overstreet 	struct bch_subvolume subvol;
3321c59b483SKent Overstreet 	struct printbuf buf = PRINTBUF;
3331c59b483SKent Overstreet 	u32 root_id;
3341c59b483SKent Overstreet 	int ret;
3351c59b483SKent Overstreet 
3361c59b483SKent Overstreet 	if (k.k->type != KEY_TYPE_snapshot_tree)
3371c59b483SKent Overstreet 		return 0;
3381c59b483SKent Overstreet 
3391c59b483SKent Overstreet 	st = bkey_s_c_to_snapshot_tree(k);
3401c59b483SKent Overstreet 	root_id = le32_to_cpu(st.v->root_snapshot);
3411c59b483SKent Overstreet 
3421c59b483SKent Overstreet 	ret = snapshot_lookup(trans, root_id, &s);
3431c59b483SKent Overstreet 	if (ret && !bch2_err_matches(ret, ENOENT))
3441c59b483SKent Overstreet 		goto err;
3451c59b483SKent Overstreet 
3461c59b483SKent Overstreet 	if (fsck_err_on(ret ||
3471c59b483SKent Overstreet 			root_id != bch2_snapshot_root(c, root_id) ||
3481c59b483SKent Overstreet 			st.k->p.offset != le32_to_cpu(s.tree),
3491c59b483SKent Overstreet 			c,
3501c59b483SKent Overstreet 			"snapshot tree points to missing/incorrect snapshot:\n  %s",
3511c59b483SKent Overstreet 			(bch2_bkey_val_to_text(&buf, c, st.s_c), buf.buf))) {
3521c59b483SKent Overstreet 		ret = bch2_btree_delete_at(trans, iter, 0);
3531c59b483SKent Overstreet 		goto err;
3541c59b483SKent Overstreet 	}
3551c59b483SKent Overstreet 
3561c59b483SKent Overstreet 	ret = bch2_subvolume_get(trans, le32_to_cpu(st.v->master_subvol),
3571c59b483SKent Overstreet 				 false, 0, &subvol);
3581c59b483SKent Overstreet 	if (ret && !bch2_err_matches(ret, ENOENT))
3591c59b483SKent Overstreet 		goto err;
3601c59b483SKent Overstreet 
3611c59b483SKent Overstreet 	if (fsck_err_on(ret, c,
3621c59b483SKent Overstreet 			"snapshot tree points to missing subvolume:\n  %s",
3631c59b483SKent Overstreet 			(printbuf_reset(&buf),
3641c59b483SKent Overstreet 			 bch2_bkey_val_to_text(&buf, c, st.s_c), buf.buf)) ||
3651c59b483SKent Overstreet 	    fsck_err_on(!bch2_snapshot_is_ancestor(c,
3661c59b483SKent Overstreet 						   le32_to_cpu(subvol.snapshot),
3671c59b483SKent Overstreet 						   root_id), c,
3681c59b483SKent Overstreet 			"snapshot tree points to subvolume that does not point to snapshot in this tree:\n  %s",
3691c59b483SKent Overstreet 			(printbuf_reset(&buf),
3701c59b483SKent Overstreet 			 bch2_bkey_val_to_text(&buf, c, st.s_c), buf.buf)) ||
3711c59b483SKent Overstreet 	    fsck_err_on(BCH_SUBVOLUME_SNAP(&subvol), c,
3721c59b483SKent Overstreet 			"snapshot tree points to snapshot subvolume:\n  %s",
3731c59b483SKent Overstreet 			(printbuf_reset(&buf),
3741c59b483SKent Overstreet 			 bch2_bkey_val_to_text(&buf, c, st.s_c), buf.buf))) {
3751c59b483SKent Overstreet 		struct bkey_i_snapshot_tree *u;
3761c59b483SKent Overstreet 		u32 subvol_id;
3771c59b483SKent Overstreet 
3781c59b483SKent Overstreet 		ret = bch2_snapshot_tree_master_subvol(trans, root_id, &subvol_id);
3791c59b483SKent Overstreet 		if (ret)
3801c59b483SKent Overstreet 			goto err;
3811c59b483SKent Overstreet 
3821c59b483SKent Overstreet 		u = bch2_bkey_make_mut_typed(trans, iter, k, 0, snapshot_tree);
3831c59b483SKent Overstreet 		ret = PTR_ERR_OR_ZERO(u);
3841c59b483SKent Overstreet 		if (ret)
3851c59b483SKent Overstreet 			goto err;
3861c59b483SKent Overstreet 
3871c59b483SKent Overstreet 		u->v.master_subvol = cpu_to_le32(subvol_id);
3881c59b483SKent Overstreet 		st = snapshot_tree_i_to_s_c(u);
3891c59b483SKent Overstreet 	}
3901c59b483SKent Overstreet err:
3911c59b483SKent Overstreet fsck_err:
3921c59b483SKent Overstreet 	printbuf_exit(&buf);
3931c59b483SKent Overstreet 	return ret;
3941c59b483SKent Overstreet }
3951c59b483SKent Overstreet 
3961c59b483SKent Overstreet /*
3971c59b483SKent Overstreet  * For each snapshot_tree, make sure it points to the root of a snapshot tree
3981c59b483SKent Overstreet  * and that snapshot entry points back to it, or delete it.
3991c59b483SKent Overstreet  *
4001c59b483SKent Overstreet  * And, make sure it points to a subvolume within that snapshot tree, or correct
4011c59b483SKent Overstreet  * it to point to the oldest subvolume within that snapshot tree.
4021c59b483SKent Overstreet  */
4031c59b483SKent Overstreet int bch2_fs_check_snapshot_trees(struct bch_fs *c)
4041c59b483SKent Overstreet {
4051c59b483SKent Overstreet 	struct btree_iter iter;
4061c59b483SKent Overstreet 	struct bkey_s_c k;
4071c59b483SKent Overstreet 	int ret;
4081c59b483SKent Overstreet 
4091c59b483SKent Overstreet 	ret = bch2_trans_run(c,
4101c59b483SKent Overstreet 		for_each_btree_key_commit(&trans, iter,
4111c59b483SKent Overstreet 			BTREE_ID_snapshot_trees, POS_MIN,
4121c59b483SKent Overstreet 			BTREE_ITER_PREFETCH, k,
4131c59b483SKent Overstreet 			NULL, NULL, BTREE_INSERT_LAZY_RW|BTREE_INSERT_NOFAIL,
4141c59b483SKent Overstreet 		check_snapshot_tree(&trans, &iter, k)));
4151c59b483SKent Overstreet 
4161c59b483SKent Overstreet 	if (ret)
4171c59b483SKent Overstreet 		bch_err(c, "error %i checking snapshot trees", ret);
4181c59b483SKent Overstreet 	return ret;
4191c59b483SKent Overstreet }
4201c59b483SKent Overstreet 
4211c59b483SKent Overstreet /*
4221c59b483SKent Overstreet  * Look up snapshot tree for @tree_id and find root,
4231c59b483SKent Overstreet  * make sure @snap_id is a descendent:
4241c59b483SKent Overstreet  */
4251c59b483SKent Overstreet static int snapshot_tree_ptr_good(struct btree_trans *trans,
4261c59b483SKent Overstreet 				  u32 snap_id, u32 tree_id)
4271c59b483SKent Overstreet {
4281c59b483SKent Overstreet 	struct bch_snapshot_tree s_t;
429*cb1b479dSKent Overstreet 	int ret = bch2_snapshot_tree_lookup(trans, tree_id, &s_t);
4301c59b483SKent Overstreet 
4311c59b483SKent Overstreet 	if (bch2_err_matches(ret, ENOENT))
4321c59b483SKent Overstreet 		return 0;
4331c59b483SKent Overstreet 	if (ret)
4341c59b483SKent Overstreet 		return ret;
4351c59b483SKent Overstreet 
4361c59b483SKent Overstreet 	return bch2_snapshot_is_ancestor(trans->c, snap_id, le32_to_cpu(s_t.root_snapshot));
4371c59b483SKent Overstreet }
4381c59b483SKent Overstreet 
4391c59b483SKent Overstreet /*
4401c59b483SKent Overstreet  * snapshot_tree pointer was incorrect: look up root snapshot node, make sure
4411c59b483SKent Overstreet  * its snapshot_tree pointer is correct (allocate new one if necessary), then
4421c59b483SKent Overstreet  * update this node's pointer to root node's pointer:
4431c59b483SKent Overstreet  */
4441c59b483SKent Overstreet static int snapshot_tree_ptr_repair(struct btree_trans *trans,
4451c59b483SKent Overstreet 				    struct btree_iter *iter,
4461c59b483SKent Overstreet 				    struct bkey_s_c_snapshot *s)
4471c59b483SKent Overstreet {
4481c59b483SKent Overstreet 	struct bch_fs *c = trans->c;
4491c59b483SKent Overstreet 	struct btree_iter root_iter;
4501c59b483SKent Overstreet 	struct bch_snapshot_tree s_t;
4511c59b483SKent Overstreet 	struct bkey_s_c_snapshot root;
4521c59b483SKent Overstreet 	struct bkey_i_snapshot *u;
4531c59b483SKent Overstreet 	u32 root_id = bch2_snapshot_root(c, s->k->p.offset), tree_id;
4541c59b483SKent Overstreet 	int ret;
4551c59b483SKent Overstreet 
4561c59b483SKent Overstreet 	root = bch2_bkey_get_iter_typed(trans, &root_iter,
4571c59b483SKent Overstreet 			       BTREE_ID_snapshots, POS(0, root_id),
4581c59b483SKent Overstreet 			       BTREE_ITER_WITH_UPDATES, snapshot);
4591c59b483SKent Overstreet 	ret = bkey_err(root);
4601c59b483SKent Overstreet 	if (ret)
4611c59b483SKent Overstreet 		goto err;
4621c59b483SKent Overstreet 
4631c59b483SKent Overstreet 	tree_id = le32_to_cpu(root.v->tree);
4641c59b483SKent Overstreet 
465*cb1b479dSKent Overstreet 	ret = bch2_snapshot_tree_lookup(trans, tree_id, &s_t);
4661c59b483SKent Overstreet 	if (ret && !bch2_err_matches(ret, ENOENT))
4671c59b483SKent Overstreet 		return ret;
4681c59b483SKent Overstreet 
4691c59b483SKent Overstreet 	if (ret || le32_to_cpu(s_t.root_snapshot) != root_id) {
4701c59b483SKent Overstreet 		u = bch2_bkey_make_mut_typed(trans, &root_iter, root.s_c, 0, snapshot);
4711c59b483SKent Overstreet 		ret =   PTR_ERR_OR_ZERO(u) ?:
4721c59b483SKent Overstreet 			snapshot_tree_create(trans, root_id,
4731c59b483SKent Overstreet 				bch2_snapshot_tree_oldest_subvol(c, root_id),
4741c59b483SKent Overstreet 				&tree_id);
4751c59b483SKent Overstreet 		if (ret)
4761c59b483SKent Overstreet 			goto err;
4771c59b483SKent Overstreet 
4781c59b483SKent Overstreet 		u->v.tree = cpu_to_le32(tree_id);
4791c59b483SKent Overstreet 		if (s->k->p.snapshot == root_id)
4801c59b483SKent Overstreet 			*s = snapshot_i_to_s_c(u);
4811c59b483SKent Overstreet 	}
4821c59b483SKent Overstreet 
4831c59b483SKent Overstreet 	if (s->k->p.snapshot != root_id) {
4841c59b483SKent Overstreet 		u = bch2_bkey_make_mut_typed(trans, iter, s->s_c, 0, snapshot);
4851c59b483SKent Overstreet 		ret = PTR_ERR_OR_ZERO(u);
4861c59b483SKent Overstreet 		if (ret)
4871c59b483SKent Overstreet 			goto err;
4881c59b483SKent Overstreet 
4891c59b483SKent Overstreet 		u->v.tree = cpu_to_le32(tree_id);
4901c59b483SKent Overstreet 		*s = snapshot_i_to_s_c(u);
4911c59b483SKent Overstreet 	}
4921c59b483SKent Overstreet err:
4931c59b483SKent Overstreet 	bch2_trans_iter_exit(trans, &root_iter);
4941c59b483SKent Overstreet 	return ret;
4951c59b483SKent Overstreet }
4961c59b483SKent Overstreet 
49735f1a503SKent Overstreet static int check_snapshot(struct btree_trans *trans,
498a1783320SKent Overstreet 			  struct btree_iter *iter,
499a1783320SKent Overstreet 			  struct bkey_s_c k)
50014b393eeSKent Overstreet {
50135f1a503SKent Overstreet 	struct bch_fs *c = trans->c;
50235f1a503SKent Overstreet 	struct bkey_s_c_snapshot s;
50314b393eeSKent Overstreet 	struct bch_subvolume subvol;
50414b393eeSKent Overstreet 	struct bch_snapshot v;
50535f1a503SKent Overstreet 	struct printbuf buf = PRINTBUF;
50635f1a503SKent Overstreet 	bool should_have_subvol;
50714b393eeSKent Overstreet 	u32 i, id;
50835f1a503SKent Overstreet 	int ret = 0;
50914b393eeSKent Overstreet 
51035f1a503SKent Overstreet 	if (k.k->type != KEY_TYPE_snapshot)
51135f1a503SKent Overstreet 		return 0;
51214b393eeSKent Overstreet 
51335f1a503SKent Overstreet 	s = bkey_s_c_to_snapshot(k);
51414b393eeSKent Overstreet 	id = le32_to_cpu(s.v->parent);
51514b393eeSKent Overstreet 	if (id) {
516a1783320SKent Overstreet 		ret = snapshot_lookup(trans, id, &v);
5171c59b483SKent Overstreet 		if (bch2_err_matches(ret, ENOENT))
51835f1a503SKent Overstreet 			bch_err(c, "snapshot with nonexistent parent:\n  %s",
51935f1a503SKent Overstreet 				(bch2_bkey_val_to_text(&buf, c, s.s_c), buf.buf));
52014b393eeSKent Overstreet 		if (ret)
52135f1a503SKent Overstreet 			goto err;
52214b393eeSKent Overstreet 
52314b393eeSKent Overstreet 		if (le32_to_cpu(v.children[0]) != s.k->p.offset &&
52414b393eeSKent Overstreet 		    le32_to_cpu(v.children[1]) != s.k->p.offset) {
52535f1a503SKent Overstreet 			bch_err(c, "snapshot parent %u missing pointer to child %llu",
52614b393eeSKent Overstreet 				id, s.k->p.offset);
52735f1a503SKent Overstreet 			ret = -EINVAL;
52835f1a503SKent Overstreet 			goto err;
52914b393eeSKent Overstreet 		}
53014b393eeSKent Overstreet 	}
53114b393eeSKent Overstreet 
53214b393eeSKent Overstreet 	for (i = 0; i < 2 && s.v->children[i]; i++) {
53314b393eeSKent Overstreet 		id = le32_to_cpu(s.v->children[i]);
53414b393eeSKent Overstreet 
535a1783320SKent Overstreet 		ret = snapshot_lookup(trans, id, &v);
5361c59b483SKent Overstreet 		if (bch2_err_matches(ret, ENOENT))
53735f1a503SKent Overstreet 			bch_err(c, "snapshot node %llu has nonexistent child %u",
53814b393eeSKent Overstreet 				s.k->p.offset, id);
53914b393eeSKent Overstreet 		if (ret)
54035f1a503SKent Overstreet 			goto err;
54114b393eeSKent Overstreet 
54214b393eeSKent Overstreet 		if (le32_to_cpu(v.parent) != s.k->p.offset) {
54335f1a503SKent Overstreet 			bch_err(c, "snapshot child %u has wrong parent (got %u should be %llu)",
54414b393eeSKent Overstreet 				id, le32_to_cpu(v.parent), s.k->p.offset);
54535f1a503SKent Overstreet 			ret = -EINVAL;
54635f1a503SKent Overstreet 			goto err;
54714b393eeSKent Overstreet 		}
54814b393eeSKent Overstreet 	}
54914b393eeSKent Overstreet 
55035f1a503SKent Overstreet 	should_have_subvol = BCH_SNAPSHOT_SUBVOL(s.v) &&
55135f1a503SKent Overstreet 		!BCH_SNAPSHOT_DELETED(s.v);
55235f1a503SKent Overstreet 
55335f1a503SKent Overstreet 	if (should_have_subvol) {
55435f1a503SKent Overstreet 		id = le32_to_cpu(s.v->subvol);
555a1783320SKent Overstreet 		ret = bch2_subvolume_get(trans, id, 0, false, &subvol);
5561c59b483SKent Overstreet 		if (bch2_err_matches(ret, ENOENT))
55735f1a503SKent Overstreet 			bch_err(c, "snapshot points to nonexistent subvolume:\n  %s",
55835f1a503SKent Overstreet 				(bch2_bkey_val_to_text(&buf, c, s.s_c), buf.buf));
55935f1a503SKent Overstreet 		if (ret)
56035f1a503SKent Overstreet 			goto err;
56135f1a503SKent Overstreet 
56235f1a503SKent Overstreet 		if (BCH_SNAPSHOT_SUBVOL(s.v) != (le32_to_cpu(subvol.snapshot) == s.k->p.offset)) {
56335f1a503SKent Overstreet 			bch_err(c, "snapshot node %llu has wrong BCH_SNAPSHOT_SUBVOL",
56435f1a503SKent Overstreet 				s.k->p.offset);
56535f1a503SKent Overstreet 			ret = -EINVAL;
56635f1a503SKent Overstreet 			goto err;
56735f1a503SKent Overstreet 		}
56835f1a503SKent Overstreet 	} else {
56935f1a503SKent Overstreet 		if (fsck_err_on(s.v->subvol, c, "snapshot should not point to subvol:\n  %s",
57035f1a503SKent Overstreet 				(bch2_bkey_val_to_text(&buf, c, s.s_c), buf.buf))) {
57135f1a503SKent Overstreet 			struct bkey_i_snapshot *u = bch2_trans_kmalloc(trans, sizeof(*u));
57235f1a503SKent Overstreet 
57335f1a503SKent Overstreet 			ret = PTR_ERR_OR_ZERO(u);
57435f1a503SKent Overstreet 			if (ret)
57535f1a503SKent Overstreet 				goto err;
57635f1a503SKent Overstreet 
57735f1a503SKent Overstreet 			bkey_reassemble(&u->k_i, s.s_c);
57835f1a503SKent Overstreet 			u->v.subvol = 0;
57935f1a503SKent Overstreet 			ret = bch2_trans_update(trans, iter, &u->k_i, 0);
58035f1a503SKent Overstreet 			if (ret)
58135f1a503SKent Overstreet 				goto err;
5821c59b483SKent Overstreet 
5831c59b483SKent Overstreet 			s = snapshot_i_to_s_c(u);
58435f1a503SKent Overstreet 		}
58535f1a503SKent Overstreet 	}
58635f1a503SKent Overstreet 
5871c59b483SKent Overstreet 	ret = snapshot_tree_ptr_good(trans, s.k->p.offset, le32_to_cpu(s.v->tree));
5881c59b483SKent Overstreet 	if (ret < 0)
5891c59b483SKent Overstreet 		goto err;
5901c59b483SKent Overstreet 
5911c59b483SKent Overstreet 	if (fsck_err_on(!ret, c, "snapshot points to missing/incorrect tree:\n  %s",
5921c59b483SKent Overstreet 			(bch2_bkey_val_to_text(&buf, c, s.s_c), buf.buf))) {
5931c59b483SKent Overstreet 		ret = snapshot_tree_ptr_repair(trans, iter, &s);
5941c59b483SKent Overstreet 		if (ret)
5951c59b483SKent Overstreet 			goto err;
5961c59b483SKent Overstreet 	}
5971c59b483SKent Overstreet 	ret = 0;
5981c59b483SKent Overstreet 
59935f1a503SKent Overstreet 	if (BCH_SNAPSHOT_DELETED(s.v))
60035f1a503SKent Overstreet 		set_bit(BCH_FS_HAVE_DELETED_SNAPSHOTS, &c->flags);
60135f1a503SKent Overstreet err:
60235f1a503SKent Overstreet fsck_err:
60335f1a503SKent Overstreet 	printbuf_exit(&buf);
60435f1a503SKent Overstreet 	return ret;
60514b393eeSKent Overstreet }
60614b393eeSKent Overstreet 
6074ab35c34SKent Overstreet int bch2_fs_check_snapshots(struct bch_fs *c)
60814b393eeSKent Overstreet {
60914b393eeSKent Overstreet 	struct btree_iter iter;
610a1783320SKent Overstreet 	struct bkey_s_c k;
61114b393eeSKent Overstreet 	int ret;
61214b393eeSKent Overstreet 
6131c59b483SKent Overstreet 	ret = bch2_trans_run(c,
6141c59b483SKent Overstreet 		for_each_btree_key_commit(&trans, iter,
615c59d66b5SKent Overstreet 			BTREE_ID_snapshots, POS_MIN,
616a1783320SKent Overstreet 			BTREE_ITER_PREFETCH, k,
617a1783320SKent Overstreet 			NULL, NULL, BTREE_INSERT_LAZY_RW|BTREE_INSERT_NOFAIL,
6181c59b483SKent Overstreet 		check_snapshot(&trans, &iter, k)));
61935f1a503SKent Overstreet 	if (ret)
6201c59b483SKent Overstreet 		bch_err(c, "%s: error %s", __func__, bch2_err_str(ret));
62114b393eeSKent Overstreet 	return ret;
62214b393eeSKent Overstreet }
62314b393eeSKent Overstreet 
6244ab35c34SKent Overstreet static int check_subvol(struct btree_trans *trans,
6256738dd19SKent Overstreet 			struct btree_iter *iter,
6266738dd19SKent Overstreet 			struct bkey_s_c k)
6274ab35c34SKent Overstreet {
6281c59b483SKent Overstreet 	struct bch_fs *c = trans->c;
6294ab35c34SKent Overstreet 	struct bkey_s_c_subvolume subvol;
63035f1a503SKent Overstreet 	struct bch_snapshot snapshot;
63135f1a503SKent Overstreet 	unsigned snapid;
6321c59b483SKent Overstreet 	int ret = 0;
6334ab35c34SKent Overstreet 
6344ab35c34SKent Overstreet 	if (k.k->type != KEY_TYPE_subvolume)
6354ab35c34SKent Overstreet 		return 0;
6364ab35c34SKent Overstreet 
6374ab35c34SKent Overstreet 	subvol = bkey_s_c_to_subvolume(k);
63835f1a503SKent Overstreet 	snapid = le32_to_cpu(subvol.v->snapshot);
63935f1a503SKent Overstreet 	ret = snapshot_lookup(trans, snapid, &snapshot);
64035f1a503SKent Overstreet 
6411c59b483SKent Overstreet 	if (bch2_err_matches(ret, ENOENT))
6421c59b483SKent Overstreet 		bch_err(c, "subvolume %llu points to nonexistent snapshot %u",
64335f1a503SKent Overstreet 			k.k->p.offset, snapid);
64435f1a503SKent Overstreet 	if (ret)
64535f1a503SKent Overstreet 		return ret;
6464ab35c34SKent Overstreet 
6474ab35c34SKent Overstreet 	if (BCH_SUBVOLUME_UNLINKED(subvol.v)) {
648653693beSKent Overstreet 		bch2_fs_lazy_rw(c);
649653693beSKent Overstreet 
6504ab35c34SKent Overstreet 		ret = bch2_subvolume_delete(trans, iter->pos.offset);
651653693beSKent Overstreet 		if (ret)
6521c59b483SKent Overstreet 			bch_err(c, "error deleting subvolume %llu: %s",
653d4bf5eecSKent Overstreet 				iter->pos.offset, bch2_err_str(ret));
654653693beSKent Overstreet 		return ret ?: -BCH_ERR_transaction_restart_nested;
6554ab35c34SKent Overstreet 	}
6564ab35c34SKent Overstreet 
6571c59b483SKent Overstreet 	if (!BCH_SUBVOLUME_SNAP(subvol.v)) {
6581c59b483SKent Overstreet 		u32 snapshot_root = bch2_snapshot_root(c, le32_to_cpu(subvol.v->snapshot));
6591c59b483SKent Overstreet 		u32 snapshot_tree = snapshot_t(c, snapshot_root)->tree;
6601c59b483SKent Overstreet 		struct bch_snapshot_tree st;
6611c59b483SKent Overstreet 
662*cb1b479dSKent Overstreet 		ret = bch2_snapshot_tree_lookup(trans, snapshot_tree, &st);
6631c59b483SKent Overstreet 
6641c59b483SKent Overstreet 		bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT), c,
6651c59b483SKent Overstreet 				"%s: snapshot tree %u not found", __func__, snapshot_tree);
6661c59b483SKent Overstreet 
6671c59b483SKent Overstreet 		if (ret)
6681c59b483SKent Overstreet 			return ret;
6691c59b483SKent Overstreet 
6701c59b483SKent Overstreet 		if (fsck_err_on(le32_to_cpu(st.master_subvol) != subvol.k->p.offset, c,
6711c59b483SKent Overstreet 				"subvolume %llu is not set as snapshot but is not master subvolume",
6721c59b483SKent Overstreet 				k.k->p.offset)) {
6731c59b483SKent Overstreet 			struct bkey_i_subvolume *s =
6741c59b483SKent Overstreet 				bch2_bkey_make_mut_typed(trans, iter, subvol.s_c, 0, subvolume);
6751c59b483SKent Overstreet 			ret = PTR_ERR_OR_ZERO(s);
6761c59b483SKent Overstreet 			if (ret)
6771c59b483SKent Overstreet 				return ret;
6781c59b483SKent Overstreet 
6791c59b483SKent Overstreet 			SET_BCH_SUBVOLUME_SNAP(&s->v, true);
6801c59b483SKent Overstreet 		}
6811c59b483SKent Overstreet 	}
6821c59b483SKent Overstreet 
6831c59b483SKent Overstreet fsck_err:
6841c59b483SKent Overstreet 	return ret;
6854ab35c34SKent Overstreet }
6864ab35c34SKent Overstreet 
6874ab35c34SKent Overstreet int bch2_fs_check_subvols(struct bch_fs *c)
6884ab35c34SKent Overstreet {
6894ab35c34SKent Overstreet 	struct btree_iter iter;
6906738dd19SKent Overstreet 	struct bkey_s_c k;
6914ab35c34SKent Overstreet 	int ret;
6924ab35c34SKent Overstreet 
6931c59b483SKent Overstreet 	ret = bch2_trans_run(c,
6941c59b483SKent Overstreet 		for_each_btree_key_commit(&trans, iter,
6956738dd19SKent Overstreet 			BTREE_ID_subvolumes, POS_MIN, BTREE_ITER_PREFETCH, k,
6966738dd19SKent Overstreet 			NULL, NULL, BTREE_INSERT_LAZY_RW|BTREE_INSERT_NOFAIL,
6971c59b483SKent Overstreet 		check_subvol(&trans, &iter, k)));
6981c59b483SKent Overstreet 	if (ret)
6991c59b483SKent Overstreet 		bch_err(c, "%s: error %s", __func__, bch2_err_str(ret));
7004ab35c34SKent Overstreet 
7014ab35c34SKent Overstreet 	return ret;
7024ab35c34SKent Overstreet }
7034ab35c34SKent Overstreet 
70414b393eeSKent Overstreet void bch2_fs_snapshots_exit(struct bch_fs *c)
70514b393eeSKent Overstreet {
70614b393eeSKent Overstreet 	genradix_free(&c->snapshots);
70714b393eeSKent Overstreet }
70814b393eeSKent Overstreet 
70914b393eeSKent Overstreet int bch2_fs_snapshots_start(struct bch_fs *c)
71014b393eeSKent Overstreet {
71114b393eeSKent Overstreet 	struct btree_iter iter;
71214b393eeSKent Overstreet 	struct bkey_s_c k;
71314b393eeSKent Overstreet 	int ret = 0;
71414b393eeSKent Overstreet 
7151c59b483SKent Overstreet 	ret = bch2_trans_run(c,
716a1783320SKent Overstreet 		for_each_btree_key2(&trans, iter, BTREE_ID_snapshots,
717a1783320SKent Overstreet 			   POS_MIN, 0, k,
7182611a041SKent Overstreet 			bch2_mark_snapshot(&trans, BTREE_ID_snapshots, 0, bkey_s_c_null, k, 0) ?:
7191c59b483SKent Overstreet 			bch2_snapshot_set_equiv(&trans, k)));
72035f1a503SKent Overstreet 	if (ret)
721d4bf5eecSKent Overstreet 		bch_err(c, "error starting snapshots: %s", bch2_err_str(ret));
72214b393eeSKent Overstreet 	return ret;
72314b393eeSKent Overstreet }
72414b393eeSKent Overstreet 
72514b393eeSKent Overstreet /*
72614b393eeSKent Overstreet  * Mark a snapshot as deleted, for future cleanup:
72714b393eeSKent Overstreet  */
72814b393eeSKent Overstreet static int bch2_snapshot_node_set_deleted(struct btree_trans *trans, u32 id)
72914b393eeSKent Overstreet {
73014b393eeSKent Overstreet 	struct btree_iter iter;
73114b393eeSKent Overstreet 	struct bkey_i_snapshot *s;
73214b393eeSKent Overstreet 	int ret = 0;
73314b393eeSKent Overstreet 
73434dfa5dbSKent Overstreet 	s = bch2_bkey_get_mut_typed(trans, &iter,
73534dfa5dbSKent Overstreet 				    BTREE_ID_snapshots, POS(0, id),
73634dfa5dbSKent Overstreet 				    0, snapshot);
737994ba475SKent Overstreet 	ret = PTR_ERR_OR_ZERO(s);
738994ba475SKent Overstreet 	if (unlikely(ret)) {
7391c59b483SKent Overstreet 		bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT),
7401c59b483SKent Overstreet 					trans->c, "missing snapshot %u", id);
741f12a798aSKent Overstreet 		return ret;
74214b393eeSKent Overstreet 	}
74314b393eeSKent Overstreet 
74414b393eeSKent Overstreet 	/* already deleted? */
745994ba475SKent Overstreet 	if (BCH_SNAPSHOT_DELETED(&s->v))
74614b393eeSKent Overstreet 		goto err;
74714b393eeSKent Overstreet 
74814b393eeSKent Overstreet 	SET_BCH_SNAPSHOT_DELETED(&s->v, true);
749416cc426SKent Overstreet 	SET_BCH_SNAPSHOT_SUBVOL(&s->v, false);
750416cc426SKent Overstreet 	s->v.subvol = 0;
75114b393eeSKent Overstreet err:
75214b393eeSKent Overstreet 	bch2_trans_iter_exit(trans, &iter);
75314b393eeSKent Overstreet 	return ret;
75414b393eeSKent Overstreet }
75514b393eeSKent Overstreet 
75614b393eeSKent Overstreet static int bch2_snapshot_node_delete(struct btree_trans *trans, u32 id)
75714b393eeSKent Overstreet {
758bcb79a51SKent Overstreet 	struct bch_fs *c = trans->c;
75914b393eeSKent Overstreet 	struct btree_iter iter, p_iter = (struct btree_iter) { NULL };
7601c59b483SKent Overstreet 	struct btree_iter tree_iter = (struct btree_iter) { NULL };
76114b393eeSKent Overstreet 	struct bkey_s_c_snapshot s;
76214b393eeSKent Overstreet 	u32 parent_id;
76314b393eeSKent Overstreet 	unsigned i;
76414b393eeSKent Overstreet 	int ret = 0;
76514b393eeSKent Overstreet 
766bcb79a51SKent Overstreet 	s = bch2_bkey_get_iter_typed(trans, &iter, BTREE_ID_snapshots, POS(0, id),
767bcb79a51SKent Overstreet 				     BTREE_ITER_INTENT, snapshot);
768bcb79a51SKent Overstreet 	ret = bkey_err(s);
7691c59b483SKent Overstreet 	bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT), c,
7701c59b483SKent Overstreet 				"missing snapshot %u", id);
771bcb79a51SKent Overstreet 
77214b393eeSKent Overstreet 	if (ret)
77314b393eeSKent Overstreet 		goto err;
77414b393eeSKent Overstreet 
77514b393eeSKent Overstreet 	BUG_ON(!BCH_SNAPSHOT_DELETED(s.v));
77614b393eeSKent Overstreet 	parent_id = le32_to_cpu(s.v->parent);
77714b393eeSKent Overstreet 
77814b393eeSKent Overstreet 	if (parent_id) {
779994ba475SKent Overstreet 		struct bkey_i_snapshot *parent;
780994ba475SKent Overstreet 
78134dfa5dbSKent Overstreet 		parent = bch2_bkey_get_mut_typed(trans, &p_iter,
78234dfa5dbSKent Overstreet 				     BTREE_ID_snapshots, POS(0, parent_id),
78334dfa5dbSKent Overstreet 				     0, snapshot);
784994ba475SKent Overstreet 		ret = PTR_ERR_OR_ZERO(parent);
785994ba475SKent Overstreet 		if (unlikely(ret)) {
7861c59b483SKent Overstreet 			bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT), c,
7871c59b483SKent Overstreet 						"missing snapshot %u", parent_id);
78814b393eeSKent Overstreet 			goto err;
78914b393eeSKent Overstreet 		}
79014b393eeSKent Overstreet 
79114b393eeSKent Overstreet 		for (i = 0; i < 2; i++)
79214b393eeSKent Overstreet 			if (le32_to_cpu(parent->v.children[i]) == id)
79314b393eeSKent Overstreet 				break;
79414b393eeSKent Overstreet 
79514b393eeSKent Overstreet 		if (i == 2)
796bcb79a51SKent Overstreet 			bch_err(c, "snapshot %u missing child pointer to %u",
79714b393eeSKent Overstreet 				parent_id, id);
79814b393eeSKent Overstreet 		else
79914b393eeSKent Overstreet 			parent->v.children[i] = 0;
80014b393eeSKent Overstreet 
80114b393eeSKent Overstreet 		if (le32_to_cpu(parent->v.children[0]) <
80214b393eeSKent Overstreet 		    le32_to_cpu(parent->v.children[1]))
80314b393eeSKent Overstreet 			swap(parent->v.children[0],
80414b393eeSKent Overstreet 			     parent->v.children[1]);
8051c59b483SKent Overstreet 	} else {
8061c59b483SKent Overstreet 		/*
8071c59b483SKent Overstreet 		 * We're deleting the root of a snapshot tree: update the
8081c59b483SKent Overstreet 		 * snapshot_tree entry to point to the new root, or delete it if
8091c59b483SKent Overstreet 		 * this is the last snapshot ID in this tree:
8101c59b483SKent Overstreet 		 */
8111c59b483SKent Overstreet 		struct bkey_i_snapshot_tree *s_t;
8121c59b483SKent Overstreet 
8131c59b483SKent Overstreet 		BUG_ON(s.v->children[1]);
8141c59b483SKent Overstreet 
8151c59b483SKent Overstreet 		s_t = bch2_bkey_get_mut_typed(trans, &tree_iter,
8161c59b483SKent Overstreet 				BTREE_ID_snapshot_trees, POS(0, le32_to_cpu(s.v->tree)),
8171c59b483SKent Overstreet 				0, snapshot_tree);
8181c59b483SKent Overstreet 		ret = PTR_ERR_OR_ZERO(s_t);
8191c59b483SKent Overstreet 		if (ret)
8201c59b483SKent Overstreet 			goto err;
8211c59b483SKent Overstreet 
8221c59b483SKent Overstreet 		if (s.v->children[0]) {
8231c59b483SKent Overstreet 			s_t->v.root_snapshot = cpu_to_le32(s.v->children[0]);
8241c59b483SKent Overstreet 		} else {
8251c59b483SKent Overstreet 			s_t->k.type = KEY_TYPE_deleted;
8261c59b483SKent Overstreet 			set_bkey_val_u64s(&s_t->k, 0);
8271c59b483SKent Overstreet 		}
82814b393eeSKent Overstreet 	}
82914b393eeSKent Overstreet 
83014b393eeSKent Overstreet 	ret = bch2_btree_delete_at(trans, &iter, 0);
83114b393eeSKent Overstreet err:
8321c59b483SKent Overstreet 	bch2_trans_iter_exit(trans, &tree_iter);
83314b393eeSKent Overstreet 	bch2_trans_iter_exit(trans, &p_iter);
83414b393eeSKent Overstreet 	bch2_trans_iter_exit(trans, &iter);
83514b393eeSKent Overstreet 	return ret;
83614b393eeSKent Overstreet }
83714b393eeSKent Overstreet 
8381c59b483SKent Overstreet static int create_snapids(struct btree_trans *trans, u32 parent, u32 tree,
83914b393eeSKent Overstreet 			  u32 *new_snapids,
84014b393eeSKent Overstreet 			  u32 *snapshot_subvols,
84114b393eeSKent Overstreet 			  unsigned nr_snapids)
84214b393eeSKent Overstreet {
8431c59b483SKent Overstreet 	struct btree_iter iter;
84414b393eeSKent Overstreet 	struct bkey_i_snapshot *n;
84514b393eeSKent Overstreet 	struct bkey_s_c k;
84614b393eeSKent Overstreet 	unsigned i;
8471c59b483SKent Overstreet 	int ret;
84814b393eeSKent Overstreet 
84914b393eeSKent Overstreet 	bch2_trans_iter_init(trans, &iter, BTREE_ID_snapshots,
85014b393eeSKent Overstreet 			     POS_MIN, BTREE_ITER_INTENT);
85114b393eeSKent Overstreet 	k = bch2_btree_iter_peek(&iter);
85214b393eeSKent Overstreet 	ret = bkey_err(k);
85314b393eeSKent Overstreet 	if (ret)
85414b393eeSKent Overstreet 		goto err;
85514b393eeSKent Overstreet 
85614b393eeSKent Overstreet 	for (i = 0; i < nr_snapids; i++) {
85714b393eeSKent Overstreet 		k = bch2_btree_iter_prev_slot(&iter);
85814b393eeSKent Overstreet 		ret = bkey_err(k);
85914b393eeSKent Overstreet 		if (ret)
86014b393eeSKent Overstreet 			goto err;
86114b393eeSKent Overstreet 
86214b393eeSKent Overstreet 		if (!k.k || !k.k->p.offset) {
863098ef98dSKent Overstreet 			ret = -BCH_ERR_ENOSPC_snapshot_create;
86414b393eeSKent Overstreet 			goto err;
86514b393eeSKent Overstreet 		}
86614b393eeSKent Overstreet 
867f8cb35fdSKent Overstreet 		n = bch2_bkey_alloc(trans, &iter, 0, snapshot);
86814b393eeSKent Overstreet 		ret = PTR_ERR_OR_ZERO(n);
86914b393eeSKent Overstreet 		if (ret)
87094a3e1a6SKent Overstreet 			goto err;
87114b393eeSKent Overstreet 
87214b393eeSKent Overstreet 		n->v.flags	= 0;
87314b393eeSKent Overstreet 		n->v.parent	= cpu_to_le32(parent);
87414b393eeSKent Overstreet 		n->v.subvol	= cpu_to_le32(snapshot_subvols[i]);
8751c59b483SKent Overstreet 		n->v.tree	= cpu_to_le32(tree);
87614b393eeSKent Overstreet 		SET_BCH_SNAPSHOT_SUBVOL(&n->v, true);
87714b393eeSKent Overstreet 
878f8cb35fdSKent Overstreet 		ret = bch2_mark_snapshot(trans, BTREE_ID_snapshots, 0,
879ae1f5623SKent Overstreet 					 bkey_s_c_null, bkey_i_to_s_c(&n->k_i), 0);
88014b393eeSKent Overstreet 		if (ret)
88194a3e1a6SKent Overstreet 			goto err;
88214b393eeSKent Overstreet 
88314b393eeSKent Overstreet 		new_snapids[i]	= iter.pos.offset;
88414b393eeSKent Overstreet 	}
8851c59b483SKent Overstreet err:
8861c59b483SKent Overstreet 	bch2_trans_iter_exit(trans, &iter);
8871c59b483SKent Overstreet 	return ret;
88814b393eeSKent Overstreet }
88914b393eeSKent Overstreet 
8901c59b483SKent Overstreet /*
8911c59b483SKent Overstreet  * Create new snapshot IDs as children of an existing snapshot ID:
8921c59b483SKent Overstreet  */
8931c59b483SKent Overstreet static int bch2_snapshot_node_create_children(struct btree_trans *trans, u32 parent,
8941c59b483SKent Overstreet 			      u32 *new_snapids,
8951c59b483SKent Overstreet 			      u32 *snapshot_subvols,
8961c59b483SKent Overstreet 			      unsigned nr_snapids)
8971c59b483SKent Overstreet {
8981c59b483SKent Overstreet 	struct btree_iter iter;
8991c59b483SKent Overstreet 	struct bkey_i_snapshot *n_parent;
9001c59b483SKent Overstreet 	int ret = 0;
9011c59b483SKent Overstreet 
9021c59b483SKent Overstreet 	n_parent = bch2_bkey_get_mut_typed(trans, &iter,
9031c59b483SKent Overstreet 			BTREE_ID_snapshots, POS(0, parent),
9041c59b483SKent Overstreet 			0, snapshot);
9051c59b483SKent Overstreet 	ret = PTR_ERR_OR_ZERO(n_parent);
9061c59b483SKent Overstreet 	if (unlikely(ret)) {
9071c59b483SKent Overstreet 		if (bch2_err_matches(ret, ENOENT))
9081c59b483SKent Overstreet 			bch_err(trans->c, "snapshot %u not found", parent);
9091c59b483SKent Overstreet 		return ret;
9101c59b483SKent Overstreet 	}
9111c59b483SKent Overstreet 
9121c59b483SKent Overstreet 	if (n_parent->v.children[0] || n_parent->v.children[1]) {
91314b393eeSKent Overstreet 		bch_err(trans->c, "Trying to add child snapshot nodes to parent that already has children");
91414b393eeSKent Overstreet 		ret = -EINVAL;
91514b393eeSKent Overstreet 		goto err;
91614b393eeSKent Overstreet 	}
91714b393eeSKent Overstreet 
9181c59b483SKent Overstreet 	ret = create_snapids(trans, parent, le32_to_cpu(n_parent->v.tree),
9191c59b483SKent Overstreet 			     new_snapids, snapshot_subvols, nr_snapids);
92094a3e1a6SKent Overstreet 	if (ret)
92194a3e1a6SKent Overstreet 		goto err;
9221c59b483SKent Overstreet 
9231c59b483SKent Overstreet 	n_parent->v.children[0] = cpu_to_le32(new_snapids[0]);
9241c59b483SKent Overstreet 	n_parent->v.children[1] = cpu_to_le32(new_snapids[1]);
9251c59b483SKent Overstreet 	n_parent->v.subvol = 0;
9261c59b483SKent Overstreet 	SET_BCH_SNAPSHOT_SUBVOL(&n_parent->v, false);
92714b393eeSKent Overstreet err:
92814b393eeSKent Overstreet 	bch2_trans_iter_exit(trans, &iter);
92914b393eeSKent Overstreet 	return ret;
93014b393eeSKent Overstreet }
93114b393eeSKent Overstreet 
9321c59b483SKent Overstreet /*
9331c59b483SKent Overstreet  * Create a snapshot node that is the root of a new tree:
9341c59b483SKent Overstreet  */
9351c59b483SKent Overstreet static int bch2_snapshot_node_create_tree(struct btree_trans *trans,
9361c59b483SKent Overstreet 			      u32 *new_snapids,
9371c59b483SKent Overstreet 			      u32 *snapshot_subvols,
9381c59b483SKent Overstreet 			      unsigned nr_snapids)
9391c59b483SKent Overstreet {
9401c59b483SKent Overstreet 	struct bkey_i_snapshot_tree *n_tree;
9411c59b483SKent Overstreet 	int ret;
9421c59b483SKent Overstreet 
9431c59b483SKent Overstreet 	n_tree = __snapshot_tree_create(trans);
9441c59b483SKent Overstreet 	ret =   PTR_ERR_OR_ZERO(n_tree) ?:
9451c59b483SKent Overstreet 		create_snapids(trans, 0, n_tree->k.p.offset,
9461c59b483SKent Overstreet 			     new_snapids, snapshot_subvols, nr_snapids);
9471c59b483SKent Overstreet 	if (ret)
9481c59b483SKent Overstreet 		return ret;
9491c59b483SKent Overstreet 
9501c59b483SKent Overstreet 	n_tree->v.master_subvol	= cpu_to_le32(snapshot_subvols[0]);
9511c59b483SKent Overstreet 	n_tree->v.root_snapshot	= cpu_to_le32(new_snapids[0]);
9521c59b483SKent Overstreet 	return 0;
9531c59b483SKent Overstreet }
9541c59b483SKent Overstreet 
9551c59b483SKent Overstreet int bch2_snapshot_node_create(struct btree_trans *trans, u32 parent,
9561c59b483SKent Overstreet 			      u32 *new_snapids,
9571c59b483SKent Overstreet 			      u32 *snapshot_subvols,
9581c59b483SKent Overstreet 			      unsigned nr_snapids)
9591c59b483SKent Overstreet {
9601c59b483SKent Overstreet 	BUG_ON((parent == 0) != (nr_snapids == 1));
9611c59b483SKent Overstreet 	BUG_ON((parent != 0) != (nr_snapids == 2));
9621c59b483SKent Overstreet 
9631c59b483SKent Overstreet 	return parent
9641c59b483SKent Overstreet 		? bch2_snapshot_node_create_children(trans, parent,
9651c59b483SKent Overstreet 				new_snapids, snapshot_subvols, nr_snapids)
9661c59b483SKent Overstreet 		: bch2_snapshot_node_create_tree(trans,
9671c59b483SKent Overstreet 				new_snapids, snapshot_subvols, nr_snapids);
9681c59b483SKent Overstreet 
9691c59b483SKent Overstreet }
9701c59b483SKent Overstreet 
9716738dd19SKent Overstreet static int snapshot_delete_key(struct btree_trans *trans,
9726738dd19SKent Overstreet 			       struct btree_iter *iter,
9736738dd19SKent Overstreet 			       struct bkey_s_c k,
97491d961baSKent Overstreet 			       snapshot_id_list *deleted,
9756738dd19SKent Overstreet 			       snapshot_id_list *equiv_seen,
9766738dd19SKent Overstreet 			       struct bpos *last_pos)
97714b393eeSKent Overstreet {
97814b393eeSKent Overstreet 	struct bch_fs *c = trans->c;
97914b393eeSKent Overstreet 	u32 equiv = snapshot_t(c, k.k->p.snapshot)->equiv;
98014b393eeSKent Overstreet 
981e88a75ebSKent Overstreet 	if (!bkey_eq(k.k->p, *last_pos))
9826738dd19SKent Overstreet 		equiv_seen->nr = 0;
9836738dd19SKent Overstreet 	*last_pos = k.k->p;
98414b393eeSKent Overstreet 
98514b393eeSKent Overstreet 	if (snapshot_list_has_id(deleted, k.k->p.snapshot) ||
9866738dd19SKent Overstreet 	    snapshot_list_has_id(equiv_seen, equiv)) {
9876738dd19SKent Overstreet 		return bch2_btree_delete_at(trans, iter,
9886738dd19SKent Overstreet 					    BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE);
98914b393eeSKent Overstreet 	} else {
9906738dd19SKent Overstreet 		return snapshot_list_add(c, equiv_seen, equiv);
99114b393eeSKent Overstreet 	}
99214b393eeSKent Overstreet }
99314b393eeSKent Overstreet 
994a1783320SKent Overstreet static int bch2_delete_redundant_snapshot(struct btree_trans *trans, struct btree_iter *iter,
995a1783320SKent Overstreet 					  struct bkey_s_c k)
996a1783320SKent Overstreet {
997a1783320SKent Overstreet 	struct bkey_s_c_snapshot snap;
998a1783320SKent Overstreet 	u32 children[2];
999a1783320SKent Overstreet 	int ret;
1000a1783320SKent Overstreet 
1001a1783320SKent Overstreet 	if (k.k->type != KEY_TYPE_snapshot)
1002a1783320SKent Overstreet 		return 0;
1003a1783320SKent Overstreet 
1004a1783320SKent Overstreet 	snap = bkey_s_c_to_snapshot(k);
1005a1783320SKent Overstreet 	if (BCH_SNAPSHOT_DELETED(snap.v) ||
1006a1783320SKent Overstreet 	    BCH_SNAPSHOT_SUBVOL(snap.v))
1007a1783320SKent Overstreet 		return 0;
1008a1783320SKent Overstreet 
1009a1783320SKent Overstreet 	children[0] = le32_to_cpu(snap.v->children[0]);
1010a1783320SKent Overstreet 	children[1] = le32_to_cpu(snap.v->children[1]);
1011a1783320SKent Overstreet 
1012a1783320SKent Overstreet 	ret   = snapshot_live(trans, children[0]) ?:
1013a1783320SKent Overstreet 		snapshot_live(trans, children[1]);
1014a1783320SKent Overstreet 	if (ret < 0)
1015a1783320SKent Overstreet 		return ret;
1016a1783320SKent Overstreet 
1017a1783320SKent Overstreet 	if (!ret)
1018a1783320SKent Overstreet 		return bch2_snapshot_node_set_deleted(trans, k.k->p.offset);
1019a1783320SKent Overstreet 	return 0;
1020a1783320SKent Overstreet }
1021a1783320SKent Overstreet 
10224ab35c34SKent Overstreet int bch2_delete_dead_snapshots(struct bch_fs *c)
102314b393eeSKent Overstreet {
102414b393eeSKent Overstreet 	struct btree_trans trans;
102514b393eeSKent Overstreet 	struct btree_iter iter;
102614b393eeSKent Overstreet 	struct bkey_s_c k;
102714b393eeSKent Overstreet 	struct bkey_s_c_snapshot snap;
102891d961baSKent Overstreet 	snapshot_id_list deleted = { 0 };
1029a1783320SKent Overstreet 	u32 i, id;
103014b393eeSKent Overstreet 	int ret = 0;
103114b393eeSKent Overstreet 
10324ab35c34SKent Overstreet 	if (!test_bit(BCH_FS_HAVE_DELETED_SNAPSHOTS, &c->flags))
10334ab35c34SKent Overstreet 		return 0;
10344ab35c34SKent Overstreet 
10354ab35c34SKent Overstreet 	if (!test_bit(BCH_FS_STARTED, &c->flags)) {
10364ab35c34SKent Overstreet 		ret = bch2_fs_read_write_early(c);
10374ab35c34SKent Overstreet 		if (ret) {
1038d4bf5eecSKent Overstreet 			bch_err(c, "error deleleting dead snapshots: error going rw: %s", bch2_err_str(ret));
10394ab35c34SKent Overstreet 			return ret;
10404ab35c34SKent Overstreet 		}
10414ab35c34SKent Overstreet 	}
10424ab35c34SKent Overstreet 
104314b393eeSKent Overstreet 	bch2_trans_init(&trans, c, 0, 0);
104414b393eeSKent Overstreet 
104514b393eeSKent Overstreet 	/*
104614b393eeSKent Overstreet 	 * For every snapshot node: If we have no live children and it's not
104714b393eeSKent Overstreet 	 * pointed to by a subvolume, delete it:
104814b393eeSKent Overstreet 	 */
1049a1783320SKent Overstreet 	ret = for_each_btree_key_commit(&trans, iter, BTREE_ID_snapshots,
1050a1783320SKent Overstreet 			POS_MIN, 0, k,
1051a1783320SKent Overstreet 			NULL, NULL, 0,
1052a1783320SKent Overstreet 		bch2_delete_redundant_snapshot(&trans, &iter, k));
105314b393eeSKent Overstreet 	if (ret) {
1054d4bf5eecSKent Overstreet 		bch_err(c, "error deleting redundant snapshots: %s", bch2_err_str(ret));
105514b393eeSKent Overstreet 		goto err;
105614b393eeSKent Overstreet 	}
105714b393eeSKent Overstreet 
1058a1783320SKent Overstreet 	for_each_btree_key2(&trans, iter, BTREE_ID_snapshots,
1059a1783320SKent Overstreet 			   POS_MIN, 0, k,
1060a1783320SKent Overstreet 		bch2_snapshot_set_equiv(&trans, k));
1061a1783320SKent Overstreet 	if (ret) {
1062d4bf5eecSKent Overstreet 		bch_err(c, "error in bch2_snapshots_set_equiv: %s", bch2_err_str(ret));
106314b393eeSKent Overstreet 		goto err;
1064a1783320SKent Overstreet 	}
106514b393eeSKent Overstreet 
106614b393eeSKent Overstreet 	for_each_btree_key(&trans, iter, BTREE_ID_snapshots,
106714b393eeSKent Overstreet 			   POS_MIN, 0, k, ret) {
106814b393eeSKent Overstreet 		if (k.k->type != KEY_TYPE_snapshot)
106914b393eeSKent Overstreet 			continue;
107014b393eeSKent Overstreet 
107114b393eeSKent Overstreet 		snap = bkey_s_c_to_snapshot(k);
107214b393eeSKent Overstreet 		if (BCH_SNAPSHOT_DELETED(snap.v)) {
1073597dee1cSKent Overstreet 			ret = snapshot_list_add(c, &deleted, k.k->p.offset);
107414b393eeSKent Overstreet 			if (ret)
107514b393eeSKent Overstreet 				break;
107614b393eeSKent Overstreet 		}
107714b393eeSKent Overstreet 	}
107814b393eeSKent Overstreet 	bch2_trans_iter_exit(&trans, &iter);
107914b393eeSKent Overstreet 
108014b393eeSKent Overstreet 	if (ret) {
1081d4bf5eecSKent Overstreet 		bch_err(c, "error walking snapshots: %s", bch2_err_str(ret));
108214b393eeSKent Overstreet 		goto err;
108314b393eeSKent Overstreet 	}
108414b393eeSKent Overstreet 
108514b393eeSKent Overstreet 	for (id = 0; id < BTREE_ID_NR; id++) {
10866738dd19SKent Overstreet 		struct bpos last_pos = POS_MIN;
10876738dd19SKent Overstreet 		snapshot_id_list equiv_seen = { 0 };
10886738dd19SKent Overstreet 
108914b393eeSKent Overstreet 		if (!btree_type_has_snapshots(id))
109014b393eeSKent Overstreet 			continue;
109114b393eeSKent Overstreet 
10926738dd19SKent Overstreet 		ret = for_each_btree_key_commit(&trans, iter,
10936738dd19SKent Overstreet 				id, POS_MIN,
10946738dd19SKent Overstreet 				BTREE_ITER_PREFETCH|BTREE_ITER_ALL_SNAPSHOTS, k,
10956738dd19SKent Overstreet 				NULL, NULL, BTREE_INSERT_NOFAIL,
10966738dd19SKent Overstreet 			snapshot_delete_key(&trans, &iter, k, &deleted, &equiv_seen, &last_pos));
10976738dd19SKent Overstreet 
10986738dd19SKent Overstreet 		darray_exit(&equiv_seen);
10996738dd19SKent Overstreet 
110014b393eeSKent Overstreet 		if (ret) {
1101d4bf5eecSKent Overstreet 			bch_err(c, "error deleting snapshot keys: %s", bch2_err_str(ret));
110214b393eeSKent Overstreet 			goto err;
110314b393eeSKent Overstreet 		}
110414b393eeSKent Overstreet 	}
110514b393eeSKent Overstreet 
110614b393eeSKent Overstreet 	for (i = 0; i < deleted.nr; i++) {
1107e68914caSKent Overstreet 		ret = commit_do(&trans, NULL, NULL, 0,
110891d961baSKent Overstreet 			bch2_snapshot_node_delete(&trans, deleted.data[i]));
110914b393eeSKent Overstreet 		if (ret) {
1110d4bf5eecSKent Overstreet 			bch_err(c, "error deleting snapshot %u: %s",
1111d4bf5eecSKent Overstreet 				deleted.data[i], bch2_err_str(ret));
111214b393eeSKent Overstreet 			goto err;
111314b393eeSKent Overstreet 		}
111414b393eeSKent Overstreet 	}
11154ab35c34SKent Overstreet 
11164ab35c34SKent Overstreet 	clear_bit(BCH_FS_HAVE_DELETED_SNAPSHOTS, &c->flags);
111714b393eeSKent Overstreet err:
111891d961baSKent Overstreet 	darray_exit(&deleted);
111914b393eeSKent Overstreet 	bch2_trans_exit(&trans);
11204ab35c34SKent Overstreet 	return ret;
11214ab35c34SKent Overstreet }
11224ab35c34SKent Overstreet 
11234ab35c34SKent Overstreet static void bch2_delete_dead_snapshots_work(struct work_struct *work)
11244ab35c34SKent Overstreet {
11254ab35c34SKent Overstreet 	struct bch_fs *c = container_of(work, struct bch_fs, snapshot_delete_work);
11264ab35c34SKent Overstreet 
11274ab35c34SKent Overstreet 	bch2_delete_dead_snapshots(c);
1128d94189adSKent Overstreet 	bch2_write_ref_put(c, BCH_WRITE_REF_delete_dead_snapshots);
112914b393eeSKent Overstreet }
113014b393eeSKent Overstreet 
11314ab35c34SKent Overstreet void bch2_delete_dead_snapshots_async(struct bch_fs *c)
113214b393eeSKent Overstreet {
1133d94189adSKent Overstreet 	if (bch2_write_ref_tryget(c, BCH_WRITE_REF_delete_dead_snapshots) &&
11348bff9875SBrian Foster 	    !queue_work(c->write_ref_wq, &c->snapshot_delete_work))
1135d94189adSKent Overstreet 		bch2_write_ref_put(c, BCH_WRITE_REF_delete_dead_snapshots);
113614b393eeSKent Overstreet }
113714b393eeSKent Overstreet 
113814b393eeSKent Overstreet static int bch2_delete_dead_snapshots_hook(struct btree_trans *trans,
113914b393eeSKent Overstreet 					   struct btree_trans_commit_hook *h)
114014b393eeSKent Overstreet {
11414ab35c34SKent Overstreet 	struct bch_fs *c = trans->c;
11424ab35c34SKent Overstreet 
11434ab35c34SKent Overstreet 	set_bit(BCH_FS_HAVE_DELETED_SNAPSHOTS, &c->flags);
11444ab35c34SKent Overstreet 
11454ab35c34SKent Overstreet 	if (!test_bit(BCH_FS_FSCK_DONE, &c->flags))
11464ab35c34SKent Overstreet 		return 0;
11474ab35c34SKent Overstreet 
11484ab35c34SKent Overstreet 	bch2_delete_dead_snapshots_async(c);
114914b393eeSKent Overstreet 	return 0;
115014b393eeSKent Overstreet }
115114b393eeSKent Overstreet 
115214b393eeSKent Overstreet /* Subvolumes: */
115314b393eeSKent Overstreet 
1154f0ac7df2SKent Overstreet int bch2_subvolume_invalid(const struct bch_fs *c, struct bkey_s_c k,
1155facafdcbSKent Overstreet 			   unsigned flags, struct printbuf *err)
115614b393eeSKent Overstreet {
1157e88a75ebSKent Overstreet 	if (bkey_lt(k.k->p, SUBVOL_POS_MIN) ||
1158e88a75ebSKent Overstreet 	    bkey_gt(k.k->p, SUBVOL_POS_MAX)) {
1159401ec4dbSKent Overstreet 		prt_printf(err, "invalid pos");
116078c0b75cSKent Overstreet 		return -BCH_ERR_invalid_bkey;
1161f0ac7df2SKent Overstreet 	}
116214b393eeSKent Overstreet 
1163f0ac7df2SKent Overstreet 	return 0;
116414b393eeSKent Overstreet }
116514b393eeSKent Overstreet 
116614b393eeSKent Overstreet void bch2_subvolume_to_text(struct printbuf *out, struct bch_fs *c,
116714b393eeSKent Overstreet 			    struct bkey_s_c k)
116814b393eeSKent Overstreet {
116914b393eeSKent Overstreet 	struct bkey_s_c_subvolume s = bkey_s_c_to_subvolume(k);
117014b393eeSKent Overstreet 
1171401ec4dbSKent Overstreet 	prt_printf(out, "root %llu snapshot id %u",
117214b393eeSKent Overstreet 		   le64_to_cpu(s.v->inode),
117314b393eeSKent Overstreet 		   le32_to_cpu(s.v->snapshot));
1174653693beSKent Overstreet 
1175653693beSKent Overstreet 	if (bkey_val_bytes(s.k) > offsetof(struct bch_subvolume, parent))
1176653693beSKent Overstreet 		prt_printf(out, " parent %u", le32_to_cpu(s.v->parent));
117714b393eeSKent Overstreet }
117814b393eeSKent Overstreet 
117998638ffaSKent Overstreet static __always_inline int
118098638ffaSKent Overstreet bch2_subvolume_get_inlined(struct btree_trans *trans, unsigned subvol,
118197996ddfSKent Overstreet 			   bool inconsistent_if_not_found,
118297996ddfSKent Overstreet 			   int iter_flags,
118397996ddfSKent Overstreet 			   struct bch_subvolume *s)
118414b393eeSKent Overstreet {
1185bcb79a51SKent Overstreet 	int ret = bch2_bkey_get_val_typed(trans, BTREE_ID_subvolumes, POS(0, subvol),
1186bcb79a51SKent Overstreet 					  iter_flags, subvolume, s);
11871c59b483SKent Overstreet 	bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT) &&
11881c59b483SKent Overstreet 				inconsistent_if_not_found,
1189bcb79a51SKent Overstreet 				trans->c, "missing subvolume %u", subvol);
119097996ddfSKent Overstreet 	return ret;
119114b393eeSKent Overstreet }
119214b393eeSKent Overstreet 
119398638ffaSKent Overstreet int bch2_subvolume_get(struct btree_trans *trans, unsigned subvol,
119498638ffaSKent Overstreet 		       bool inconsistent_if_not_found,
119598638ffaSKent Overstreet 		       int iter_flags,
119698638ffaSKent Overstreet 		       struct bch_subvolume *s)
119798638ffaSKent Overstreet {
119898638ffaSKent Overstreet 	return bch2_subvolume_get_inlined(trans, subvol, inconsistent_if_not_found, iter_flags, s);
119998638ffaSKent Overstreet }
120098638ffaSKent Overstreet 
12019ca4853bSKent Overstreet int bch2_snapshot_get_subvol(struct btree_trans *trans, u32 snapshot,
12029ca4853bSKent Overstreet 			     struct bch_subvolume *subvol)
12039ca4853bSKent Overstreet {
12049ca4853bSKent Overstreet 	struct bch_snapshot snap;
12059ca4853bSKent Overstreet 
12069ca4853bSKent Overstreet 	return  snapshot_lookup(trans, snapshot, &snap) ?:
12079ca4853bSKent Overstreet 		bch2_subvolume_get(trans, le32_to_cpu(snap.subvol), true, 0, subvol);
12089ca4853bSKent Overstreet }
12099ca4853bSKent Overstreet 
121097996ddfSKent Overstreet int bch2_subvolume_get_snapshot(struct btree_trans *trans, u32 subvol,
121197996ddfSKent Overstreet 				u32 *snapid)
121297996ddfSKent Overstreet {
1213653693beSKent Overstreet 	struct btree_iter iter;
1214653693beSKent Overstreet 	struct bkey_s_c k;
121597996ddfSKent Overstreet 	int ret;
121697996ddfSKent Overstreet 
1217653693beSKent Overstreet 	k = bch2_bkey_get_iter(trans, &iter, BTREE_ID_subvolumes, POS(0, subvol),
121897996ddfSKent Overstreet 			       BTREE_ITER_CACHED|
1219653693beSKent Overstreet 			       BTREE_ITER_WITH_UPDATES);
1220653693beSKent Overstreet 	ret = bkey_err(k) ?: k.k->type == KEY_TYPE_subvolume ? 0 : -ENOENT;
1221653693beSKent Overstreet 
1222653693beSKent Overstreet 	if (likely(!ret))
1223653693beSKent Overstreet 		*snapid = le32_to_cpu(bkey_s_c_to_subvolume(k).v->snapshot);
1224653693beSKent Overstreet 	else if (bch2_err_matches(ret, ENOENT))
1225653693beSKent Overstreet 		bch2_fs_inconsistent(trans->c, "missing subvolume %u", subvol);
1226653693beSKent Overstreet 	bch2_trans_iter_exit(trans, &iter);
122714b393eeSKent Overstreet 	return ret;
122814b393eeSKent Overstreet }
122914b393eeSKent Overstreet 
1230653693beSKent Overstreet static int bch2_subvolume_reparent(struct btree_trans *trans,
1231653693beSKent Overstreet 				   struct btree_iter *iter,
1232653693beSKent Overstreet 				   struct bkey_s_c k,
1233653693beSKent Overstreet 				   u32 old_parent, u32 new_parent)
1234653693beSKent Overstreet {
1235653693beSKent Overstreet 	struct bkey_i_subvolume *s;
1236653693beSKent Overstreet 	int ret;
1237653693beSKent Overstreet 
1238653693beSKent Overstreet 	if (k.k->type != KEY_TYPE_subvolume)
1239653693beSKent Overstreet 		return 0;
1240653693beSKent Overstreet 
1241653693beSKent Overstreet 	if (bkey_val_bytes(k.k) > offsetof(struct bch_subvolume, parent) &&
1242653693beSKent Overstreet 	    le32_to_cpu(bkey_s_c_to_subvolume(k).v->parent) != old_parent)
1243653693beSKent Overstreet 		return 0;
1244653693beSKent Overstreet 
1245653693beSKent Overstreet 	s = bch2_bkey_make_mut_typed(trans, iter, k, 0, subvolume);
1246653693beSKent Overstreet 	ret = PTR_ERR_OR_ZERO(s);
1247653693beSKent Overstreet 	if (ret)
1248653693beSKent Overstreet 		return ret;
1249653693beSKent Overstreet 
1250653693beSKent Overstreet 	s->v.parent = cpu_to_le32(new_parent);
1251653693beSKent Overstreet 	return 0;
1252653693beSKent Overstreet }
1253653693beSKent Overstreet 
1254653693beSKent Overstreet /*
1255653693beSKent Overstreet  * Scan for subvolumes with parent @subvolid_to_delete, reparent:
1256653693beSKent Overstreet  */
1257653693beSKent Overstreet static int bch2_subvolumes_reparent(struct btree_trans *trans, u32 subvolid_to_delete)
1258653693beSKent Overstreet {
1259653693beSKent Overstreet 	struct btree_iter iter;
1260653693beSKent Overstreet 	struct bkey_s_c k;
1261653693beSKent Overstreet 	struct bch_subvolume s;
1262653693beSKent Overstreet 
1263653693beSKent Overstreet 	return lockrestart_do(trans,
1264653693beSKent Overstreet 			bch2_subvolume_get(trans, subvolid_to_delete, true,
1265653693beSKent Overstreet 				   BTREE_ITER_CACHED, &s)) ?:
1266653693beSKent Overstreet 		for_each_btree_key_commit(trans, iter,
1267653693beSKent Overstreet 				BTREE_ID_subvolumes, POS_MIN, BTREE_ITER_PREFETCH, k,
1268653693beSKent Overstreet 				NULL, NULL, BTREE_INSERT_NOFAIL,
1269653693beSKent Overstreet 			bch2_subvolume_reparent(trans, &iter, k,
1270653693beSKent Overstreet 					subvolid_to_delete, le32_to_cpu(s.parent)));
1271653693beSKent Overstreet }
1272653693beSKent Overstreet 
12732027875bSKent Overstreet /*
12742027875bSKent Overstreet  * Delete subvolume, mark snapshot ID as deleted, queue up snapshot
12752027875bSKent Overstreet  * deletion/cleanup:
12762027875bSKent Overstreet  */
1277653693beSKent Overstreet static int __bch2_subvolume_delete(struct btree_trans *trans, u32 subvolid)
127814b393eeSKent Overstreet {
127914b393eeSKent Overstreet 	struct btree_iter iter;
128014b393eeSKent Overstreet 	struct bkey_s_c_subvolume subvol;
128114b393eeSKent Overstreet 	struct btree_trans_commit_hook *h;
128214b393eeSKent Overstreet 	u32 snapid;
128314b393eeSKent Overstreet 	int ret = 0;
128414b393eeSKent Overstreet 
1285bcb79a51SKent Overstreet 	subvol = bch2_bkey_get_iter_typed(trans, &iter,
1286bcb79a51SKent Overstreet 				BTREE_ID_subvolumes, POS(0, subvolid),
1287bcb79a51SKent Overstreet 				BTREE_ITER_CACHED|BTREE_ITER_INTENT,
1288bcb79a51SKent Overstreet 				subvolume);
1289bcb79a51SKent Overstreet 	ret = bkey_err(subvol);
12901c59b483SKent Overstreet 	bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT), trans->c,
12911c59b483SKent Overstreet 				"missing subvolume %u", subvolid);
129214b393eeSKent Overstreet 	if (ret)
1293bcb79a51SKent Overstreet 		return ret;
129414b393eeSKent Overstreet 
129514b393eeSKent Overstreet 	snapid = le32_to_cpu(subvol.v->snapshot);
129614b393eeSKent Overstreet 
1297416cc426SKent Overstreet 	ret = bch2_btree_delete_at(trans, &iter, 0);
129814b393eeSKent Overstreet 	if (ret)
129914b393eeSKent Overstreet 		goto err;
130014b393eeSKent Overstreet 
130114b393eeSKent Overstreet 	ret = bch2_snapshot_node_set_deleted(trans, snapid);
130231301dd4SKent Overstreet 	if (ret)
130331301dd4SKent Overstreet 		goto err;
130414b393eeSKent Overstreet 
130514b393eeSKent Overstreet 	h = bch2_trans_kmalloc(trans, sizeof(*h));
130614b393eeSKent Overstreet 	ret = PTR_ERR_OR_ZERO(h);
130714b393eeSKent Overstreet 	if (ret)
130814b393eeSKent Overstreet 		goto err;
130914b393eeSKent Overstreet 
131014b393eeSKent Overstreet 	h->fn = bch2_delete_dead_snapshots_hook;
131114b393eeSKent Overstreet 	bch2_trans_commit_hook(trans, h);
131214b393eeSKent Overstreet err:
131314b393eeSKent Overstreet 	bch2_trans_iter_exit(trans, &iter);
131414b393eeSKent Overstreet 	return ret;
131514b393eeSKent Overstreet }
131614b393eeSKent Overstreet 
1317653693beSKent Overstreet static int bch2_subvolume_delete(struct btree_trans *trans, u32 subvolid)
1318653693beSKent Overstreet {
1319653693beSKent Overstreet 	return bch2_subvolumes_reparent(trans, subvolid) ?:
1320653693beSKent Overstreet 		commit_do(trans, NULL, NULL, BTREE_INSERT_NOFAIL,
1321653693beSKent Overstreet 			  __bch2_subvolume_delete(trans, subvolid));
1322653693beSKent Overstreet }
1323653693beSKent Overstreet 
13242027875bSKent Overstreet void bch2_subvolume_wait_for_pagecache_and_delete(struct work_struct *work)
13252027875bSKent Overstreet {
13262027875bSKent Overstreet 	struct bch_fs *c = container_of(work, struct bch_fs,
13272027875bSKent Overstreet 				snapshot_wait_for_pagecache_and_delete_work);
132891d961baSKent Overstreet 	snapshot_id_list s;
13292027875bSKent Overstreet 	u32 *id;
13302027875bSKent Overstreet 	int ret = 0;
13312027875bSKent Overstreet 
13322027875bSKent Overstreet 	while (!ret) {
13332027875bSKent Overstreet 		mutex_lock(&c->snapshots_unlinked_lock);
13342027875bSKent Overstreet 		s = c->snapshots_unlinked;
133591d961baSKent Overstreet 		darray_init(&c->snapshots_unlinked);
13362027875bSKent Overstreet 		mutex_unlock(&c->snapshots_unlinked_lock);
13372027875bSKent Overstreet 
13382027875bSKent Overstreet 		if (!s.nr)
13392027875bSKent Overstreet 			break;
13402027875bSKent Overstreet 
13412027875bSKent Overstreet 		bch2_evict_subvolume_inodes(c, &s);
13422027875bSKent Overstreet 
134391d961baSKent Overstreet 		for (id = s.data; id < s.data + s.nr; id++) {
1344653693beSKent Overstreet 			ret = bch2_trans_run(c, bch2_subvolume_delete(&trans, *id));
13452027875bSKent Overstreet 			if (ret) {
1346d4bf5eecSKent Overstreet 				bch_err(c, "error deleting subvolume %u: %s", *id, bch2_err_str(ret));
13472027875bSKent Overstreet 				break;
13482027875bSKent Overstreet 			}
13492027875bSKent Overstreet 		}
13502027875bSKent Overstreet 
135191d961baSKent Overstreet 		darray_exit(&s);
13522027875bSKent Overstreet 	}
13532027875bSKent Overstreet 
1354d94189adSKent Overstreet 	bch2_write_ref_put(c, BCH_WRITE_REF_snapshot_delete_pagecache);
13552027875bSKent Overstreet }
13562027875bSKent Overstreet 
13572027875bSKent Overstreet struct subvolume_unlink_hook {
13582027875bSKent Overstreet 	struct btree_trans_commit_hook	h;
13592027875bSKent Overstreet 	u32				subvol;
13602027875bSKent Overstreet };
13612027875bSKent Overstreet 
13622027875bSKent Overstreet int bch2_subvolume_wait_for_pagecache_and_delete_hook(struct btree_trans *trans,
13632027875bSKent Overstreet 						      struct btree_trans_commit_hook *_h)
13642027875bSKent Overstreet {
13652027875bSKent Overstreet 	struct subvolume_unlink_hook *h = container_of(_h, struct subvolume_unlink_hook, h);
13662027875bSKent Overstreet 	struct bch_fs *c = trans->c;
13672027875bSKent Overstreet 	int ret = 0;
13682027875bSKent Overstreet 
13692027875bSKent Overstreet 	mutex_lock(&c->snapshots_unlinked_lock);
13702027875bSKent Overstreet 	if (!snapshot_list_has_id(&c->snapshots_unlinked, h->subvol))
1371597dee1cSKent Overstreet 		ret = snapshot_list_add(c, &c->snapshots_unlinked, h->subvol);
13722027875bSKent Overstreet 	mutex_unlock(&c->snapshots_unlinked_lock);
13732027875bSKent Overstreet 
13742027875bSKent Overstreet 	if (ret)
13752027875bSKent Overstreet 		return ret;
13762027875bSKent Overstreet 
1377d94189adSKent Overstreet 	if (!bch2_write_ref_tryget(c, BCH_WRITE_REF_snapshot_delete_pagecache))
13782027875bSKent Overstreet 		return -EROFS;
13792027875bSKent Overstreet 
13808bff9875SBrian Foster 	if (!queue_work(c->write_ref_wq, &c->snapshot_wait_for_pagecache_and_delete_work))
1381d94189adSKent Overstreet 		bch2_write_ref_put(c, BCH_WRITE_REF_snapshot_delete_pagecache);
13822027875bSKent Overstreet 	return 0;
13832027875bSKent Overstreet }
13842027875bSKent Overstreet 
13852027875bSKent Overstreet int bch2_subvolume_unlink(struct btree_trans *trans, u32 subvolid)
13862027875bSKent Overstreet {
13872027875bSKent Overstreet 	struct btree_iter iter;
13882027875bSKent Overstreet 	struct bkey_i_subvolume *n;
13892027875bSKent Overstreet 	struct subvolume_unlink_hook *h;
13902027875bSKent Overstreet 	int ret = 0;
13912027875bSKent Overstreet 
1392f12a798aSKent Overstreet 	h = bch2_trans_kmalloc(trans, sizeof(*h));
1393f12a798aSKent Overstreet 	ret = PTR_ERR_OR_ZERO(h);
1394f12a798aSKent Overstreet 	if (ret)
1395f12a798aSKent Overstreet 		return ret;
1396f12a798aSKent Overstreet 
1397f12a798aSKent Overstreet 	h->h.fn		= bch2_subvolume_wait_for_pagecache_and_delete_hook;
1398f12a798aSKent Overstreet 	h->subvol	= subvolid;
1399f12a798aSKent Overstreet 	bch2_trans_commit_hook(trans, &h->h);
1400f12a798aSKent Overstreet 
140134dfa5dbSKent Overstreet 	n = bch2_bkey_get_mut_typed(trans, &iter,
140234dfa5dbSKent Overstreet 			BTREE_ID_subvolumes, POS(0, subvolid),
140334dfa5dbSKent Overstreet 			BTREE_ITER_CACHED, subvolume);
1404994ba475SKent Overstreet 	ret = PTR_ERR_OR_ZERO(n);
1405994ba475SKent Overstreet 	if (unlikely(ret)) {
14061c59b483SKent Overstreet 		bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT), trans->c,
14071c59b483SKent Overstreet 					"missing subvolume %u", subvolid);
1408f12a798aSKent Overstreet 		return ret;
14092027875bSKent Overstreet 	}
14102027875bSKent Overstreet 
14112027875bSKent Overstreet 	SET_BCH_SUBVOLUME_UNLINKED(&n->v, true);
14122027875bSKent Overstreet 	bch2_trans_iter_exit(trans, &iter);
14132027875bSKent Overstreet 	return ret;
14142027875bSKent Overstreet }
14152027875bSKent Overstreet 
141614b393eeSKent Overstreet int bch2_subvolume_create(struct btree_trans *trans, u64 inode,
141714b393eeSKent Overstreet 			  u32 src_subvolid,
141814b393eeSKent Overstreet 			  u32 *new_subvolid,
141914b393eeSKent Overstreet 			  u32 *new_snapshotid,
142014b393eeSKent Overstreet 			  bool ro)
142114b393eeSKent Overstreet {
1422653693beSKent Overstreet 	struct bch_fs *c = trans->c;
142314b393eeSKent Overstreet 	struct btree_iter dst_iter, src_iter = (struct btree_iter) { NULL };
142414b393eeSKent Overstreet 	struct bkey_i_subvolume *new_subvol = NULL;
142514b393eeSKent Overstreet 	struct bkey_i_subvolume *src_subvol = NULL;
142614b393eeSKent Overstreet 	u32 parent = 0, new_nodes[2], snapshot_subvols[2];
142714b393eeSKent Overstreet 	int ret = 0;
142814b393eeSKent Overstreet 
142951e84d3bSKent Overstreet 	ret = bch2_bkey_get_empty_slot(trans, &dst_iter,
143051e84d3bSKent Overstreet 				BTREE_ID_subvolumes, POS(0, U32_MAX));
143151e84d3bSKent Overstreet 	if (ret == -BCH_ERR_ENOSPC_btree_slot)
1432098ef98dSKent Overstreet 		ret = -BCH_ERR_ENOSPC_subvolume_create;
143351e84d3bSKent Overstreet 	if (ret)
143451e84d3bSKent Overstreet 		return ret;
143551e84d3bSKent Overstreet 
143614b393eeSKent Overstreet 	snapshot_subvols[0] = dst_iter.pos.offset;
143714b393eeSKent Overstreet 	snapshot_subvols[1] = src_subvolid;
143814b393eeSKent Overstreet 
143914b393eeSKent Overstreet 	if (src_subvolid) {
144014b393eeSKent Overstreet 		/* Creating a snapshot: */
144114b393eeSKent Overstreet 
144234dfa5dbSKent Overstreet 		src_subvol = bch2_bkey_get_mut_typed(trans, &src_iter,
144334dfa5dbSKent Overstreet 				BTREE_ID_subvolumes, POS(0, src_subvolid),
144434dfa5dbSKent Overstreet 				BTREE_ITER_CACHED, subvolume);
1445994ba475SKent Overstreet 		ret = PTR_ERR_OR_ZERO(src_subvol);
1446994ba475SKent Overstreet 		if (unlikely(ret)) {
1447653693beSKent Overstreet 			bch2_fs_inconsistent_on(ret == -ENOENT, c,
1448994ba475SKent Overstreet 						"subvolume %u not found", src_subvolid);
144914b393eeSKent Overstreet 			goto err;
145014b393eeSKent Overstreet 		}
145114b393eeSKent Overstreet 
145214b393eeSKent Overstreet 		parent = le32_to_cpu(src_subvol->v.snapshot);
145314b393eeSKent Overstreet 	}
145414b393eeSKent Overstreet 
145514b393eeSKent Overstreet 	ret = bch2_snapshot_node_create(trans, parent, new_nodes,
145614b393eeSKent Overstreet 					snapshot_subvols,
145714b393eeSKent Overstreet 					src_subvolid ? 2 : 1);
145814b393eeSKent Overstreet 	if (ret)
145914b393eeSKent Overstreet 		goto err;
146014b393eeSKent Overstreet 
146114b393eeSKent Overstreet 	if (src_subvolid) {
146214b393eeSKent Overstreet 		src_subvol->v.snapshot = cpu_to_le32(new_nodes[1]);
146394a3e1a6SKent Overstreet 		ret = bch2_trans_update(trans, &src_iter, &src_subvol->k_i, 0);
146494a3e1a6SKent Overstreet 		if (ret)
146594a3e1a6SKent Overstreet 			goto err;
146614b393eeSKent Overstreet 	}
146714b393eeSKent Overstreet 
1468f8cb35fdSKent Overstreet 	new_subvol = bch2_bkey_alloc(trans, &dst_iter, 0, subvolume);
146914b393eeSKent Overstreet 	ret = PTR_ERR_OR_ZERO(new_subvol);
147014b393eeSKent Overstreet 	if (ret)
147114b393eeSKent Overstreet 		goto err;
147214b393eeSKent Overstreet 
147314b393eeSKent Overstreet 	new_subvol->v.flags	= 0;
147414b393eeSKent Overstreet 	new_subvol->v.snapshot	= cpu_to_le32(new_nodes[0]);
147514b393eeSKent Overstreet 	new_subvol->v.inode	= cpu_to_le64(inode);
1476653693beSKent Overstreet 	new_subvol->v.parent	= cpu_to_le32(src_subvolid);
1477653693beSKent Overstreet 	new_subvol->v.otime.lo	= cpu_to_le64(bch2_current_time(c));
1478653693beSKent Overstreet 	new_subvol->v.otime.hi	= 0;
1479653693beSKent Overstreet 
148014b393eeSKent Overstreet 	SET_BCH_SUBVOLUME_RO(&new_subvol->v, ro);
148114b393eeSKent Overstreet 	SET_BCH_SUBVOLUME_SNAP(&new_subvol->v, src_subvolid != 0);
148214b393eeSKent Overstreet 
148314b393eeSKent Overstreet 	*new_subvolid	= new_subvol->k.p.offset;
148414b393eeSKent Overstreet 	*new_snapshotid	= new_nodes[0];
148514b393eeSKent Overstreet err:
148614b393eeSKent Overstreet 	bch2_trans_iter_exit(trans, &src_iter);
148714b393eeSKent Overstreet 	bch2_trans_iter_exit(trans, &dst_iter);
148814b393eeSKent Overstreet 	return ret;
148914b393eeSKent Overstreet }
149014b393eeSKent Overstreet 
149114b393eeSKent Overstreet int bch2_fs_subvolumes_init(struct bch_fs *c)
149214b393eeSKent Overstreet {
149314b393eeSKent Overstreet 	INIT_WORK(&c->snapshot_delete_work, bch2_delete_dead_snapshots_work);
14942027875bSKent Overstreet 	INIT_WORK(&c->snapshot_wait_for_pagecache_and_delete_work,
14952027875bSKent Overstreet 		  bch2_subvolume_wait_for_pagecache_and_delete);
14962027875bSKent Overstreet 	mutex_init(&c->snapshots_unlinked_lock);
149714b393eeSKent Overstreet 	return 0;
149814b393eeSKent Overstreet }
1499