Commit 45dbb73e authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet

bcachefs: improve extent debugcheck fn

Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 641ab736
...@@ -626,48 +626,34 @@ void bch2_btree_ptr_debugcheck(struct bch_fs *c, struct btree *b, ...@@ -626,48 +626,34 @@ void bch2_btree_ptr_debugcheck(struct bch_fs *c, struct btree *b,
{ {
struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k); struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k);
const struct bch_extent_ptr *ptr; const struct bch_extent_ptr *ptr;
unsigned seq;
const char *err; const char *err;
char buf[160]; char buf[160];
struct bucket_mark mark; struct bucket_mark mark;
struct bch_dev *ca; struct bch_dev *ca;
unsigned replicas = 0;
bool bad; bch2_fs_bug_on(!test_bit(BCH_FS_REBUILD_REPLICAS, &c->flags) &&
!bch2_bkey_replicas_marked(c, k, false), c,
"btree key bad (replicas not marked in superblock):\n%s",
(bch2_bkey_val_to_text(&PBUF(buf), c, k), buf));
if (!test_bit(BCH_FS_INITIAL_GC_DONE, &c->flags))
return;
bkey_for_each_ptr(ptrs, ptr) { bkey_for_each_ptr(ptrs, ptr) {
ca = bch_dev_bkey_exists(c, ptr->dev); ca = bch_dev_bkey_exists(c, ptr->dev);
replicas++;
if (!test_bit(BCH_FS_ALLOC_READ_DONE, &c->flags)) mark = ptr_bucket_mark(ca, ptr);
continue;
err = "stale"; err = "stale";
if (ptr_stale(ca, ptr)) if (gen_after(mark.gen, ptr->gen))
goto err; goto err;
do {
seq = read_seqcount_begin(&c->gc_pos_lock);
mark = ptr_bucket_mark(ca, ptr);
bad = gc_pos_cmp(c->gc_pos, gc_pos_btree_node(b)) > 0 &&
(mark.data_type != BCH_DATA_BTREE ||
mark.dirty_sectors < c->opts.btree_node_size);
} while (read_seqcount_retry(&c->gc_pos_lock, seq));
err = "inconsistent"; err = "inconsistent";
if (bad) if (mark.data_type != BCH_DATA_BTREE ||
mark.dirty_sectors < c->opts.btree_node_size)
goto err; goto err;
} }
if (!test_bit(BCH_FS_REBUILD_REPLICAS, &c->flags) &&
!bch2_bkey_replicas_marked(c, k, false)) {
bch2_bkey_val_to_text(&PBUF(buf), c, k);
bch2_fs_bug(c,
"btree key bad (replicas not marked in superblock):\n%s",
buf);
return;
}
return; return;
err: err:
bch2_bkey_val_to_text(&PBUF(buf), c, k); bch2_bkey_val_to_text(&PBUF(buf), c, k);
...@@ -1340,13 +1326,9 @@ void bch2_extent_debugcheck(struct bch_fs *c, struct btree *b, ...@@ -1340,13 +1326,9 @@ void bch2_extent_debugcheck(struct bch_fs *c, struct btree *b,
struct bkey_s_c k) struct bkey_s_c k)
{ {
struct bkey_s_c_extent e = bkey_s_c_to_extent(k); struct bkey_s_c_extent e = bkey_s_c_to_extent(k);
const struct bch_extent_ptr *ptr; const union bch_extent_entry *entry;
struct bch_dev *ca; struct extent_ptr_decoded p;
struct bucket_mark mark;
unsigned seq, stale;
char buf[160]; char buf[160];
bool bad;
unsigned replicas = 0;
/* /*
* XXX: we should be doing most/all of these checks at startup time, * XXX: we should be doing most/all of these checks at startup time,
...@@ -1357,73 +1339,42 @@ void bch2_extent_debugcheck(struct bch_fs *c, struct btree *b, ...@@ -1357,73 +1339,42 @@ void bch2_extent_debugcheck(struct bch_fs *c, struct btree *b,
* going to get overwritten during replay) * going to get overwritten during replay)
*/ */
extent_for_each_ptr(e, ptr) { bch2_fs_bug_on(!test_bit(BCH_FS_REBUILD_REPLICAS, &c->flags) &&
ca = bch_dev_bkey_exists(c, ptr->dev); !bch2_bkey_replicas_marked(c, e.s_c, false), c,
replicas++; "extent key bad (replicas not marked in superblock):\n%s",
(bch2_bkey_val_to_text(&PBUF(buf), c, e.s_c), buf));
/* /*
* If journal replay hasn't finished, we might be seeing keys * If journal replay hasn't finished, we might be seeing keys
* that will be overwritten by the time journal replay is done: * that will be overwritten by the time journal replay is done:
*/ */
if (!test_bit(JOURNAL_REPLAY_DONE, &c->journal.flags)) if (!test_bit(JOURNAL_REPLAY_DONE, &c->journal.flags))
continue; return;
stale = 0;
do {
seq = read_seqcount_begin(&c->gc_pos_lock);
mark = ptr_bucket_mark(ca, ptr);
/* between mark and bucket gen */
smp_rmb();
stale = ptr_stale(ca, ptr);
bch2_fs_bug_on(stale && !ptr->cached, c,
"stale dirty pointer");
bch2_fs_bug_on(stale > 96, c,
"key too stale: %i",
stale);
if (stale)
break;
bad = gc_pos_cmp(c->gc_pos, gc_pos_btree_node(b)) > 0 && extent_for_each_ptr_decode(e, p, entry) {
(mark.data_type != BCH_DATA_USER || struct bch_dev *ca = bch_dev_bkey_exists(c, p.ptr.dev);
!(ptr->cached struct bucket_mark mark = ptr_bucket_mark(ca, &p.ptr);
unsigned stale = gen_after(mark.gen, p.ptr.gen);
unsigned disk_sectors = ptr_disk_sectors(p);
unsigned mark_sectors = p.ptr.cached
? mark.cached_sectors ? mark.cached_sectors
: mark.dirty_sectors)); : mark.dirty_sectors;
} while (read_seqcount_retry(&c->gc_pos_lock, seq));
if (bad) bch2_fs_bug_on(stale && !p.ptr.cached, c,
goto bad_ptr; "stale dirty pointer (ptr gen %u bucket %u",
} p.ptr.gen, mark.gen);
if (replicas > BCH_REPLICAS_MAX) { bch2_fs_bug_on(stale > 96, c, "key too stale: %i", stale);
bch2_bkey_val_to_text(&PBUF(buf), c, e.s_c);
bch2_fs_bug(c,
"extent key bad (too many replicas: %u): %s",
replicas, buf);
return;
}
if (!test_bit(BCH_FS_REBUILD_REPLICAS, &c->flags) && bch2_fs_bug_on(!stale &&
!bch2_bkey_replicas_marked(c, e.s_c, false)) { (mark.data_type != BCH_DATA_USER ||
bch2_bkey_val_to_text(&PBUF(buf), c, e.s_c); mark_sectors < disk_sectors), c,
bch2_fs_bug(c, "extent pointer not marked: %s:\n"
"extent key bad (replicas not marked in superblock):\n%s", "type %u sectors %u < %u",
buf); (bch2_bkey_val_to_text(&PBUF(buf), c, e.s_c), buf),
return; mark.data_type,
mark_sectors, disk_sectors);
} }
return;
bad_ptr:
bch2_bkey_val_to_text(&PBUF(buf), c, e.s_c);
bch2_fs_bug(c, "extent pointer bad gc mark: %s:\nbucket %zu "
"gen %i type %u", buf,
PTR_BUCKET_NR(ca, ptr), mark.gen, mark.data_type);
} }
void bch2_extent_to_text(struct printbuf *out, struct bch_fs *c, void bch2_extent_to_text(struct printbuf *out, struct bch_fs *c,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment