bcachefs: Simplify, fix bch2_backpointer_get_key()
authorKent Overstreet <kent.overstreet@linux.dev>
Sun, 5 Nov 2023 00:22:56 +0000 (20:22 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 5 Nov 2023 18:14:22 +0000 (13:14 -0500)
 - backpointer_not_found() checks backpointers_no_use_write_buffer, no
   need to do it inbackpointer_get_key().

 - always use backpointer_get_node() for pointers to nodes:
   backpointer_get_key() was sometimes returning the key from the root
   node unlocked.

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

index 2cf93ad..ef02c9b 100644 (file)
@@ -5,6 +5,7 @@
 #include "backpointers.h"
 #include "btree_cache.h"
 #include "btree_update.h"
+#include "btree_update_interior.h"
 #include "btree_write_buffer.h"
 #include "error.h"
 
@@ -226,6 +227,11 @@ static void backpointer_not_found(struct btree_trans *trans,
        struct printbuf buf = PRINTBUF;
        struct bpos bucket = bp_pos_to_bucket(c, bp_pos);
 
+       /*
+        * If we're using the btree write buffer, the backpointer we were
+        * looking at may have already been deleted - failure to find what it
+        * pointed to is not an error:
+        */
        if (likely(!bch2_backpointers_no_use_write_buffer))
                return;
 
@@ -256,56 +262,37 @@ struct bkey_s_c bch2_backpointer_get_key(struct btree_trans *trans,
                                         struct bch_backpointer bp,
                                         unsigned iter_flags)
 {
-       struct bch_fs *c = trans->c;
-       struct btree_root *r = bch2_btree_id_root(c, bp.btree_id);
-       struct bpos bucket = bp_pos_to_bucket(c, bp_pos);
-       struct bkey_s_c k;
-
-       bch2_trans_node_iter_init(trans, iter,
-                                 bp.btree_id,
-                                 bp.pos,
-                                 0,
-                                 min(bp.level, r->level),
-                                 iter_flags);
-       k = bch2_btree_iter_peek_slot(iter);
-       if (bkey_err(k)) {
-               bch2_trans_iter_exit(trans, iter);
-               return k;
-       }
-
-       if (bp.level == r->level + 1)
-               k = bkey_i_to_s_c(&r->key);
-
-       if (k.k && extent_matches_bp(c, bp.btree_id, bp.level, k, bucket, bp))
-               return k;
-
-       bch2_trans_iter_exit(trans, iter);
+       if (likely(!bp.level)) {
+               struct bch_fs *c = trans->c;
+               struct bpos bucket = bp_pos_to_bucket(c, bp_pos);
+               struct bkey_s_c k;
+
+               bch2_trans_node_iter_init(trans, iter,
+                                         bp.btree_id,
+                                         bp.pos,
+                                         0, 0,
+                                         iter_flags);
+               k = bch2_btree_iter_peek_slot(iter);
+               if (bkey_err(k)) {
+                       bch2_trans_iter_exit(trans, iter);
+                       return k;
+               }
 
-       if (unlikely(bch2_backpointers_no_use_write_buffer)) {
-               if (bp.level) {
-                       struct btree *b;
+               if (k.k && extent_matches_bp(c, bp.btree_id, bp.level, k, bucket, bp))
+                       return k;
 
-                       /*
-                        * If a backpointer for a btree node wasn't found, it may be
-                        * because it was overwritten by a new btree node that hasn't
-                        * been written out yet - backpointer_get_node() checks for
-                        * this:
-                        */
-                       b = bch2_backpointer_get_node(trans, iter, bp_pos, bp);
-                       if (!IS_ERR_OR_NULL(b))
-                               return bkey_i_to_s_c(&b->key);
+               bch2_trans_iter_exit(trans, iter);
+               backpointer_not_found(trans, bp_pos, bp, k);
+               return bkey_s_c_null;
+       } else {
+               struct btree *b = bch2_backpointer_get_node(trans, iter, bp_pos, bp);
 
+               if (IS_ERR_OR_NULL(b)) {
                        bch2_trans_iter_exit(trans, iter);
-
-                       if (IS_ERR(b))
-                               return bkey_s_c_err(PTR_ERR(b));
-                       return bkey_s_c_null;
+                       return IS_ERR(b) ? bkey_s_c_err(PTR_ERR(b)) : bkey_s_c_null;
                }
-
-               backpointer_not_found(trans, bp_pos, bp, k);
+               return bkey_i_to_s_c(&b->key);
        }
-
-       return bkey_s_c_null;
 }
 
 struct btree *bch2_backpointer_get_node(struct btree_trans *trans,
@@ -329,6 +316,8 @@ struct btree *bch2_backpointer_get_node(struct btree_trans *trans,
        if (IS_ERR(b))
                goto err;
 
+       BUG_ON(b->c.level != bp.level - 1);
+
        if (b && extent_matches_bp(c, bp.btree_id, bp.level,
                                   bkey_i_to_s_c(&b->key),
                                   bucket, bp))