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