summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2021-04-22 01:08:39 +0300
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-23 00:09:01 +0300
commiteb365fbc333519651bed300eb866f26dbc1efd05 (patch)
treea79177519a4028397667dbb380ca8cf671c2c7cc
parentf09517fc5136ad2ea67b6f332ed2445f053ccfe6 (diff)
downloadlinux-eb365fbc333519651bed300eb866f26dbc1efd05.tar.xz
bcachefs: Don't BUG() in update_replicas
Apparently, we have a bug where in mark and sweep while accounting for a key, a replicas entry isn't found. Change the code to print out the key we couldn't mark and halt instead of a BUG_ON(). Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com> Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r--fs/bcachefs/buckets.c49
1 files changed, 36 insertions, 13 deletions
diff --git a/fs/bcachefs/buckets.c b/fs/bcachefs/buckets.c
index b51f311ad60e..e6e984587b5d 100644
--- a/fs/bcachefs/buckets.c
+++ b/fs/bcachefs/buckets.c
@@ -399,20 +399,22 @@ static void bch2_dev_usage_update(struct bch_fs *c, struct bch_dev *ca,
bch2_wake_allocator(ca);
}
-static inline void update_replicas(struct bch_fs *c,
+static inline int update_replicas(struct bch_fs *c,
struct bch_fs_usage *fs_usage,
struct bch_replicas_entry *r,
s64 sectors)
{
int idx = bch2_replicas_entry_idx(c, r);
- BUG_ON(idx < 0);
+ if (idx < 0)
+ return -1;
fs_usage_data_type_to_base(fs_usage, r->data_type, sectors);
fs_usage->replicas[idx] += sectors;
+ return 0;
}
-static inline void update_cached_sectors(struct bch_fs *c,
+static inline int update_cached_sectors(struct bch_fs *c,
struct bch_fs_usage *fs_usage,
unsigned dev, s64 sectors)
{
@@ -420,7 +422,7 @@ static inline void update_cached_sectors(struct bch_fs *c,
bch2_replicas_entry_cached(&r.e, dev);
- update_replicas(c, fs_usage, &r.e, sectors);
+ return update_replicas(c, fs_usage, &r.e, sectors);
}
static struct replicas_delta_list *
@@ -573,8 +575,12 @@ static int bch2_mark_alloc(struct bch_fs *c,
if ((flags & BTREE_TRIGGER_BUCKET_INVALIDATE) &&
old_m.cached_sectors) {
- update_cached_sectors(c, fs_usage, ca->dev_idx,
- -old_m.cached_sectors);
+ if (update_cached_sectors(c, fs_usage, ca->dev_idx,
+ -old_m.cached_sectors)) {
+ bch2_fs_fatal_error(c, "bch2_mark_alloc(): no replicas entry while updating cached sectors");
+ return -1;
+ }
+
trace_invalidate(ca, bucket_to_sector(ca, new.k->p.offset),
old_m.cached_sectors);
}
@@ -956,8 +962,12 @@ static int bch2_mark_extent(struct bch_fs *c,
if (p.ptr.cached) {
if (!stale)
- update_cached_sectors(c, fs_usage, p.ptr.dev,
- disk_sectors);
+ if (update_cached_sectors(c, fs_usage, p.ptr.dev,
+ disk_sectors)) {
+ bch2_fs_fatal_error(c, "bch2_mark_extent(): no replicas entry while updating cached sectors");
+ return -1;
+
+ }
} else if (!p.has_ec) {
dirty_sectors += disk_sectors;
r.e.devs[r.e.nr_devs++] = p.ptr.dev;
@@ -976,8 +986,15 @@ static int bch2_mark_extent(struct bch_fs *c,
}
}
- if (r.e.nr_devs)
- update_replicas(c, fs_usage, &r.e, dirty_sectors);
+ if (r.e.nr_devs) {
+ if (update_replicas(c, fs_usage, &r.e, dirty_sectors)) {
+ char buf[200];
+
+ bch2_bkey_val_to_text(&PBUF(buf), c, k);
+ bch2_fs_fatal_error(c, "no replicas entry for %s", buf);
+ return -1;
+ }
+ }
return 0;
}
@@ -1051,8 +1068,14 @@ static int bch2_mark_stripe(struct bch_fs *c,
return ret;
}
- update_replicas(c, fs_usage, &m->r.e,
- ((s64) m->sectors * m->nr_redundant));
+ if (update_replicas(c, fs_usage, &m->r.e,
+ ((s64) m->sectors * m->nr_redundant))) {
+ char buf[200];
+
+ bch2_bkey_val_to_text(&PBUF(buf), c, new);
+ bch2_fs_fatal_error(c, "no replicas entry for %s", buf);
+ return -1;
+ }
}
return 0;
@@ -1312,7 +1335,7 @@ void bch2_trans_fs_usage_apply(struct btree_trans *trans,
added += d->delta;
}
- update_replicas(c, dst, &d->r, d->delta);
+ BUG_ON(update_replicas(c, dst, &d->r, d->delta));
}
dst->nr_inodes += deltas->nr_inodes;