summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2021-03-12 16:55:28 -0500
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:08:55 -0400
commitb3b66e30445e42a94fa171fad99e0b4e4e43c1ac (patch)
treee2a425848894d9e0fddd1b740e72d8ceb1cd62a9 /fs
parent53b3e3c0e2f14f661cd61bbc9b82dc9383f783b9 (diff)
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>
Diffstat (limited to 'fs')
-rw-r--r--fs/bcachefs/btree_gc.c21
-rw-r--r--fs/bcachefs/buckets.c2
-rw-r--r--fs/bcachefs/ec.c3
-rw-r--r--fs/bcachefs/ec.h37
-rw-r--r--fs/bcachefs/ec_types.h1
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;
};