diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2023-09-28 17:57:21 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-22 17:10:16 -0400 |
commit | 69d1f052d1675c2af7da496f0265f68673328afb (patch) | |
tree | e064572300707f5719a8dcb8467745540010293c /fs/bcachefs | |
parent | 4fc1f402c6c259b1f44e45c096ac6666925a9b87 (diff) |
bcachefs: Correctly initialize new buckets on device resize
bch2_dev_resize() was never updated for the allocator rewrite with
persistent freelists, and it wasn't noticed because the tests weren't
running fsck - oops.
Fix this by running bch2_dev_freespace_init() for the new buckets.
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs')
-rw-r--r-- | fs/bcachefs/alloc_background.c | 21 | ||||
-rw-r--r-- | fs/bcachefs/alloc_background.h | 1 | ||||
-rw-r--r-- | fs/bcachefs/super.c | 14 |
3 files changed, 27 insertions, 9 deletions
diff --git a/fs/bcachefs/alloc_background.c b/fs/bcachefs/alloc_background.c index 4059d3d4b7f5..2d516207e223 100644 --- a/fs/bcachefs/alloc_background.c +++ b/fs/bcachefs/alloc_background.c @@ -1831,29 +1831,33 @@ void bch2_do_invalidates(struct bch_fs *c) bch2_write_ref_put(c, BCH_WRITE_REF_invalidate); } -static int bch2_dev_freespace_init(struct bch_fs *c, struct bch_dev *ca, - unsigned long *last_updated) +int bch2_dev_freespace_init(struct bch_fs *c, struct bch_dev *ca, + u64 bucket_start, u64 bucket_end) { struct btree_trans *trans = bch2_trans_get(c); struct btree_iter iter; struct bkey_s_c k; struct bkey hole; - struct bpos end = POS(ca->dev_idx, ca->mi.nbuckets); + struct bpos end = POS(ca->dev_idx, bucket_end); struct bch_member *m; + unsigned long last_updated = jiffies; int ret; + BUG_ON(bucket_start > bucket_end); + BUG_ON(bucket_end > ca->mi.nbuckets); + bch2_trans_iter_init(trans, &iter, BTREE_ID_alloc, - POS(ca->dev_idx, ca->mi.first_bucket), - BTREE_ITER_PREFETCH); + POS(ca->dev_idx, max_t(u64, ca->mi.first_bucket, bucket_start)), + BTREE_ITER_PREFETCH); /* * Scan the alloc btree for every bucket on @ca, and add buckets to the * freespace/need_discard/need_gc_gens btrees as needed: */ while (1) { - if (*last_updated + HZ * 10 < jiffies) { + if (last_updated + HZ * 10 < jiffies) { bch_info(ca, "%s: currently at %llu/%llu", __func__, iter.pos.offset, ca->mi.nbuckets); - *last_updated = jiffies; + last_updated = jiffies; } bch2_trans_begin(trans); @@ -1935,7 +1939,6 @@ int bch2_fs_freespace_init(struct bch_fs *c) unsigned i; int ret = 0; bool doing_init = false; - unsigned long last_updated = jiffies; /* * We can crash during the device add path, so we need to check this on @@ -1951,7 +1954,7 @@ int bch2_fs_freespace_init(struct bch_fs *c) doing_init = true; } - ret = bch2_dev_freespace_init(c, ca, &last_updated); + ret = bch2_dev_freespace_init(c, ca, 0, ca->mi.nbuckets); if (ret) { percpu_ref_put(&ca->ref); bch_err_fn(c, ret); diff --git a/fs/bcachefs/alloc_background.h b/fs/bcachefs/alloc_background.h index c0914feb54b5..97042067d2a9 100644 --- a/fs/bcachefs/alloc_background.h +++ b/fs/bcachefs/alloc_background.h @@ -245,6 +245,7 @@ static inline const struct bch_backpointer *alloc_v4_backpointers_c(const struct return (void *) ((u64 *) &a->v + BCH_ALLOC_V4_BACKPOINTERS_START(a)); } +int bch2_dev_freespace_init(struct bch_fs *, struct bch_dev *, u64, u64); int bch2_fs_freespace_init(struct bch_fs *); void bch2_recalc_capacity(struct bch_fs *); diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c index c91c3f7e3328..2014f7816f66 100644 --- a/fs/bcachefs/super.c +++ b/fs/bcachefs/super.c @@ -1808,9 +1808,11 @@ int bch2_dev_offline(struct bch_fs *c, struct bch_dev *ca, int flags) int bch2_dev_resize(struct bch_fs *c, struct bch_dev *ca, u64 nbuckets) { struct bch_member *m; + u64 old_nbuckets; int ret = 0; down_write(&c->state_lock); + old_nbuckets = ca->mi.nbuckets; if (nbuckets < ca->mi.nbuckets) { bch_err(ca, "Cannot shrink yet"); @@ -1843,6 +1845,18 @@ int bch2_dev_resize(struct bch_fs *c, struct bch_dev *ca, u64 nbuckets) bch2_write_super(c); mutex_unlock(&c->sb_lock); + if (ca->mi.freespace_initialized) { + ret = bch2_dev_freespace_init(c, ca, old_nbuckets, nbuckets); + if (ret) + goto err; + + /* + * XXX: this is all wrong transactionally - we'll be able to do + * this correctly after the disk space accounting rewrite + */ + ca->usage_base->d[BCH_DATA_free].buckets += nbuckets - old_nbuckets; + } + bch2_recalc_capacity(c); err: up_write(&c->state_lock); |