fixup bcachefs: New on disk format: Backpointers
authorKent Overstreet <kent.overstreet@linux.dev>
Sun, 12 Feb 2023 19:25:59 +0000 (14:25 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:51 +0000 (17:09 -0400)
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/backpointers.c

index 3978c0b50f2049c65ec257f56bf09ebf519d906d..3e862da6f15fde0fe46dc1313c65cb00b9c80546 100644 (file)
@@ -5,6 +5,7 @@
 #include "backpointers.h"
 #include "btree_cache.h"
 #include "btree_update.h"
+#include "btree_write_buffer.h"
 #include "error.h"
 
 #include <linux/mm.h>
@@ -553,7 +554,8 @@ static int check_bp_exists(struct btree_trans *trans,
                           struct bch_backpointer bp,
                           struct bkey_s_c orig_k,
                           struct bpos bucket_start,
-                          struct bpos bucket_end)
+                          struct bpos bucket_end,
+                          struct bpos *last_flushed_pos)
 {
        struct bch_fs *c = trans->c;
        struct btree_iter alloc_iter, bp_iter = { NULL };
@@ -597,8 +599,15 @@ static int check_bp_exists(struct btree_trans *trans,
                goto err;
 
        if (bp_k.k->type != KEY_TYPE_backpointer ||
-           memcmp(bkey_s_c_to_backpointer(bp_k).v, &bp, sizeof(bp)))
+           memcmp(bkey_s_c_to_backpointer(bp_k).v, &bp, sizeof(bp))) {
+               if (!bpos_eq(*last_flushed_pos, orig_k.k->p)) {
+                       *last_flushed_pos = orig_k.k->p;
+                       ret = bch2_btree_write_buffer_flush_sync(trans) ?:
+                               -BCH_ERR_transaction_restart_write_buffer_flush;
+                       goto out;
+               }
                goto missing;
+       }
 out:
 err:
 fsck_err:
@@ -607,6 +616,7 @@ fsck_err:
        printbuf_exit(&buf);
        return ret;
 missing:
+
        prt_printf(&buf, "missing backpointer for btree=%s l=%u ",
               bch2_btree_ids[bp.btree_id], bp.level);
        bch2_bkey_val_to_text(&buf, c, orig_k);
@@ -628,7 +638,8 @@ missing:
 static int check_extent_to_backpointers(struct btree_trans *trans,
                                        struct btree_iter *iter,
                                        struct bpos bucket_start,
-                                       struct bpos bucket_end)
+                                       struct bpos bucket_end,
+                                       struct bpos *last_flushed_pos)
 {
        struct bch_fs *c = trans->c;
        struct bkey_ptrs_c ptrs;
@@ -655,7 +666,9 @@ static int check_extent_to_backpointers(struct btree_trans *trans,
                bch2_extent_ptr_to_bp(c, iter->btree_id, iter->path->level,
                                      k, p, &bucket_pos, &bp);
 
-               ret = check_bp_exists(trans, bucket_pos, bp, k, bucket_start, bucket_end);
+               ret = check_bp_exists(trans, bucket_pos, bp, k,
+                                     bucket_start, bucket_end,
+                                     last_flushed_pos);
                if (ret)
                        return ret;
        }
@@ -666,7 +679,8 @@ static int check_extent_to_backpointers(struct btree_trans *trans,
 static int check_btree_root_to_backpointers(struct btree_trans *trans,
                                            enum btree_id btree_id,
                                            struct bpos bucket_start,
-                                           struct bpos bucket_end)
+                                           struct bpos bucket_end,
+                                           struct bpos *last_flushed_pos)
 {
        struct bch_fs *c = trans->c;
        struct btree_iter iter;
@@ -698,7 +712,9 @@ static int check_btree_root_to_backpointers(struct btree_trans *trans,
                bch2_extent_ptr_to_bp(c, iter.btree_id, iter.path->level + 1,
                                      k, p, &bucket_pos, &bp);
 
-               ret = check_bp_exists(trans, bucket_pos, bp, k, bucket_start, bucket_end);
+               ret = check_bp_exists(trans, bucket_pos, bp, k,
+                                     bucket_start, bucket_end,
+                                     last_flushed_pos);
                if (ret)
                        goto err;
        }
@@ -778,6 +794,7 @@ static int bch2_check_extents_to_backpointers_pass(struct btree_trans *trans,
 {
        struct btree_iter iter;
        enum btree_id btree_id;
+       struct bpos last_flushed_pos = SPOS_MAX;
        int ret = 0;
 
        for (btree_id = 0; btree_id < BTREE_ID_NR; btree_id++) {
@@ -793,7 +810,8 @@ static int bch2_check_extents_to_backpointers_pass(struct btree_trans *trans,
                                        BTREE_INSERT_LAZY_RW|
                                        BTREE_INSERT_NOFAIL,
                                        check_extent_to_backpointers(trans, &iter,
-                                                               bucket_start, bucket_end));
+                                                               bucket_start, bucket_end,
+                                                               &last_flushed_pos));
                        if (ret)
                                break;
                } while (!bch2_btree_iter_advance(&iter));
@@ -807,7 +825,8 @@ static int bch2_check_extents_to_backpointers_pass(struct btree_trans *trans,
                                BTREE_INSERT_LAZY_RW|
                                BTREE_INSERT_NOFAIL,
                                check_btree_root_to_backpointers(trans, btree_id,
-                                                       bucket_start, bucket_end));
+                                                       bucket_start, bucket_end,
+                                                       &last_flushed_pos));
                if (ret)
                        break;
        }