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>
This commit is contained in:
Kent Overstreet 2023-09-28 17:57:21 -04:00
parent 4fc1f402c6
commit 69d1f052d1
3 changed files with 27 additions and 9 deletions

View File

@ -1831,29 +1831,33 @@ void bch2_do_invalidates(struct bch_fs *c)
bch2_write_ref_put(c, BCH_WRITE_REF_invalidate); bch2_write_ref_put(c, BCH_WRITE_REF_invalidate);
} }
static int bch2_dev_freespace_init(struct bch_fs *c, struct bch_dev *ca, int bch2_dev_freespace_init(struct bch_fs *c, struct bch_dev *ca,
unsigned long *last_updated) u64 bucket_start, u64 bucket_end)
{ {
struct btree_trans *trans = bch2_trans_get(c); struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
struct bkey hole; 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; struct bch_member *m;
unsigned long last_updated = jiffies;
int ret; int ret;
BUG_ON(bucket_start > bucket_end);
BUG_ON(bucket_end > ca->mi.nbuckets);
bch2_trans_iter_init(trans, &iter, BTREE_ID_alloc, bch2_trans_iter_init(trans, &iter, BTREE_ID_alloc,
POS(ca->dev_idx, ca->mi.first_bucket), POS(ca->dev_idx, max_t(u64, ca->mi.first_bucket, bucket_start)),
BTREE_ITER_PREFETCH); BTREE_ITER_PREFETCH);
/* /*
* Scan the alloc btree for every bucket on @ca, and add buckets to the * Scan the alloc btree for every bucket on @ca, and add buckets to the
* freespace/need_discard/need_gc_gens btrees as needed: * freespace/need_discard/need_gc_gens btrees as needed:
*/ */
while (1) { while (1) {
if (*last_updated + HZ * 10 < jiffies) { if (last_updated + HZ * 10 < jiffies) {
bch_info(ca, "%s: currently at %llu/%llu", bch_info(ca, "%s: currently at %llu/%llu",
__func__, iter.pos.offset, ca->mi.nbuckets); __func__, iter.pos.offset, ca->mi.nbuckets);
*last_updated = jiffies; last_updated = jiffies;
} }
bch2_trans_begin(trans); bch2_trans_begin(trans);
@ -1935,7 +1939,6 @@ int bch2_fs_freespace_init(struct bch_fs *c)
unsigned i; unsigned i;
int ret = 0; int ret = 0;
bool doing_init = false; bool doing_init = false;
unsigned long last_updated = jiffies;
/* /*
* We can crash during the device add path, so we need to check this on * 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; 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) { if (ret) {
percpu_ref_put(&ca->ref); percpu_ref_put(&ca->ref);
bch_err_fn(c, ret); bch_err_fn(c, ret);

View File

@ -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)); 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 *); int bch2_fs_freespace_init(struct bch_fs *);
void bch2_recalc_capacity(struct bch_fs *); void bch2_recalc_capacity(struct bch_fs *);

View File

@ -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) int bch2_dev_resize(struct bch_fs *c, struct bch_dev *ca, u64 nbuckets)
{ {
struct bch_member *m; struct bch_member *m;
u64 old_nbuckets;
int ret = 0; int ret = 0;
down_write(&c->state_lock); down_write(&c->state_lock);
old_nbuckets = ca->mi.nbuckets;
if (nbuckets < ca->mi.nbuckets) { if (nbuckets < ca->mi.nbuckets) {
bch_err(ca, "Cannot shrink yet"); 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); bch2_write_super(c);
mutex_unlock(&c->sb_lock); 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); bch2_recalc_capacity(c);
err: err:
up_write(&c->state_lock); up_write(&c->state_lock);