diff options
-rw-r--r-- | fs/bcachefs/alloc_background.c | 51 | ||||
-rw-r--r-- | fs/bcachefs/lru.c | 9 | ||||
-rw-r--r-- | fs/bcachefs/lru.h | 2 |
3 files changed, 46 insertions, 16 deletions
diff --git a/fs/bcachefs/alloc_background.c b/fs/bcachefs/alloc_background.c index e8412fb1547e..83c750e049dc 100644 --- a/fs/bcachefs/alloc_background.c +++ b/fs/bcachefs/alloc_background.c @@ -1751,37 +1751,38 @@ void bch2_do_discards(struct bch_fs *c) static int invalidate_one_bucket(struct btree_trans *trans, struct btree_iter *lru_iter, - struct bpos bucket, + struct bkey_s_c lru_k, s64 *nr_to_invalidate) { struct bch_fs *c = trans->c; struct btree_iter alloc_iter = { NULL }; - struct bkey_i_alloc_v4 *a; + struct bkey_i_alloc_v4 *a = NULL; struct printbuf buf = PRINTBUF; + struct bpos bucket = u64_to_bucket(lru_k.k->p.offset); unsigned cached_sectors; int ret = 0; if (*nr_to_invalidate <= 0) return 1; + if (!bch2_dev_bucket_exists(c, bucket)) { + prt_str(&buf, "lru entry points to invalid bucket"); + goto err; + } + a = bch2_trans_start_alloc_update(trans, &alloc_iter, bucket); ret = PTR_ERR_OR_ZERO(a); if (ret) goto out; if (lru_pos_time(lru_iter->pos) != alloc_lru_idx(a->v)) { - prt_printf(&buf, "alloc key does not point back to lru entry when invalidating bucket:\n "); - bch2_bpos_to_text(&buf, lru_iter->pos); - prt_printf(&buf, "\n "); - bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&a->k_i)); - - bch_err(c, "%s", buf.buf); - if (test_bit(BCH_FS_CHECK_LRUS_DONE, &c->flags)) { - bch2_inconsistent_error(c); - ret = -EINVAL; - } + prt_str(&buf, "alloc key does not point back to lru entry when invalidating bucket:"); + goto err; + } - goto out; + if (a->v.data_type != BCH_DATA_cached) { + prt_str(&buf, "lru entry points to non cached bucket:"); + goto err; } if (!a->v.cached_sectors) @@ -1810,6 +1811,26 @@ out: bch2_trans_iter_exit(trans, &alloc_iter); printbuf_exit(&buf); return ret; +err: + prt_str(&buf, "\n lru key: "); + bch2_bkey_val_to_text(&buf, c, lru_k); + + prt_str(&buf, "\n lru entry: "); + bch2_lru_pos_to_text(&buf, lru_iter->pos); + + prt_str(&buf, "\n alloc key: "); + if (!a) + bch2_bpos_to_text(&buf, bucket); + else + bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&a->k_i)); + + bch_err(c, "%s", buf.buf); + if (test_bit(BCH_FS_CHECK_LRUS_DONE, &c->flags)) { + bch2_inconsistent_error(c); + ret = -EINVAL; + } + + goto out; } static void bch2_do_invalidates_work(struct work_struct *work) @@ -1832,9 +1853,7 @@ static void bch2_do_invalidates_work(struct work_struct *work) lru_pos(ca->dev_idx, 0, 0), lru_pos(ca->dev_idx, U64_MAX, LRU_TIME_MAX), BTREE_ITER_INTENT, k, - invalidate_one_bucket(&trans, &iter, - u64_to_bucket(k.k->p.offset), - &nr_to_invalidate)); + invalidate_one_bucket(&trans, &iter, k, &nr_to_invalidate)); if (ret < 0) { percpu_ref_put(&ca->ref); diff --git a/fs/bcachefs/lru.c b/fs/bcachefs/lru.c index f1d6368dda07..07fb41ca8c6b 100644 --- a/fs/bcachefs/lru.c +++ b/fs/bcachefs/lru.c @@ -37,6 +37,15 @@ void bch2_lru_to_text(struct printbuf *out, struct bch_fs *c, prt_printf(out, "idx %llu", le64_to_cpu(lru->idx)); } +void bch2_lru_pos_to_text(struct printbuf *out, struct bpos lru) +{ + prt_printf(out, "%llu:%llu -> %llu:%llu", + lru_pos_id(lru), + lru_pos_time(lru), + u64_to_bucket(lru.offset).inode, + u64_to_bucket(lru.offset).offset); +} + static int __bch2_lru_set(struct btree_trans *trans, u16 lru_id, u64 dev_bucket, u64 time, unsigned key_type) { diff --git a/fs/bcachefs/lru.h b/fs/bcachefs/lru.h index 0cfc7459711b..b8d9848cdb1a 100644 --- a/fs/bcachefs/lru.h +++ b/fs/bcachefs/lru.h @@ -25,6 +25,8 @@ static inline u64 lru_pos_time(struct bpos pos) int bch2_lru_invalid(const struct bch_fs *, struct bkey_s_c, unsigned, struct printbuf *); void bch2_lru_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c); +void bch2_lru_pos_to_text(struct printbuf *, struct bpos); + #define bch2_bkey_ops_lru ((struct bkey_ops) { \ .key_invalid = bch2_lru_invalid, \ .val_to_text = bch2_lru_to_text, \ |