]> www.infradead.org Git - nvme.git/commitdiff
bcachefs: Improve check_snapshot_exists()
authorKent Overstreet <kent.overstreet@linux.dev>
Thu, 10 Oct 2024 01:28:11 +0000 (21:28 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sat, 12 Oct 2024 09:02:48 +0000 (05:02 -0400)
Check if we have snapshot_trees or subvolumes that refer to the snapshot
node being reconstructed, and use them.

With this, the kill_btree_root test that blows away the snapshots btree
now passes, and we're able to successfully reconstruct.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/snapshot.c

index 9f4d13faf7aaa44eb4ac3943e3acd54e9f842d81..ae57638506c3aaafb24c92f21c764a2d21ddcbe7 100644 (file)
@@ -905,12 +905,30 @@ static int check_snapshot_exists(struct btree_trans *trans, u32 id)
        if (bch2_snapshot_equiv(c, id))
                return 0;
 
-       /* 0 is an invalid tree ID */
+       /* Do we need to reconstruct the snapshot_tree entry as well? */
+       struct btree_iter iter;
+       struct bkey_s_c k;
+       int ret = 0;
        u32 tree_id = 0;
-       int ret = bch2_snapshot_tree_create(trans, id, 0, &tree_id);
+
+       for_each_btree_key_norestart(trans, iter, BTREE_ID_snapshot_trees, POS_MIN,
+                                    0, k, ret) {
+               if (le32_to_cpu(bkey_s_c_to_snapshot_tree(k).v->root_snapshot) == id) {
+                       tree_id = k.k->p.offset;
+                       break;
+               }
+       }
+       bch2_trans_iter_exit(trans, &iter);
+
        if (ret)
                return ret;
 
+       if (!tree_id) {
+               ret = bch2_snapshot_tree_create(trans, id, 0, &tree_id);
+               if (ret)
+                       return ret;
+       }
+
        struct bkey_i_snapshot *snapshot = bch2_trans_kmalloc(trans, sizeof(*snapshot));
        ret = PTR_ERR_OR_ZERO(snapshot);
        if (ret)
@@ -921,6 +939,16 @@ static int check_snapshot_exists(struct btree_trans *trans, u32 id)
        snapshot->v.tree        = cpu_to_le32(tree_id);
        snapshot->v.btime.lo    = cpu_to_le64(bch2_current_time(c));
 
+       for_each_btree_key_norestart(trans, iter, BTREE_ID_subvolumes, POS_MIN,
+                                    0, k, ret) {
+               if (le32_to_cpu(bkey_s_c_to_subvolume(k).v->snapshot) == id) {
+                       snapshot->v.subvol = cpu_to_le32(k.k->p.offset);
+                       SET_BCH_SNAPSHOT_SUBVOL(&snapshot->v, true);
+                       break;
+               }
+       }
+       bch2_trans_iter_exit(trans, &iter);
+
        return  bch2_btree_insert_trans(trans, BTREE_ID_snapshots, &snapshot->k_i, 0) ?:
                bch2_mark_snapshot(trans, BTREE_ID_snapshots, 0,
                                   bkey_s_c_null, bkey_i_to_s(&snapshot->k_i), 0) ?: