Commit d39881d2 authored by Kent Overstreet's avatar Kent Overstreet
Browse files

bcachefs: add check for missing fragmentation in check_alloc_to_lru_ref()



We need to make sure we're not missing any fragmenation entries in the
LRU BTREE after repairing ALLOC BTREE

Also, use the new bch2_btree_write_buffer_maybe_flush() helper; this was
only working without it before since bucket invalidation (usually)
wasn't happening while fsck was running.

Co-developed-by: default avatarDaniel Hill <daniel@gluo.nz>
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 92e1c29a
Loading
Loading
Loading
Loading
+23 −25
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@
#include "alloc_background.h"
#include "alloc_foreground.h"
#include "backpointers.h"
#include "bkey_buf.h"
#include "btree_cache.h"
#include "btree_io.h"
#include "btree_key_cache.h"
@@ -1553,13 +1554,13 @@ int bch2_check_alloc_info(struct bch_fs *c)
}

static int bch2_check_alloc_to_lru_ref(struct btree_trans *trans,
				       struct btree_iter *alloc_iter)
				       struct btree_iter *alloc_iter,
				       struct bkey_buf *last_flushed)
{
	struct bch_fs *c = trans->c;
	struct btree_iter lru_iter;
	struct bch_alloc_v4 a_convert;
	const struct bch_alloc_v4 *a;
	struct bkey_s_c alloc_k, lru_k;
	struct bkey_s_c alloc_k;
	struct printbuf buf = PRINTBUF;
	int ret;

@@ -1573,6 +1574,14 @@ static int bch2_check_alloc_to_lru_ref(struct btree_trans *trans,

	a = bch2_alloc_to_v4(alloc_k, &a_convert);

	if (a->fragmentation_lru) {
		ret = bch2_lru_check_set(trans, BCH_LRU_FRAGMENTATION_START,
					 a->fragmentation_lru,
					 alloc_k, last_flushed);
		if (ret)
			return ret;
	}

	if (a->data_type != BCH_DATA_cached)
		return 0;

@@ -1597,41 +1606,30 @@ static int bch2_check_alloc_to_lru_ref(struct btree_trans *trans,
		a = &a_mut->v;
	}

	lru_k = bch2_bkey_get_iter(trans, &lru_iter, BTREE_ID_lru,
			     lru_pos(alloc_k.k->p.inode,
				     bucket_to_u64(alloc_k.k->p),
				     a->io_time[READ]), 0);
	ret = bkey_err(lru_k);
	if (ret)
		return ret;

	if (fsck_err_on(lru_k.k->type != KEY_TYPE_set, c,
			alloc_key_to_missing_lru_entry,
			"missing lru entry\n"
			"  %s",
			(printbuf_reset(&buf),
			 bch2_bkey_val_to_text(&buf, c, alloc_k), buf.buf))) {
		ret = bch2_lru_set(trans,
				   alloc_k.k->p.inode,
				   bucket_to_u64(alloc_k.k->p),
				   a->io_time[READ]);
	ret = bch2_lru_check_set(trans, alloc_k.k->p.inode, a->io_time[READ],
				 alloc_k, last_flushed);
	if (ret)
		goto err;
	}
err:
fsck_err:
	bch2_trans_iter_exit(trans, &lru_iter);
	printbuf_exit(&buf);
	return ret;
}

int bch2_check_alloc_to_lru_refs(struct bch_fs *c)
{
	struct bkey_buf last_flushed;

	bch2_bkey_buf_init(&last_flushed);
	bkey_init(&last_flushed.k->k);

	int ret = bch2_trans_run(c,
		for_each_btree_key_commit(trans, iter, BTREE_ID_alloc,
				POS_MIN, BTREE_ITER_prefetch, k,
				NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
			bch2_check_alloc_to_lru_ref(trans, &iter)));
			bch2_check_alloc_to_lru_ref(trans, &iter, &last_flushed)));

	bch2_bkey_buf_exit(&last_flushed, c);
	bch_err_fn(c, ret);
	return ret;
}
+39 −0
Original line number Diff line number Diff line
@@ -77,6 +77,45 @@ static const char * const bch2_lru_types[] = {
	NULL
};

int bch2_lru_check_set(struct btree_trans *trans,
		       u16 lru_id, u64 time,
		       struct bkey_s_c referring_k,
		       struct bkey_buf *last_flushed)
{
	struct bch_fs *c = trans->c;
	struct printbuf buf = PRINTBUF;
	struct btree_iter lru_iter;
	struct bkey_s_c lru_k =
		bch2_bkey_get_iter(trans, &lru_iter, BTREE_ID_lru,
				   lru_pos(lru_id,
					   bucket_to_u64(referring_k.k->p),
					   time), 0);
	int ret = bkey_err(lru_k);
	if (ret)
		return ret;

	if (lru_k.k->type != KEY_TYPE_set) {
		ret = bch2_btree_write_buffer_maybe_flush(trans, referring_k, last_flushed);
		if (ret)
			goto err;

		if (fsck_err(c, alloc_key_to_missing_lru_entry,
			     "missing %s lru entry\n"
			     "  %s",
			     bch2_lru_types[lru_type(lru_k)],
			     (bch2_bkey_val_to_text(&buf, c, referring_k), buf.buf))) {
			ret = bch2_lru_set(trans, lru_id, bucket_to_u64(referring_k.k->p), time);
			if (ret)
				goto err;
		}
	}
err:
fsck_err:
	bch2_trans_iter_exit(trans, &lru_iter);
	printbuf_exit(&buf);
	return ret;
}

static int bch2_check_lru_key(struct btree_trans *trans,
			      struct btree_iter *lru_iter,
			      struct bkey_s_c lru_k,
+3 −0
Original line number Diff line number Diff line
@@ -61,6 +61,9 @@ int bch2_lru_del(struct btree_trans *, u16, u64, u64);
int bch2_lru_set(struct btree_trans *, u16, u64, u64);
int bch2_lru_change(struct btree_trans *, u16, u64, u64, u64);

struct bkey_buf;
int bch2_lru_check_set(struct btree_trans *, u16, u64, struct bkey_s_c, struct bkey_buf *);

int bch2_check_lrus(struct bch_fs *);

#endif /* _BCACHEFS_LRU_H */