X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libbcachefs%2Flru.c;h=a5cc0ed195d6324d1f49718d5860b24045579f1b;hb=d320a4e927fd706b34c714b77130965a385ea4fb;hp=9eec12a99535e84675e5ad3d5bd63b3348611f1b;hpb=46a6b9210c927ab46fd1227cb6f641be0b4a7505;p=bcachefs-tools-debian diff --git a/libbcachefs/lru.c b/libbcachefs/lru.c index 9eec12a..a5cc0ed 100644 --- a/libbcachefs/lru.c +++ b/libbcachefs/lru.c @@ -4,29 +4,23 @@ #include "alloc_background.h" #include "btree_iter.h" #include "btree_update.h" +#include "btree_write_buffer.h" #include "error.h" #include "lru.h" #include "recovery.h" /* KEY_TYPE_lru is obsolete: */ -int bch2_lru_invalid(const struct bch_fs *c, struct bkey_s_c k, - unsigned flags, struct printbuf *err) +int bch2_lru_invalid(struct bch_fs *c, struct bkey_s_c k, + enum bkey_invalid_flags flags, + struct printbuf *err) { - const struct bch_lru *lru = bkey_s_c_to_lru(k).v; - - if (bkey_val_bytes(k.k) < sizeof(*lru)) { - prt_printf(err, "incorrect value size (%zu < %zu)", - bkey_val_bytes(k.k), sizeof(*lru)); - return -BCH_ERR_invalid_bkey; - } - - if (!lru_pos_time(k.k->p)) { - prt_printf(err, "lru entry at time=0"); - return -BCH_ERR_invalid_bkey; - - } + int ret = 0; - return 0; + bkey_fsck_err_on(!lru_pos_time(k.k->p), c, err, + lru_entry_at_time_0, + "lru entry at time=0"); +fsck_err: + return ret; } void bch2_lru_to_text(struct printbuf *out, struct bch_fs *c, @@ -47,28 +41,12 @@ void bch2_lru_pos_to_text(struct printbuf *out, struct bpos lru) } static int __bch2_lru_set(struct btree_trans *trans, u16 lru_id, - u64 dev_bucket, u64 time, unsigned key_type) + u64 dev_bucket, u64 time, bool set) { - struct bkey_i *k; - int ret = 0; - - if (!time) - return 0; - - k = bch2_trans_kmalloc_nomemzero(trans, sizeof(*k)); - ret = PTR_ERR_OR_ZERO(k); - if (unlikely(ret)) - return ret; - - bkey_init(&k->k); - k->k.type = key_type; - k->k.p = lru_pos(lru_id, dev_bucket, time); - - EBUG_ON(lru_pos_id(k->k.p) != lru_id); - EBUG_ON(lru_pos_time(k->k.p) != time); - EBUG_ON(k->k.p.offset != dev_bucket); - - return bch2_trans_update_buffered(trans, BTREE_ID_lru, k); + return time + ? bch2_btree_bit_mod(trans, BTREE_ID_lru, + lru_pos(lru_id, dev_bucket, time), set) + : 0; } int bch2_lru_del(struct btree_trans *trans, u16 lru_id, u64 dev_bucket, u64 time) @@ -101,7 +79,8 @@ static const char * const bch2_lru_types[] = { static int bch2_check_lru_key(struct btree_trans *trans, struct btree_iter *lru_iter, - struct bkey_s_c lru_k) + struct bkey_s_c lru_k, + struct bpos *last_flushed_pos) { struct bch_fs *c = trans->c; struct btree_iter iter; @@ -116,12 +95,12 @@ static int bch2_check_lru_key(struct btree_trans *trans, int ret; if (fsck_err_on(!bch2_dev_bucket_exists(c, alloc_pos), c, + lru_entry_to_invalid_bucket, "lru key points to nonexistent device:bucket %llu:%llu", alloc_pos.inode, alloc_pos.offset)) return bch2_btree_delete_at(trans, lru_iter, 0); - bch2_trans_iter_init(trans, &iter, BTREE_ID_alloc, alloc_pos, 0); - k = bch2_btree_iter_peek_slot(&iter); + k = bch2_bkey_get_iter(trans, &iter, BTREE_ID_alloc, alloc_pos, 0); ret = bkey_err(k); if (ret) goto err; @@ -137,19 +116,27 @@ static int bch2_check_lru_key(struct btree_trans *trans, break; } - if (fsck_err_on(lru_k.k->type != KEY_TYPE_set || - lru_pos_time(lru_k.k->p) != idx, c, - "incorrect lru entry: lru %s time %llu\n" - " %s\n" - " for %s", - bch2_lru_types[type], - lru_pos_time(lru_k.k->p), - (bch2_bkey_val_to_text(&buf1, c, lru_k), buf1.buf), - (bch2_bkey_val_to_text(&buf2, c, k), buf2.buf))) { - ret = bch2_btree_delete_at(trans, lru_iter, 0); - if (ret) - goto err; + if (lru_k.k->type != KEY_TYPE_set || + lru_pos_time(lru_k.k->p) != idx) { + if (!bpos_eq(*last_flushed_pos, lru_k.k->p)) { + *last_flushed_pos = lru_k.k->p; + ret = bch2_btree_write_buffer_flush_sync(trans) ?: + -BCH_ERR_transaction_restart_write_buffer_flush; + goto out; + } + + if (c->opts.reconstruct_alloc || + fsck_err(c, lru_entry_bad, + "incorrect lru entry: lru %s time %llu\n" + " %s\n" + " for %s", + bch2_lru_types[type], + lru_pos_time(lru_k.k->p), + (bch2_bkey_val_to_text(&buf1, c, lru_k), buf1.buf), + (bch2_bkey_val_to_text(&buf2, c, k), buf2.buf))) + ret = bch2_btree_delete_at(trans, lru_iter, 0); } +out: err: fsck_err: bch2_trans_iter_exit(trans, &iter); @@ -160,19 +147,18 @@ fsck_err: int bch2_check_lrus(struct bch_fs *c) { - struct btree_trans trans; struct btree_iter iter; struct bkey_s_c k; + struct bpos last_flushed_pos = POS_MIN; int ret = 0; - bch2_trans_init(&trans, c, 0, 0); - - ret = for_each_btree_key_commit(&trans, iter, - BTREE_ID_lru, POS_MIN, BTREE_ITER_PREFETCH, k, - NULL, NULL, BTREE_INSERT_NOFAIL|BTREE_INSERT_LAZY_RW, - bch2_check_lru_key(&trans, &iter, k)); - - bch2_trans_exit(&trans); + ret = bch2_trans_run(c, + for_each_btree_key_commit(trans, iter, + BTREE_ID_lru, POS_MIN, BTREE_ITER_PREFETCH, k, + NULL, NULL, BTREE_INSERT_NOFAIL|BTREE_INSERT_LAZY_RW, + bch2_check_lru_key(trans, &iter, k, &last_flushed_pos))); + if (ret) + bch_err_fn(c, ret); return ret; }