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 11*653693beSKent Overstreet static int bch2_subvolume_delete(struct btree_trans *, u32); 12*653693beSKent 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 371c59b483SKent Overstreet static int 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; 4291c59b483SKent Overstreet int ret = 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 4651c59b483SKent Overstreet ret = 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)) { 648*653693beSKent Overstreet bch2_fs_lazy_rw(c); 649*653693beSKent Overstreet 6504ab35c34SKent Overstreet ret = bch2_subvolume_delete(trans, iter->pos.offset); 651*653693beSKent Overstreet if (ret) 6521c59b483SKent Overstreet bch_err(c, "error deleting subvolume %llu: %s", 653d4bf5eecSKent Overstreet iter->pos.offset, bch2_err_str(ret)); 654*653693beSKent 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 6621c59b483SKent Overstreet ret = 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)); 1174*653693beSKent Overstreet 1175*653693beSKent Overstreet if (bkey_val_bytes(s.k) > offsetof(struct bch_subvolume, parent)) 1176*653693beSKent 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 { 1213*653693beSKent Overstreet struct btree_iter iter; 1214*653693beSKent Overstreet struct bkey_s_c k; 121597996ddfSKent Overstreet int ret; 121697996ddfSKent Overstreet 1217*653693beSKent Overstreet k = bch2_bkey_get_iter(trans, &iter, BTREE_ID_subvolumes, POS(0, subvol), 121897996ddfSKent Overstreet BTREE_ITER_CACHED| 1219*653693beSKent Overstreet BTREE_ITER_WITH_UPDATES); 1220*653693beSKent Overstreet ret = bkey_err(k) ?: k.k->type == KEY_TYPE_subvolume ? 0 : -ENOENT; 1221*653693beSKent Overstreet 1222*653693beSKent Overstreet if (likely(!ret)) 1223*653693beSKent Overstreet *snapid = le32_to_cpu(bkey_s_c_to_subvolume(k).v->snapshot); 1224*653693beSKent Overstreet else if (bch2_err_matches(ret, ENOENT)) 1225*653693beSKent Overstreet bch2_fs_inconsistent(trans->c, "missing subvolume %u", subvol); 1226*653693beSKent Overstreet bch2_trans_iter_exit(trans, &iter); 122714b393eeSKent Overstreet return ret; 122814b393eeSKent Overstreet } 122914b393eeSKent Overstreet 1230*653693beSKent Overstreet static int bch2_subvolume_reparent(struct btree_trans *trans, 1231*653693beSKent Overstreet struct btree_iter *iter, 1232*653693beSKent Overstreet struct bkey_s_c k, 1233*653693beSKent Overstreet u32 old_parent, u32 new_parent) 1234*653693beSKent Overstreet { 1235*653693beSKent Overstreet struct bkey_i_subvolume *s; 1236*653693beSKent Overstreet int ret; 1237*653693beSKent Overstreet 1238*653693beSKent Overstreet if (k.k->type != KEY_TYPE_subvolume) 1239*653693beSKent Overstreet return 0; 1240*653693beSKent Overstreet 1241*653693beSKent Overstreet if (bkey_val_bytes(k.k) > offsetof(struct bch_subvolume, parent) && 1242*653693beSKent Overstreet le32_to_cpu(bkey_s_c_to_subvolume(k).v->parent) != old_parent) 1243*653693beSKent Overstreet return 0; 1244*653693beSKent Overstreet 1245*653693beSKent Overstreet s = bch2_bkey_make_mut_typed(trans, iter, k, 0, subvolume); 1246*653693beSKent Overstreet ret = PTR_ERR_OR_ZERO(s); 1247*653693beSKent Overstreet if (ret) 1248*653693beSKent Overstreet return ret; 1249*653693beSKent Overstreet 1250*653693beSKent Overstreet s->v.parent = cpu_to_le32(new_parent); 1251*653693beSKent Overstreet return 0; 1252*653693beSKent Overstreet } 1253*653693beSKent Overstreet 1254*653693beSKent Overstreet /* 1255*653693beSKent Overstreet * Scan for subvolumes with parent @subvolid_to_delete, reparent: 1256*653693beSKent Overstreet */ 1257*653693beSKent Overstreet static int bch2_subvolumes_reparent(struct btree_trans *trans, u32 subvolid_to_delete) 1258*653693beSKent Overstreet { 1259*653693beSKent Overstreet struct btree_iter iter; 1260*653693beSKent Overstreet struct bkey_s_c k; 1261*653693beSKent Overstreet struct bch_subvolume s; 1262*653693beSKent Overstreet 1263*653693beSKent Overstreet return lockrestart_do(trans, 1264*653693beSKent Overstreet bch2_subvolume_get(trans, subvolid_to_delete, true, 1265*653693beSKent Overstreet BTREE_ITER_CACHED, &s)) ?: 1266*653693beSKent Overstreet for_each_btree_key_commit(trans, iter, 1267*653693beSKent Overstreet BTREE_ID_subvolumes, POS_MIN, BTREE_ITER_PREFETCH, k, 1268*653693beSKent Overstreet NULL, NULL, BTREE_INSERT_NOFAIL, 1269*653693beSKent Overstreet bch2_subvolume_reparent(trans, &iter, k, 1270*653693beSKent Overstreet subvolid_to_delete, le32_to_cpu(s.parent))); 1271*653693beSKent Overstreet } 1272*653693beSKent Overstreet 12732027875bSKent Overstreet /* 12742027875bSKent Overstreet * Delete subvolume, mark snapshot ID as deleted, queue up snapshot 12752027875bSKent Overstreet * deletion/cleanup: 12762027875bSKent Overstreet */ 1277*653693beSKent 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 1317*653693beSKent Overstreet static int bch2_subvolume_delete(struct btree_trans *trans, u32 subvolid) 1318*653693beSKent Overstreet { 1319*653693beSKent Overstreet return bch2_subvolumes_reparent(trans, subvolid) ?: 1320*653693beSKent Overstreet commit_do(trans, NULL, NULL, BTREE_INSERT_NOFAIL, 1321*653693beSKent Overstreet __bch2_subvolume_delete(trans, subvolid)); 1322*653693beSKent Overstreet } 1323*653693beSKent 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++) { 1344*653693beSKent 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 { 1422*653693beSKent 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)) { 1447*653693beSKent 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); 1476*653693beSKent Overstreet new_subvol->v.parent = cpu_to_le32(src_subvolid); 1477*653693beSKent Overstreet new_subvol->v.otime.lo = cpu_to_le64(bch2_current_time(c)); 1478*653693beSKent Overstreet new_subvol->v.otime.hi = 0; 1479*653693beSKent 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