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,
}
#define checked_add(a, b) \
do { \
({ \
unsigned _res = (unsigned) (a) + (b); \
bool overflow = _res > U16_MAX; \
if (overflow) \
_res = U16_MAX; \
(a) = _res; \
BUG_ON((a) != _res); \
} while (0)
overflow; \
})
static int __bch2_mark_metadata_bucket(struct bch_fs *c, struct bch_dev *ca,
size_t b, enum bch_data_type type,
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_mark new;
struct bucket_mark old, new;
bool overflow;
BUG_ON(type != BCH_DATA_SB &&
type != BCH_DATA_JOURNAL);
bucket_data_cmpxchg(c, ca, fs_usage, g, new, ({
old = bucket_cmpxchg(g, new, ({
new.dirty = true;
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;
}
......@@ -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,
ca, b, type, sectors);
} else {
struct bucket *g;
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();
__bch2_mark_metadata_bucket(c, ca, b, type, sectors, 0);
}
preempt_enable();
......@@ -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);
size_t b = PTR_BUCKET_NR(ca, &p.ptr);
struct bucket *g = __bucket(ca, b, gc);
bool overflow;
u64 v;
v = atomic64_read(&g->_mark.v);
......@@ -657,9 +657,9 @@ static bool bch2_mark_pointer(struct bch_fs *c,
}
if (!p.ptr.cached)
checked_add(new.dirty_sectors, sectors);
overflow = checked_add(new.dirty_sectors, sectors);
else
checked_add(new.cached_sectors, sectors);
overflow = checked_add(new.cached_sectors, sectors);
if (!new.dirty_sectors &&
!new.cached_sectors) {
......@@ -681,6 +681,12 @@ static bool bch2_mark_pointer(struct bch_fs *c,
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);
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