summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2023-01-04 07:54:10 +0300
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-23 00:09:52 +0300
commit629a21b621c466deac6e7ce20242308091f09735 (patch)
treeb91390439357a9b087cc49ea65f03d95701464cf
parent46eea9cb9ec14684d1b6e90c17db1ac896f26a5b (diff)
downloadlinux-629a21b621c466deac6e7ce20242308091f09735.tar.xz
bcachefs: Improve invalidate_one_bucket() error messages
Make sure to check for lru entries that point to buckets that don't exist as well as buckets in the wrong state, and improve the error message we print out. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r--fs/bcachefs/alloc_background.c51
-rw-r--r--fs/bcachefs/lru.c9
-rw-r--r--fs/bcachefs/lru.h2
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, \