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

bcachefs: Better error messages on bucket sector count overflows

Signed-off-by: default avatarKent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 2340fd9d
...@@ -581,8 +581,10 @@ static int bch2_gc_done(struct bch_fs *c, ...@@ -581,8 +581,10 @@ static int bch2_gc_done(struct bch_fs *c,
#define copy_bucket_field(_f) \ #define copy_bucket_field(_f) \
if (dst->b[b].mark._f != src->b[b].mark._f) { \ if (dst->b[b].mark._f != src->b[b].mark._f) { \
if (verify) \ if (verify) \
fsck_err(c, "dev %u bucket %zu has wrong " #_f \ fsck_err(c, "bucket %u:%zu gen %u data type %s has wrong " #_f \
": got %u, should be %u", i, b, \ ": got %u, should be %u", i, b, \
dst->b[b].mark.gen, \
bch2_data_types[dst->b[b].mark.data_type],\
dst->b[b].mark._f, src->b[b].mark._f); \ dst->b[b].mark._f, src->b[b].mark._f); \
dst->b[b]._mark._f = src->b[b].mark._f; \ dst->b[b]._mark._f = src->b[b].mark._f; \
} }
......
...@@ -778,29 +778,31 @@ static int bch2_mark_alloc(struct bch_fs *c, struct bkey_s_c k, ...@@ -778,29 +778,31 @@ static int bch2_mark_alloc(struct bch_fs *c, struct bkey_s_c k,
}) })
static int __bch2_mark_metadata_bucket(struct bch_fs *c, struct bch_dev *ca, static int __bch2_mark_metadata_bucket(struct bch_fs *c, struct bch_dev *ca,
size_t b, enum bch_data_type type, size_t b, enum bch_data_type data_type,
unsigned sectors, bool gc) unsigned sectors, bool gc)
{ {
struct bucket *g = __bucket(ca, b, gc); struct bucket *g = __bucket(ca, b, gc);
struct bucket_mark old, new; struct bucket_mark old, new;
bool overflow; bool overflow;
BUG_ON(type != BCH_DATA_SB && BUG_ON(data_type != BCH_DATA_SB &&
type != BCH_DATA_JOURNAL); data_type != BCH_DATA_JOURNAL);
old = bucket_cmpxchg(g, new, ({ old = bucket_cmpxchg(g, new, ({
new.data_type = type; new.data_type = data_type;
overflow = checked_add(new.dirty_sectors, sectors); overflow = checked_add(new.dirty_sectors, sectors);
})); }));
bch2_fs_inconsistent_on(old.data_type && bch2_fs_inconsistent_on(old.data_type &&
old.data_type != type, c, old.data_type != data_type, c,
"different types of data in same bucket: %s, %s", "different types of data in same bucket: %s, %s",
bch2_data_types[old.data_type], bch2_data_types[old.data_type],
bch2_data_types[type]); bch2_data_types[data_type]);
bch2_fs_inconsistent_on(overflow, c, bch2_fs_inconsistent_on(overflow, c,
"bucket sector count overflow: %u + %u > U16_MAX", "bucket %u:%zu gen %u data type %s sector count overflow: %u + %u > U16_MAX",
ca->dev_idx, b, new.gen,
bch2_data_types[old.data_type ?: data_type],
old.dirty_sectors, sectors); old.dirty_sectors, sectors);
if (c) if (c)
...@@ -926,6 +928,7 @@ static bool bch2_mark_pointer(struct bch_fs *c, ...@@ -926,6 +928,7 @@ static bool bch2_mark_pointer(struct bch_fs *c,
struct bucket_mark old, new; struct bucket_mark old, new;
struct bch_dev *ca = bch_dev_bkey_exists(c, p.ptr.dev); struct bch_dev *ca = bch_dev_bkey_exists(c, p.ptr.dev);
struct bucket *g = PTR_BUCKET(ca, &p.ptr, gc); struct bucket *g = PTR_BUCKET(ca, &p.ptr, gc);
u16 *dst_sectors, orig_sectors;
bool overflow; bool overflow;
u64 v; u64 v;
...@@ -953,10 +956,12 @@ static bool bch2_mark_pointer(struct bch_fs *c, ...@@ -953,10 +956,12 @@ static bool bch2_mark_pointer(struct bch_fs *c,
return true; return true;
} }
if (!p.ptr.cached) dst_sectors = !p.ptr.cached
overflow = checked_add(new.dirty_sectors, sectors); ? &new.dirty_sectors
else : &new.cached_sectors;
overflow = checked_add(new.cached_sectors, sectors); orig_sectors = *dst_sectors;
overflow = checked_add(*dst_sectors, sectors);
if (!new.dirty_sectors && if (!new.dirty_sectors &&
!new.cached_sectors) { !new.cached_sectors) {
...@@ -987,10 +992,10 @@ static bool bch2_mark_pointer(struct bch_fs *c, ...@@ -987,10 +992,10 @@ static bool bch2_mark_pointer(struct bch_fs *c,
bch2_data_types[data_type]); bch2_data_types[data_type]);
bch2_fs_inconsistent_on(overflow, c, bch2_fs_inconsistent_on(overflow, c,
"bucket sector count overflow: %u + %lli > U16_MAX", "bucket %u:%zu gen %u data type %s sector count overflow: %u + %lli > U16_MAX",
!p.ptr.cached p.ptr.dev, PTR_BUCKET_NR(ca, &p.ptr), new.gen,
? old.dirty_sectors bch2_data_types[old.data_type ?: data_type],
: old.cached_sectors, sectors); orig_sectors, sectors);
bch2_dev_usage_update(c, ca, fs_usage, old, new, gc); bch2_dev_usage_update(c, ca, fs_usage, old, new, gc);
...@@ -1504,7 +1509,9 @@ static int bch2_trans_mark_pointer(struct btree_trans *trans, ...@@ -1504,7 +1509,9 @@ static int bch2_trans_mark_pointer(struct btree_trans *trans,
if (checked_add(*dst_sectors, sectors)) { if (checked_add(*dst_sectors, sectors)) {
bch2_fs_inconsistent(c, bch2_fs_inconsistent(c,
"bucket sector count overflow: %u + %lli > U16_MAX", "bucket %llu:%llu gen %u data type %s sector count overflow: %u + %lli > U16_MAX",
iter->pos.inode, iter->pos.offset, u.gen,
bch2_data_types[u.data_type ?: data_type],
orig_sectors, sectors); orig_sectors, sectors);
/* return an error indicating that we need full fsck */ /* return an error indicating that we need full fsck */
ret = -EIO; ret = -EIO;
......
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