diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2021-03-13 00:55:28 +0300 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-23 00:08:55 +0300 |
commit | b3b66e30445e42a94fa171fad99e0b4e4e43c1ac (patch) | |
tree | e2a425848894d9e0fddd1b740e72d8ceb1cd62a9 | |
parent | 53b3e3c0e2f14f661cd61bbc9b82dc9383f783b9 (diff) | |
download | linux-b3b66e30445e42a94fa171fad99e0b4e4e43c1ac.tar.xz |
bcachefs: Have fsck check for stripe pointers matching stripe
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r-- | fs/bcachefs/btree_gc.c | 21 | ||||
-rw-r--r-- | fs/bcachefs/buckets.c | 2 | ||||
-rw-r--r-- | fs/bcachefs/ec.c | 3 | ||||
-rw-r--r-- | fs/bcachefs/ec.h | 37 | ||||
-rw-r--r-- | fs/bcachefs/ec_types.h | 1 |
5 files changed, 51 insertions, 13 deletions
diff --git a/fs/bcachefs/btree_gc.c b/fs/bcachefs/btree_gc.c index 808bb9ca8d50..e8cdc82d3451 100644 --- a/fs/bcachefs/btree_gc.c +++ b/fs/bcachefs/btree_gc.c @@ -223,6 +223,11 @@ static int bch2_check_fix_ptrs(struct bch_fs *c, enum btree_id btree_id, "pointer to nonexistent stripe %llu", (u64) p.ec.idx)) 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 @@ again: if (extent_entry_type(entry) == BCH_EXTENT_ENTRY_stripe_ptr) { struct stripe *m = genradix_ptr(&c->stripes[true], 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); goto again; } diff --git a/fs/bcachefs/buckets.c b/fs/bcachefs/buckets.c index 55b9818a1dc2..7bf2fded816f 100644 --- a/fs/bcachefs/buckets.c +++ b/fs/bcachefs/buckets.c @@ -1215,6 +1215,8 @@ static int bch2_mark_stripe(struct bch_fs *c, m->block_sectors[i] = stripe_blockcount_get(new_s, i); m->blocks_nonempty += !!m->block_sectors[i]; + + m->ptrs[i] = new_s->ptrs[i]; } bch2_bkey_to_replicas(&m->r.e, new); diff --git a/fs/bcachefs/ec.c b/fs/bcachefs/ec.c index ced8ceeef992..f61d4c873a82 100644 --- a/fs/bcachefs/ec.c +++ b/fs/bcachefs/ec.c @@ -151,7 +151,8 @@ static int bkey_matches_stripe(struct bch_stripe *s, bkey_for_each_ptr(ptrs, ptr) 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 -1; diff --git a/fs/bcachefs/ec.h b/fs/bcachefs/ec.h index 765baa9d9264..744e51eaf327 100644 --- a/fs/bcachefs/ec.h +++ b/fs/bcachefs/ec.h @@ -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]); } -static inline bool __bch2_ptr_matches_stripe(const struct bch_stripe *s, - const struct bch_extent_ptr *ptr, - unsigned block) +static inline bool __bch2_ptr_matches_stripe(const struct bch_extent_ptr *stripe_ptr, + const struct bch_extent_ptr *data_ptr, + 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; - if (block >= nr_data) + BUG_ON(!p.has_ec); + + if (p.ec.block >= nr_data) return false; - return ptr->dev == s->ptrs[block].dev && - ptr->gen == s->ptrs[block].gen && - ptr->offset >= s->ptrs[block].offset && - ptr->offset < s->ptrs[block].offset + le16_to_cpu(s->sectors); + return __bch2_ptr_matches_stripe(&s->ptrs[p.ec.block], &p.ptr, + le16_to_cpu(s->sectors)); } -static inline bool bch2_ptr_matches_stripe(const struct bch_stripe *s, - struct extent_ptr_decoded p) +static inline bool bch2_ptr_matches_stripe_m(const struct stripe *m, + struct extent_ptr_decoded p) { + unsigned nr_data = m->nr_blocks - m->nr_redundant; + 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; diff --git a/fs/bcachefs/ec_types.h b/fs/bcachefs/ec_types.h index 847770166223..3fc31222459a 100644 --- a/fs/bcachefs/ec_types.h +++ b/fs/bcachefs/ec_types.h @@ -22,6 +22,7 @@ struct stripe { unsigned on_heap:1; u8 blocks_nonempty; u16 block_sectors[BCH_BKEY_PTRS_MAX]; + struct bch_extent_ptr ptrs[BCH_BKEY_PTRS_MAX]; struct bch_replicas_padded r; }; |