summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2022-10-24 11:24:22 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2022-10-25 00:22:24 -0400
commitcf6c9fae912e78f65c564a06613f8601ffbe3596 (patch)
treefe508463917b2ab93fc2cc5dd3714c2eefe42d24
parent18dd24526abd2e14cc4228805520aad41ec339a7 (diff)
bcachefs: Fix for allocating before backpointers have been checked
Before the backpointers phase of fsck completes - which runs while we're RW - we could have free buckets (dirty_sectors = 0) with backpointers in them - invalid backpointers that will be removed later. We don't want to allocate from these buckets, we'll get "overlapping backpointer" errors. This patch fixes this issue by explicitly checking if there's any backpointers in the candidate bucket if backpointers haven't been checked yet. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r--fs/bcachefs/alloc_foreground.c24
-rw-r--r--fs/bcachefs/btree_update_interior.c3
-rw-r--r--fs/bcachefs/recovery.c3
-rw-r--r--include/trace/events/bcachefs.h12
4 files changed, 37 insertions, 5 deletions
diff --git a/fs/bcachefs/alloc_foreground.c b/fs/bcachefs/alloc_foreground.c
index a9e0c7397292..58368b04f257 100644
--- a/fs/bcachefs/alloc_foreground.c
+++ b/fs/bcachefs/alloc_foreground.c
@@ -14,6 +14,7 @@
#include "bcachefs.h"
#include "alloc_background.h"
#include "alloc_foreground.h"
+#include "backpointers.h"
#include "btree_iter.h"
#include "btree_update.h"
#include "btree_gc.h"
@@ -333,6 +334,29 @@ static struct open_bucket *try_alloc_bucket(struct btree_trans *trans, struct bc
goto err;
}
+ if (!test_bit(BCH_FS_CHECK_BACKPOINTERS_DONE, &c->flags)) {
+ struct bch_backpointer bp;
+ u64 bp_offset = 0;
+
+ ret = bch2_get_next_backpointer(trans, POS(ca->dev_idx, b), -1,
+ &bp_offset, &bp,
+ BTREE_ITER_NOPRESERVE);
+ if (ret) {
+ ob = ERR_PTR(ret);
+ goto err;
+ }
+
+ if (bp_offset != U64_MAX) {
+ /*
+ * Bucket may have data in it - we don't call
+ * bc2h_trans_inconnsistent() because fsck hasn't
+ * finished yet
+ */
+ ob = NULL;
+ goto err;
+ }
+ }
+
ob = __try_alloc_bucket(c, ca, b, reserve, &a,
skipped_open,
skipped_need_journal_commit,
diff --git a/fs/bcachefs/btree_update_interior.c b/fs/bcachefs/btree_update_interior.c
index 5ce91ae6a69e..39298f0246b4 100644
--- a/fs/bcachefs/btree_update_interior.c
+++ b/fs/bcachefs/btree_update_interior.c
@@ -1178,7 +1178,8 @@ bch2_btree_update_start(struct btree_trans *trans, struct btree_path *path,
}
if (ret) {
- trace_and_count(c, btree_reserve_get_fail, trans->fn, _RET_IP_, nr_nodes[0] + nr_nodes[1]);
+ trace_and_count(c, btree_reserve_get_fail, trans->fn,
+ _RET_IP_, nr_nodes[0] + nr_nodes[1], ret);
goto err;
}
diff --git a/fs/bcachefs/recovery.c b/fs/bcachefs/recovery.c
index 6968f934594f..2bb078749b9a 100644
--- a/fs/bcachefs/recovery.c
+++ b/fs/bcachefs/recovery.c
@@ -1486,6 +1486,9 @@ int bch2_fs_initialize(struct bch_fs *c)
mutex_unlock(&c->sb_lock);
set_bit(BCH_FS_INITIAL_GC_DONE, &c->flags);
+ set_bit(BCH_FS_CHECK_LRUS_DONE, &c->flags);
+ set_bit(BCH_FS_CHECK_BACKPOINTERS_DONE, &c->flags);
+ set_bit(BCH_FS_CHECK_ALLOC_TO_LRU_REFS_DONE, &c->flags);
set_bit(BCH_FS_MAY_GO_RW, &c->flags);
set_bit(BCH_FS_FSCK_DONE, &c->flags);
diff --git a/include/trace/events/bcachefs.h b/include/trace/events/bcachefs.h
index 444f43f0474d..6bc361ae7d7a 100644
--- a/include/trace/events/bcachefs.h
+++ b/include/trace/events/bcachefs.h
@@ -344,25 +344,29 @@ DEFINE_EVENT(btree_node, btree_node_free,
TRACE_EVENT(btree_reserve_get_fail,
TP_PROTO(const char *trans_fn,
unsigned long caller_ip,
- size_t required),
- TP_ARGS(trans_fn, caller_ip, required),
+ size_t required,
+ int ret),
+ TP_ARGS(trans_fn, caller_ip, required, ret),
TP_STRUCT__entry(
__array(char, trans_fn, 32 )
__field(unsigned long, caller_ip )
__field(size_t, required )
+ __array(char, ret, 32 )
),
TP_fast_assign(
strscpy(__entry->trans_fn, trans_fn, sizeof(__entry->trans_fn));
__entry->caller_ip = caller_ip;
__entry->required = required;
+ strscpy(__entry->ret, bch2_err_str(ret), sizeof(__entry->ret));
),
- TP_printk("%s %pS required %zu",
+ TP_printk("%s %pS required %zu ret %s",
__entry->trans_fn,
(void *) __entry->caller_ip,
- __entry->required)
+ __entry->required,
+ __entry->ret)
);
DEFINE_EVENT(btree_node, btree_node_compact,