summaryrefslogtreecommitdiffstats
path: root/fs/bcachefs/lru.c
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2022-02-17 03:11:39 -0500
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:09:29 -0400
commit5add07d56a5e714a6ac1bedffa9b999d2966708c (patch)
tree7d4c7598720b8606a887f55431b0fd1f41a351bf /fs/bcachefs/lru.c
parentcaece7fe3f1199f0da42b4537434166f99f0c11f (diff)
downloadlinux-5add07d56a5e714a6ac1bedffa9b999d2966708c.tar.gz
linux-5add07d56a5e714a6ac1bedffa9b999d2966708c.tar.bz2
linux-5add07d56a5e714a6ac1bedffa9b999d2966708c.zip
bcachefs: Fsck for need_discard & freespace btrees
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs/lru.c')
-rw-r--r--fs/bcachefs/lru.c84
1 files changed, 84 insertions, 0 deletions
diff --git a/fs/bcachefs/lru.c b/fs/bcachefs/lru.c
index 2ababca5efe5..4f0e6960e597 100644
--- a/fs/bcachefs/lru.c
+++ b/fs/bcachefs/lru.c
@@ -1,10 +1,12 @@
// SPDX-License-Identifier: GPL-2.0
#include "bcachefs.h"
+#include "alloc_background.h"
#include "btree_iter.h"
#include "btree_update.h"
#include "error.h"
#include "lru.h"
+#include "recovery.h"
const char *bch2_lru_invalid(const struct bch_fs *c, struct bkey_s_c k)
{
@@ -117,3 +119,85 @@ int bch2_lru_change(struct btree_trans *trans, u64 id, u64 idx,
return lru_delete(trans, id, idx, old_time) ?:
lru_set(trans, id, idx, new_time);
}
+
+static int bch2_check_lru_key(struct btree_trans *trans,
+ struct btree_iter *lru_iter, bool initial)
+{
+ struct bch_fs *c = trans->c;
+ struct btree_iter iter;
+ struct bkey_s_c lru_k, k;
+ struct bch_alloc_v4 a;
+ struct printbuf buf1 = PRINTBUF;
+ struct printbuf buf2 = PRINTBUF;
+ u64 idx;
+ int ret;
+
+ lru_k = bch2_btree_iter_peek(lru_iter);
+ if (!lru_k.k)
+ return 0;
+
+ ret = bkey_err(lru_k);
+ if (ret)
+ return ret;
+
+ idx = le64_to_cpu(bkey_s_c_to_lru(lru_k).v->idx);
+
+ bch2_trans_iter_init(trans, &iter, BTREE_ID_alloc,
+ POS(lru_k.k->p.inode, idx), 0);
+ k = bch2_btree_iter_peek_slot(&iter);
+ ret = bkey_err(k);
+ if (ret)
+ goto err;
+
+ bch2_alloc_to_v4(k, &a);
+
+ if (fsck_err_on(bucket_state(a) != BUCKET_cached ||
+ a.io_time[READ] != lru_k.k->p.offset, c,
+ "incorrect lru entry %s\n"
+ " for %s",
+ (bch2_bkey_val_to_text(&buf1, c, lru_k), buf1.buf),
+ (bch2_bkey_val_to_text(&buf2, c, k), buf2.buf))) {
+ struct bkey_i *update =
+ bch2_trans_kmalloc(trans, sizeof(*update));
+
+ ret = PTR_ERR_OR_ZERO(update);
+ if (ret)
+ goto err;
+
+ bkey_init(&update->k);
+ update->k.p = lru_iter->pos;
+
+ ret = bch2_trans_update(trans, lru_iter, update, 0);
+ if (ret)
+ goto err;
+ }
+err:
+fsck_err:
+ bch2_trans_iter_exit(trans, &iter);
+ printbuf_exit(&buf2);
+ printbuf_exit(&buf1);
+ return ret;
+}
+
+int bch2_check_lrus(struct bch_fs *c, bool initial)
+{
+ struct btree_trans trans;
+ struct btree_iter iter;
+ struct bkey_s_c k;
+ int ret = 0;
+
+ bch2_trans_init(&trans, c, 0, 0);
+
+ for_each_btree_key(&trans, iter, BTREE_ID_lru, POS_MIN,
+ BTREE_ITER_PREFETCH, k, ret) {
+ ret = __bch2_trans_do(&trans, NULL, NULL, 0,
+ bch2_check_lru_key(&trans, &iter, initial));
+ if (ret)
+ break;
+ }
+ bch2_trans_iter_exit(&trans, &iter);
+
+ bch2_trans_exit(&trans);
+ return ret;
+
+}