]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - libbcachefs/btree_iter.c
Update bcachefs sources to 386f00b639 bcachefs: Snapshot creation, deletion
[bcachefs-tools-debian] / libbcachefs / btree_iter.c
index ce4d7c7e6f9b655dff015aa3093653579264965e..b5484d7702a49277de8f607153cc3f9633481f74 100644 (file)
@@ -13,6 +13,7 @@
 #include "extents.h"
 #include "journal.h"
 #include "replicas.h"
+#include "subvolume.h"
 
 #include <linux/prefetch.h>
 #include <trace/events/bcachefs.h>
@@ -152,7 +153,7 @@ bool __bch2_btree_node_relock(struct btree_trans *trans,
        if (six_relock_type(&b->c.lock, want, path->l[level].lock_seq) ||
            (btree_node_lock_seq_matches(path, b, level) &&
             btree_node_lock_increment(trans, b, level, want))) {
-               mark_btree_node_locked(trans, path, level, want);
+               mark_btree_node_locked(path, level, want);
                return true;
        } else {
                return false;
@@ -188,7 +189,7 @@ static bool bch2_btree_node_upgrade(struct btree_trans *trans,
 
        return false;
 success:
-       mark_btree_node_intent_locked(trans, path, level);
+       mark_btree_node_intent_locked(path, level);
        return true;
 }
 
@@ -674,6 +675,9 @@ static void bch2_btree_iter_verify(struct btree_iter *iter)
 
 static void bch2_btree_iter_verify_entry_exit(struct btree_iter *iter)
 {
+       BUG_ON((iter->flags & BTREE_ITER_FILTER_SNAPSHOTS) &&
+              !iter->pos.snapshot);
+
        BUG_ON(!(iter->flags & BTREE_ITER_ALL_SNAPSHOTS) &&
               iter->pos.snapshot != iter->snapshot);
 
@@ -681,6 +685,55 @@ static void bch2_btree_iter_verify_entry_exit(struct btree_iter *iter)
               bkey_cmp(iter->pos, iter->k.p) > 0);
 }
 
+static int bch2_btree_iter_verify_ret(struct btree_iter *iter, struct bkey_s_c k)
+{
+       struct btree_trans *trans = iter->trans;
+       struct btree_iter copy;
+       struct bkey_s_c prev;
+       int ret = 0;
+
+       if (!bch2_debug_check_iterators)
+               return 0;
+
+       if (!(iter->flags & BTREE_ITER_FILTER_SNAPSHOTS))
+               return 0;
+
+       if (bkey_err(k) || !k.k)
+               return 0;
+
+       BUG_ON(!bch2_snapshot_is_ancestor(trans->c,
+                                         iter->snapshot,
+                                         k.k->p.snapshot));
+
+       bch2_trans_iter_init(trans, &copy, iter->btree_id, iter->pos,
+                            BTREE_ITER_ALL_SNAPSHOTS);
+       prev = bch2_btree_iter_prev(&copy);
+       if (!prev.k)
+               goto out;
+
+       ret = bkey_err(prev);
+       if (ret)
+               goto out;
+
+       if (!bkey_cmp(prev.k->p, k.k->p) &&
+           bch2_snapshot_is_ancestor(trans->c, iter->snapshot,
+                                     prev.k->p.snapshot) > 0) {
+               char buf1[100], buf2[200];
+
+               bch2_bkey_to_text(&PBUF(buf1), k.k);
+               bch2_bkey_to_text(&PBUF(buf2), prev.k);
+
+               panic("iter snap %u\n"
+                     "k    %s\n"
+                     "prev %s\n",
+                     iter->snapshot,
+                     buf1, buf2);
+       }
+out:
+       bch2_trans_iter_exit(trans, &copy);
+       return ret;
+}
+
 #else
 
 static inline void bch2_btree_path_verify_level(struct btree_trans *trans,
@@ -689,6 +742,7 @@ static inline void bch2_btree_path_verify(struct btree_trans *trans,
                                          struct btree_path *path) {}
 static inline void bch2_btree_iter_verify(struct btree_iter *iter) {}
 static inline void bch2_btree_iter_verify_entry_exit(struct btree_iter *iter) {}
+static inline int bch2_btree_iter_verify_ret(struct btree_iter *iter, struct bkey_s_c k) { return 0; }
 
 #endif
 
@@ -896,12 +950,12 @@ static inline struct bkey_s_c btree_path_level_peek_all(struct bch_fs *c,
                        bch2_btree_node_iter_peek_all(&l->iter, l->b));
 }
 
-static inline struct bkey_s_c btree_path_level_peek(struct btree_trans *trans,
+static inline struct bkey_s_c btree_path_level_peek(struct bch_fs *c,
                                                    struct btree_path *path,
                                                    struct btree_path_level *l,
                                                    struct bkey *u)
 {
-       struct bkey_s_c k = __btree_iter_unpack(trans->c, l, u,
+       struct bkey_s_c k = __btree_iter_unpack(c, l, u,
                        bch2_btree_node_iter_peek(&l->iter, l->b));
 
        path->pos = k.k ? k.k->p : l->b->key.k.p;
@@ -1041,7 +1095,7 @@ void bch2_trans_node_add(struct btree_trans *trans, struct btree *b)
                            t != BTREE_NODE_UNLOCKED) {
                                btree_node_unlock(path, b->c.level);
                                six_lock_increment(&b->c.lock, t);
-                               mark_btree_node_locked(trans, path, b->c.level, t);
+                               mark_btree_node_locked(path, b->c.level, t);
                        }
 
                        btree_path_level_init(trans, path, b);
@@ -1118,7 +1172,7 @@ static inline int btree_path_lock_root(struct btree_trans *trans,
                        for (i = path->level + 1; i < BTREE_MAX_DEPTH; i++)
                                path->l[i].b = NULL;
 
-                       mark_btree_node_locked(trans, path, path->level, lock_type);
+                       mark_btree_node_locked(path, path->level, lock_type);
                        btree_path_level_init(trans, path, b);
                        return 0;
                }
@@ -1210,7 +1264,7 @@ static __always_inline int btree_path_down(struct btree_trans *trans,
        if (unlikely(ret))
                goto err;
 
-       mark_btree_node_locked(trans, path, level, lock_type);
+       mark_btree_node_locked(path, level, lock_type);
        btree_path_level_init(trans, path, b);
 
        if (tmp.k->k.type == KEY_TYPE_btree_ptr_v2 &&
@@ -1252,10 +1306,6 @@ retry_all:
 
        btree_trans_verify_sorted(trans);
 
-#ifdef CONFIG_BCACHEFS_DEBUG
-       trans->traverse_all_idx = U8_MAX;
-#endif
-
        for (i = trans->nr_sorted - 2; i >= 0; --i) {
                struct btree_path *path1 = trans->paths + trans->sorted[i];
                struct btree_path *path2 = trans->paths + trans->sorted[i + 1];
@@ -1294,9 +1344,6 @@ retry_all:
                path = trans->paths + trans->sorted[i];
 
                EBUG_ON(!(trans->paths_allocated & (1ULL << path->idx)));
-#ifdef CONFIG_BCACHEFS_DEBUG
-               trans->traverse_all_idx = path->idx;
-#endif
 
                ret = btree_path_traverse_one(trans, path, 0, _THIS_IP_);
                if (ret)
@@ -1985,11 +2032,25 @@ struct bkey_s_c bch2_btree_iter_peek(struct btree_iter *iter)
                }
 
                if (likely(k.k)) {
-                       if (likely(!bkey_deleted(k.k)))
-                               break;
+                       /*
+                        * We can never have a key in a leaf node at POS_MAX, so
+                        * we don't have to check these successor() calls:
+                        */
+                       if ((iter->flags & BTREE_ITER_FILTER_SNAPSHOTS) &&
+                           !bch2_snapshot_is_ancestor(trans->c,
+                                                      iter->snapshot,
+                                                      k.k->p.snapshot)) {
+                               search_key = bpos_successor(k.k->p);
+                               continue;
+                       }
+
+                       if (bkey_whiteout(k.k) &&
+                           !(iter->flags & BTREE_ITER_ALL_SNAPSHOTS)) {
+                               search_key = bkey_successor(iter, k.k->p);
+                               continue;
+                       }
 
-                       /* Advance to next key: */
-                       search_key = bkey_successor(iter, k.k->p);
+                       break;
                } else if (likely(bpos_cmp(iter->path->l[0].b->key.k.p, SPOS_MAX))) {
                        /* Advance to next leaf node: */
                        search_key = bpos_successor(iter->path->l[0].b->key.k.p);
@@ -2010,6 +2071,9 @@ struct bkey_s_c bch2_btree_iter_peek(struct btree_iter *iter)
        else if (bkey_cmp(bkey_start_pos(k.k), iter->pos) > 0)
                iter->pos = bkey_start_pos(k.k);
 
+       if (iter->flags & BTREE_ITER_FILTER_SNAPSHOTS)
+               iter->pos.snapshot = iter->snapshot;
+
        cmp = bpos_cmp(k.k->p, iter->path->pos);
        if (cmp) {
                iter->path = bch2_btree_path_make_mut(trans, iter->path,
@@ -2022,6 +2086,10 @@ out:
 
        bch2_btree_iter_verify_entry_exit(iter);
        bch2_btree_iter_verify(iter);
+       ret = bch2_btree_iter_verify_ret(iter, k);
+       if (unlikely(ret))
+               return bkey_s_c_err(ret);
+
        return k;
 }
 
@@ -2045,7 +2113,10 @@ struct bkey_s_c bch2_btree_iter_peek_prev(struct btree_iter *iter)
 {
        struct btree_trans *trans = iter->trans;
        struct bpos search_key = iter->pos;
+       struct btree_path *saved_path = NULL;
        struct bkey_s_c k;
+       struct bkey saved_k;
+       const struct bch_val *saved_v;
        int ret;
 
        EBUG_ON(iter->path->cached || iter->path->level);
@@ -2053,6 +2124,9 @@ struct bkey_s_c bch2_btree_iter_peek_prev(struct btree_iter *iter)
        bch2_btree_iter_verify(iter);
        bch2_btree_iter_verify_entry_exit(iter);
 
+       if (iter->flags & BTREE_ITER_FILTER_SNAPSHOTS)
+               search_key.snapshot = U32_MAX;
+
        while (1) {
                iter->path = btree_path_set_pos(trans, iter->path, search_key,
                                                iter->flags & BTREE_ITER_INTENT);
@@ -2065,18 +2139,61 @@ struct bkey_s_c bch2_btree_iter_peek_prev(struct btree_iter *iter)
                        goto out;
                }
 
-               k = btree_path_level_peek(trans, iter->path,
+               k = btree_path_level_peek(trans->c, iter->path,
                                          &iter->path->l[0], &iter->k);
                if (!k.k ||
                    ((iter->flags & BTREE_ITER_IS_EXTENTS)
-                    ? bkey_cmp(bkey_start_pos(k.k), iter->pos) >= 0
-                    : bkey_cmp(k.k->p, iter->pos) > 0))
+                    ? bpos_cmp(bkey_start_pos(k.k), search_key) >= 0
+                    : bpos_cmp(k.k->p, search_key) > 0))
                        k = btree_path_level_prev(trans->c, iter->path,
                                                  &iter->path->l[0], &iter->k);
 
                btree_path_check_sort(trans, iter->path, 0);
 
                if (likely(k.k)) {
+                       if (iter->flags & BTREE_ITER_FILTER_SNAPSHOTS) {
+                               if (k.k->p.snapshot == iter->snapshot)
+                                       goto got_key;
+
+                               /*
+                                * If we have a saved candidate, and we're no
+                                * longer at the same _key_ (not pos), return
+                                * that candidate
+                                */
+                               if (saved_path && bkey_cmp(k.k->p, saved_k.p)) {
+                                       bch2_path_put(trans, iter->path,
+                                                     iter->flags & BTREE_ITER_INTENT);
+                                       iter->path = saved_path;
+                                       saved_path = NULL;
+                                       iter->k = saved_k;
+                                       k.v     = saved_v;
+                                       goto got_key;
+                               }
+
+                               if (bch2_snapshot_is_ancestor(iter->trans->c,
+                                                             iter->snapshot,
+                                                             k.k->p.snapshot)) {
+                                       if (saved_path)
+                                               bch2_path_put(trans, saved_path,
+                                                     iter->flags & BTREE_ITER_INTENT);
+                                       saved_path = btree_path_clone(trans, iter->path,
+                                                               iter->flags & BTREE_ITER_INTENT);
+                                       saved_k = *k.k;
+                                       saved_v = k.v;
+                               }
+
+                               search_key = bpos_predecessor(k.k->p);
+                               continue;
+                       }
+got_key:
+                       if (bkey_whiteout(k.k) &&
+                           !(iter->flags & BTREE_ITER_ALL_SNAPSHOTS)) {
+                               search_key = bkey_predecessor(iter, k.k->p);
+                               if (iter->flags & BTREE_ITER_FILTER_SNAPSHOTS)
+                                       search_key.snapshot = U32_MAX;
+                               continue;
+                       }
+
                        break;
                } else if (likely(bpos_cmp(iter->path->l[0].b->data->min_key, POS_MIN))) {
                        /* Advance to previous leaf node: */
@@ -2094,7 +2211,12 @@ struct bkey_s_c bch2_btree_iter_peek_prev(struct btree_iter *iter)
        /* Extents can straddle iter->pos: */
        if (bkey_cmp(k.k->p, iter->pos) < 0)
                iter->pos = k.k->p;
+
+       if (iter->flags & BTREE_ITER_FILTER_SNAPSHOTS)
+               iter->pos.snapshot = iter->snapshot;
 out:
+       if (saved_path)
+               bch2_path_put(trans, saved_path, iter->flags & BTREE_ITER_INTENT);
        iter->path->should_be_locked = true;
 
        bch2_btree_iter_verify_entry_exit(iter);
@@ -2143,7 +2265,8 @@ struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_iter *iter)
        if (unlikely(ret))
                return bkey_s_c_err(ret);
 
-       if (!(iter->flags & BTREE_ITER_IS_EXTENTS)) {
+       if ((iter->flags & BTREE_ITER_CACHED) ||
+           !(iter->flags & (BTREE_ITER_IS_EXTENTS|BTREE_ITER_FILTER_SNAPSHOTS))) {
                struct bkey_i *next_update;
 
                next_update = iter->flags & BTREE_ITER_WITH_UPDATES
@@ -2202,6 +2325,9 @@ struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_iter *iter)
 
        bch2_btree_iter_verify_entry_exit(iter);
        bch2_btree_iter_verify(iter);
+       ret = bch2_btree_iter_verify_ret(iter, k);
+       if (unlikely(ret))
+               return bkey_s_c_err(ret);
 
        return k;
 }
@@ -2352,13 +2478,13 @@ static void __bch2_trans_iter_init(struct btree_trans *trans,
            btree_node_type_is_extents(btree_id))
                flags |= BTREE_ITER_IS_EXTENTS;
 
-       if (!btree_type_has_snapshots(btree_id) &&
-           !(flags & __BTREE_ITER_ALL_SNAPSHOTS))
+       if (!(flags & __BTREE_ITER_ALL_SNAPSHOTS) &&
+           !btree_type_has_snapshots(btree_id))
                flags &= ~BTREE_ITER_ALL_SNAPSHOTS;
 
-       if (!(flags & BTREE_ITER_ALL_SNAPSHOTS))
-               pos.snapshot = btree_type_has_snapshots(btree_id)
-                       ? U32_MAX : 0;
+       if (!(flags & BTREE_ITER_ALL_SNAPSHOTS) &&
+           btree_type_has_snapshots(btree_id))
+               flags |= BTREE_ITER_FILTER_SNAPSHOTS;
 
        iter->trans     = trans;
        iter->path      = NULL;