mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 10:04:04 +02:00
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:
parent
4fc1f402c6
commit
69d1f052d1
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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 *);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user