Commit 59928c12 authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet

bcachefs: Don't BUG_ON() on bucket sector count overflow

Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 446c562c
...@@ -541,29 +541,40 @@ static int bch2_mark_alloc(struct bch_fs *c, struct bkey_s_c k, ...@@ -541,29 +541,40 @@ static int bch2_mark_alloc(struct bch_fs *c, struct bkey_s_c k,
} }
#define checked_add(a, b) \ #define checked_add(a, b) \
do { \ ({ \
unsigned _res = (unsigned) (a) + (b); \ unsigned _res = (unsigned) (a) + (b); \
bool overflow = _res > U16_MAX; \
if (overflow) \
_res = U16_MAX; \
(a) = _res; \ (a) = _res; \
BUG_ON((a) != _res); \ overflow; \
} while (0) })
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 type,
unsigned sectors, bool gc) unsigned sectors, bool gc)
{ {
struct bch_fs_usage *fs_usage = this_cpu_ptr(c->usage[gc]);
struct bucket *g = __bucket(ca, b, gc); struct bucket *g = __bucket(ca, b, gc);
struct bucket_mark new; struct bucket_mark old, new;
bool overflow;
BUG_ON(type != BCH_DATA_SB && BUG_ON(type != BCH_DATA_SB &&
type != BCH_DATA_JOURNAL); type != BCH_DATA_JOURNAL);
bucket_data_cmpxchg(c, ca, fs_usage, g, new, ({ old = bucket_cmpxchg(g, new, ({
new.dirty = true; new.dirty = true;
new.data_type = type; new.data_type = type;
checked_add(new.dirty_sectors, sectors); overflow = checked_add(new.dirty_sectors, sectors);
})); }));
bch2_fs_inconsistent_on(overflow, c,
"bucket sector count overflow: %u + %u > U16_MAX",
old.dirty_sectors, sectors);
if (c)
bch2_dev_usage_update(c, ca, this_cpu_ptr(c->usage[gc]),
old, new, gc);
return 0; return 0;
} }
...@@ -581,19 +592,7 @@ void bch2_mark_metadata_bucket(struct bch_fs *c, struct bch_dev *ca, ...@@ -581,19 +592,7 @@ void bch2_mark_metadata_bucket(struct bch_fs *c, struct bch_dev *ca,
do_mark_fn(__bch2_mark_metadata_bucket, c, pos, flags, do_mark_fn(__bch2_mark_metadata_bucket, c, pos, flags,
ca, b, type, sectors); ca, b, type, sectors);
} else { } else {
struct bucket *g; __bch2_mark_metadata_bucket(c, ca, b, type, sectors, 0);
struct bucket_mark new;
rcu_read_lock();
g = bucket(ca, b);
bucket_cmpxchg(g, new, ({
new.dirty = true;
new.data_type = type;
checked_add(new.dirty_sectors, sectors);
}));
rcu_read_unlock();
} }
preempt_enable(); preempt_enable();
...@@ -636,6 +635,7 @@ static bool bch2_mark_pointer(struct bch_fs *c, ...@@ -636,6 +635,7 @@ static bool bch2_mark_pointer(struct bch_fs *c,
struct bch_dev *ca = bch_dev_bkey_exists(c, p.ptr.dev); struct bch_dev *ca = bch_dev_bkey_exists(c, p.ptr.dev);
size_t b = PTR_BUCKET_NR(ca, &p.ptr); size_t b = PTR_BUCKET_NR(ca, &p.ptr);
struct bucket *g = __bucket(ca, b, gc); struct bucket *g = __bucket(ca, b, gc);
bool overflow;
u64 v; u64 v;
v = atomic64_read(&g->_mark.v); v = atomic64_read(&g->_mark.v);
...@@ -657,9 +657,9 @@ static bool bch2_mark_pointer(struct bch_fs *c, ...@@ -657,9 +657,9 @@ static bool bch2_mark_pointer(struct bch_fs *c,
} }
if (!p.ptr.cached) if (!p.ptr.cached)
checked_add(new.dirty_sectors, sectors); overflow = checked_add(new.dirty_sectors, sectors);
else else
checked_add(new.cached_sectors, sectors); overflow = checked_add(new.cached_sectors, sectors);
if (!new.dirty_sectors && if (!new.dirty_sectors &&
!new.cached_sectors) { !new.cached_sectors) {
...@@ -681,6 +681,12 @@ static bool bch2_mark_pointer(struct bch_fs *c, ...@@ -681,6 +681,12 @@ static bool bch2_mark_pointer(struct bch_fs *c,
old.v.counter, old.v.counter,
new.v.counter)) != old.v.counter); new.v.counter)) != old.v.counter);
bch2_fs_inconsistent_on(overflow, c,
"bucket sector count overflow: %u + %lli > U16_MAX",
!p.ptr.cached
? old.dirty_sectors
: old.cached_sectors, sectors);
bch2_dev_usage_update(c, ca, fs_usage, old, new, gc); bch2_dev_usage_update(c, ca, fs_usage, old, new, gc);
BUG_ON(!gc && bucket_became_unavailable(old, new)); BUG_ON(!gc && bucket_became_unavailable(old, new));
......
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