1 // SPDX-License-Identifier: GPL-2.0
4 #include "alloc_background.h"
5 #include "btree_iter.h"
6 #include "btree_update.h"
11 const char *bch2_lru_invalid(const struct bch_fs *c, struct bkey_s_c k)
13 const struct bch_lru *lru = bkey_s_c_to_lru(k).v;
15 if (bkey_val_bytes(k.k) < sizeof(*lru))
16 return "incorrect value size";
21 void bch2_lru_to_text(struct printbuf *out, struct bch_fs *c,
24 const struct bch_lru *lru = bkey_s_c_to_lru(k).v;
26 pr_buf(out, "idx %llu", le64_to_cpu(lru->idx));
29 static int lru_delete(struct btree_trans *trans, u64 id, u64 idx, u64 time)
31 struct bch_fs *c = trans->c;
32 struct btree_iter iter;
40 bch2_trans_iter_init(trans, &iter, BTREE_ID_lru,
43 BTREE_ITER_WITH_UPDATES);
44 k = bch2_btree_iter_peek_slot(&iter);
49 if (k.k->type != KEY_TYPE_lru) {
50 bch2_fs_inconsistent(c,
51 "pointer to nonexistent lru %llu:%llu",
57 existing_idx = le64_to_cpu(bkey_s_c_to_lru(k).v->idx);
58 if (existing_idx != idx) {
59 bch2_fs_inconsistent(c,
60 "lru %llu:%llu with wrong backpointer: got %llu, should be %llu",
61 id, time, existing_idx, idx);
66 ret = bch2_btree_delete_at(trans, &iter, 0);
68 bch2_trans_iter_exit(trans, &iter);
72 static int lru_set(struct btree_trans *trans, u64 lru_id, u64 idx, u64 *time)
74 struct btree_iter iter;
76 struct bkey_i_lru *lru;
82 for_each_btree_key_norestart(trans, iter, BTREE_ID_lru,
86 BTREE_ITER_WITH_UPDATES, k, ret)
87 if (bkey_deleted(k.k))
93 BUG_ON(iter.pos.inode != lru_id);
94 *time = iter.pos.offset;
96 lru = bch2_trans_kmalloc(trans, sizeof(*lru));
97 ret = PTR_ERR_OR_ZERO(lru);
101 bkey_lru_init(&lru->k_i);
103 lru->v.idx = cpu_to_le64(idx);
105 ret = bch2_trans_update(trans, &iter, &lru->k_i, 0);
109 bch2_trans_iter_exit(trans, &iter);
113 int bch2_lru_change(struct btree_trans *trans, u64 id, u64 idx,
114 u64 old_time, u64 *new_time)
116 if (old_time == *new_time)
119 return lru_delete(trans, id, idx, old_time) ?:
120 lru_set(trans, id, idx, new_time);
123 static int bch2_check_lru_key(struct btree_trans *trans,
124 struct btree_iter *lru_iter, bool initial)
126 struct bch_fs *c = trans->c;
127 struct btree_iter iter;
128 struct bkey_s_c lru_k, k;
129 struct bkey_alloc_unpacked a;
130 struct printbuf buf1 = PRINTBUF;
131 struct printbuf buf2 = PRINTBUF;
135 lru_k = bch2_btree_iter_peek(lru_iter);
139 ret = bkey_err(lru_k);
143 idx = le64_to_cpu(bkey_s_c_to_lru(lru_k).v->idx);
145 bch2_trans_iter_init(trans, &iter, BTREE_ID_alloc,
146 POS(lru_k.k->p.inode, idx), 0);
147 k = bch2_btree_iter_peek_slot(&iter);
152 a = bch2_alloc_unpack(k);
154 if (fsck_err_on(bucket_state(a) != BUCKET_cached ||
155 a.read_time != lru_k.k->p.offset, c,
156 "incorrect lru entry %s\n"
158 (bch2_bkey_val_to_text(&buf1, c, lru_k), buf1.buf),
159 (bch2_bkey_val_to_text(&buf2, c, k), buf2.buf))) {
160 struct bkey_i *update =
161 bch2_trans_kmalloc(trans, sizeof(*update));
163 ret = PTR_ERR_OR_ZERO(update);
167 bkey_init(&update->k);
168 update->k.p = lru_iter->pos;
170 ret = bch2_trans_update(trans, lru_iter, update, 0);
176 bch2_trans_iter_exit(trans, &iter);
177 printbuf_exit(&buf2);
178 printbuf_exit(&buf1);
182 int bch2_check_lrus(struct bch_fs *c, bool initial)
184 struct btree_trans trans;
185 struct btree_iter iter;
189 bch2_trans_init(&trans, c, 0, 0);
191 for_each_btree_key(&trans, iter, BTREE_ID_lru, POS_MIN,
192 BTREE_ITER_PREFETCH, k, ret) {
193 ret = __bch2_trans_do(&trans, NULL, NULL, 0,
194 bch2_check_lru_key(&trans, &iter, initial));
198 bch2_trans_iter_exit(&trans, &iter);
200 bch2_trans_exit(&trans);