]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
bcachefs: Correctly initialize new buckets on device resize
authorKent Overstreet <kent.overstreet@linux.dev>
Thu, 28 Sep 2023 21:57:21 +0000 (17:57 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:10:16 +0000 (17:10 -0400)
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>
fs/bcachefs/alloc_background.c
fs/bcachefs/alloc_background.h
fs/bcachefs/super.c

index 4059d3d4b7f519591ded54557320f4ec29b7e573..2d516207e223f097d75c056288620297bfcbedb6 100644 (file)
@@ -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);
index c0914feb54b5faecaca91dbb845880456947a84f..97042067d2a960e32f586b5686f4e30490cf0974 100644 (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));
 }
 
+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 *);
index c91c3f7e332805d8efaf4ada66c53b9c16df8d5e..2014f7816f6679fd7436b33252cdfd3686618de2 100644 (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)
 {
        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);