Don't scan keys in inodes for which the snapshot tree doesn't match any
we're deleting from.

Signed-off-by: Kent Overstreet <[email protected]>
---
 fs/bcachefs/snapshot.c       | 35 +++++++++++++++++++++++++++++++++--
 fs/bcachefs/snapshot_types.h |  1 +
 2 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/fs/bcachefs/snapshot.c b/fs/bcachefs/snapshot.c
index 2f2f129ce482..219cba038778 100644
--- a/fs/bcachefs/snapshot.c
+++ b/fs/bcachefs/snapshot.c
@@ -1432,6 +1432,24 @@ static int delete_dead_snapshots_process_key(struct 
btree_trans *trans,
        return 0;
 }
 
+static bool skip_unrelated_snapshot_tree(struct btree_trans *trans, struct 
btree_iter *iter)
+{
+       struct bch_fs *c = trans->c;
+       struct snapshot_delete *d = &c->snapshot_delete;
+
+       bool ret = !snapshot_list_has_id(&d->deleting_from_trees,
+                                        bch2_snapshot_tree(c, 
iter->pos.snapshot));
+       if (unlikely(ret)) {
+               struct bpos pos = iter->pos;
+               pos.snapshot = 0;
+               if (iter->btree_id != BTREE_ID_inodes)
+                       pos.offset = U64_MAX;
+               bch2_btree_iter_set_pos(trans, iter, 
bpos_nosnap_successor(pos));
+       }
+
+       return ret;
+}
+
 /*
  * For a given snapshot, if it doesn't have a subvolume that points to it, and
  * it doesn't have child snapshot nodes - it's now redundant and we can mark it
@@ -1457,8 +1475,11 @@ static int check_should_delete_snapshot(struct 
btree_trans *trans, struct bkey_s
                        !snapshot_list_has_id(&d->delete_leaves, child);
        }
 
+       u32 tree = bch2_snapshot_tree(c, s.k->p.offset);
+
        if (live_children == 0) {
-               return snapshot_list_add(c, &d->delete_leaves, s.k->p.offset);
+               return  snapshot_list_add_nodup(c, &d->deleting_from_trees, 
tree) ?:
+                       snapshot_list_add(c, &d->delete_leaves, s.k->p.offset);
        } else if (live_children == 1) {
                struct snapshot_interior_delete n = {
                        .id             = s.k->p.offset,
@@ -1470,7 +1491,8 @@ static int check_should_delete_snapshot(struct 
btree_trans *trans, struct bkey_s
                        return -EINVAL;
                }
 
-               return darray_push(&d->delete_interior, n);
+               return  snapshot_list_add_nodup(c, &d->deleting_from_trees, 
tree) ?:
+                       darray_push(&d->delete_interior, n);
        } else {
                return 0;
        }
@@ -1551,6 +1573,10 @@ static int bch2_fix_child_of_deleted_snapshot(struct 
btree_trans *trans,
 
 static void bch2_snapshot_delete_nodes_to_text(struct printbuf *out, struct 
snapshot_delete *d)
 {
+       prt_printf(out, "deleting from trees");
+       darray_for_each(d->deleting_from_trees, i)
+               prt_printf(out, " %u", *i);
+
        prt_printf(out, "deleting leaves");
        darray_for_each(d->delete_leaves, i)
                prt_printf(out, " %u", *i);
@@ -1611,6 +1637,10 @@ int bch2_delete_dead_snapshots(struct bch_fs *c)
                                BTREE_ITER_prefetch|BTREE_ITER_all_snapshots, k,
                                &res, NULL, BCH_TRANS_COMMIT_no_enospc, ({
                        d->pos.pos = iter.pos;
+
+                       if (skip_unrelated_snapshot_tree(trans, &iter))
+                               continue;
+
                        delete_dead_snapshots_process_key(trans, &iter, k);
                }));
 
@@ -1653,6 +1683,7 @@ int bch2_delete_dead_snapshots(struct bch_fs *c)
        }
 err:
        mutex_lock(&d->lock);
+       darray_exit(&d->deleting_from_trees);
        darray_exit(&d->delete_interior);
        darray_exit(&d->delete_leaves);
        d->running = false;
diff --git a/fs/bcachefs/snapshot_types.h b/fs/bcachefs/snapshot_types.h
index bb67a6beb6e3..39fb47f43183 100644
--- a/fs/bcachefs/snapshot_types.h
+++ b/fs/bcachefs/snapshot_types.h
@@ -15,6 +15,7 @@ struct snapshot_delete {
        struct work_struct      work;
 
        struct mutex            lock;
+       snapshot_id_list        deleting_from_trees;
        snapshot_id_list        delete_leaves;
        interior_delete_list    delete_interior;
 
-- 
2.49.0


Reply via email to