Commit b3b66e30 authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet

bcachefs: Have fsck check for stripe pointers matching stripe

Signed-off-by: default avatarKent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 53b3e3c0
...@@ -223,6 +223,11 @@ static int bch2_check_fix_ptrs(struct bch_fs *c, enum btree_id btree_id, ...@@ -223,6 +223,11 @@ static int bch2_check_fix_ptrs(struct bch_fs *c, enum btree_id btree_id,
"pointer to nonexistent stripe %llu", "pointer to nonexistent stripe %llu",
(u64) p.ec.idx)) (u64) p.ec.idx))
do_update = true; do_update = true;
if (fsck_err_on(!bch2_ptr_matches_stripe_m(m, p), c,
"pointer does not match stripe %llu",
(u64) p.ec.idx))
do_update = true;
} }
} }
...@@ -274,8 +279,22 @@ static int bch2_check_fix_ptrs(struct bch_fs *c, enum btree_id btree_id, ...@@ -274,8 +279,22 @@ static int bch2_check_fix_ptrs(struct bch_fs *c, enum btree_id btree_id,
if (extent_entry_type(entry) == BCH_EXTENT_ENTRY_stripe_ptr) { if (extent_entry_type(entry) == BCH_EXTENT_ENTRY_stripe_ptr) {
struct stripe *m = genradix_ptr(&c->stripes[true], struct stripe *m = genradix_ptr(&c->stripes[true],
entry->stripe_ptr.idx); entry->stripe_ptr.idx);
union bch_extent_entry *next_ptr;
bkey_extent_entry_for_each_from(ptrs, next_ptr, entry)
if (extent_entry_type(next_ptr) == BCH_EXTENT_ENTRY_ptr)
goto found;
next_ptr = NULL;
found:
if (!next_ptr) {
bch_err(c, "aieee, found stripe ptr with no data ptr");
continue;
}
if (!m || !m->alive) { if (!m || !m->alive ||
!__bch2_ptr_matches_stripe(&m->ptrs[entry->stripe_ptr.block],
&next_ptr->ptr,
m->sectors)) {
bch2_bkey_extent_entry_drop(new, entry); bch2_bkey_extent_entry_drop(new, entry);
goto again; goto again;
} }
......
...@@ -1215,6 +1215,8 @@ static int bch2_mark_stripe(struct bch_fs *c, ...@@ -1215,6 +1215,8 @@ static int bch2_mark_stripe(struct bch_fs *c,
m->block_sectors[i] = m->block_sectors[i] =
stripe_blockcount_get(new_s, i); stripe_blockcount_get(new_s, i);
m->blocks_nonempty += !!m->block_sectors[i]; m->blocks_nonempty += !!m->block_sectors[i];
m->ptrs[i] = new_s->ptrs[i];
} }
bch2_bkey_to_replicas(&m->r.e, new); bch2_bkey_to_replicas(&m->r.e, new);
......
...@@ -151,7 +151,8 @@ static int bkey_matches_stripe(struct bch_stripe *s, ...@@ -151,7 +151,8 @@ static int bkey_matches_stripe(struct bch_stripe *s,
bkey_for_each_ptr(ptrs, ptr) bkey_for_each_ptr(ptrs, ptr)
for (i = 0; i < nr_data; i++) for (i = 0; i < nr_data; i++)
if (__bch2_ptr_matches_stripe(s, ptr, i)) if (__bch2_ptr_matches_stripe(&s->ptrs[i], ptr,
le16_to_cpu(s->sectors)))
return i; return i;
return -1; return -1;
......
...@@ -84,27 +84,42 @@ static inline void stripe_csum_set(struct bch_stripe *s, ...@@ -84,27 +84,42 @@ static inline void stripe_csum_set(struct bch_stripe *s,
memcpy(stripe_csum(s, block, csum_idx), &csum, bch_crc_bytes[s->csum_type]); memcpy(stripe_csum(s, block, csum_idx), &csum, bch_crc_bytes[s->csum_type]);
} }
static inline bool __bch2_ptr_matches_stripe(const struct bch_stripe *s, static inline bool __bch2_ptr_matches_stripe(const struct bch_extent_ptr *stripe_ptr,
const struct bch_extent_ptr *ptr, const struct bch_extent_ptr *data_ptr,
unsigned block) unsigned sectors)
{
return data_ptr->dev == stripe_ptr->dev &&
data_ptr->gen == stripe_ptr->gen &&
data_ptr->offset >= stripe_ptr->offset &&
data_ptr->offset < stripe_ptr->offset + sectors;
}
static inline bool bch2_ptr_matches_stripe(const struct bch_stripe *s,
struct extent_ptr_decoded p)
{ {
unsigned nr_data = s->nr_blocks - s->nr_redundant; unsigned nr_data = s->nr_blocks - s->nr_redundant;
if (block >= nr_data) BUG_ON(!p.has_ec);
if (p.ec.block >= nr_data)
return false; return false;
return ptr->dev == s->ptrs[block].dev && return __bch2_ptr_matches_stripe(&s->ptrs[p.ec.block], &p.ptr,
ptr->gen == s->ptrs[block].gen && le16_to_cpu(s->sectors));
ptr->offset >= s->ptrs[block].offset &&
ptr->offset < s->ptrs[block].offset + le16_to_cpu(s->sectors);
} }
static inline bool bch2_ptr_matches_stripe(const struct bch_stripe *s, static inline bool bch2_ptr_matches_stripe_m(const struct stripe *m,
struct extent_ptr_decoded p) struct extent_ptr_decoded p)
{ {
unsigned nr_data = m->nr_blocks - m->nr_redundant;
BUG_ON(!p.has_ec); BUG_ON(!p.has_ec);
return __bch2_ptr_matches_stripe(s, &p.ptr, p.ec.block); if (p.ec.block >= nr_data)
return false;
return __bch2_ptr_matches_stripe(&m->ptrs[p.ec.block], &p.ptr,
m->sectors);
} }
struct bch_read_bio; struct bch_read_bio;
......
...@@ -22,6 +22,7 @@ struct stripe { ...@@ -22,6 +22,7 @@ struct stripe {
unsigned on_heap:1; unsigned on_heap:1;
u8 blocks_nonempty; u8 blocks_nonempty;
u16 block_sectors[BCH_BKEY_PTRS_MAX]; u16 block_sectors[BCH_BKEY_PTRS_MAX];
struct bch_extent_ptr ptrs[BCH_BKEY_PTRS_MAX];
struct bch_replicas_padded r; struct bch_replicas_padded r;
}; };
......
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