]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
bcachefs: gc mark fn fixes, cleanups
authorKent Overstreet <kent.overstreet@gmail.com>
Sat, 2 Apr 2022 22:00:04 +0000 (18:00 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:30 +0000 (17:09 -0400)
mark_stripe_bucket() was busted; it was using @new unitialized.

Also, clean up all the gc mark functions, and convert them to the same
style.

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
fs/bcachefs/buckets.c
fs/bcachefs/buckets.h

index dcb2ea3de4b8e7c7a3185c1c41661859b7a58793..5b78e8f983a1fbb02d418ebbc9905d87ee2920db 100644 (file)
@@ -624,13 +624,13 @@ int bch2_mark_alloc(struct btree_trans *trans,
        return 0;
 }
 
-void bch2_mark_metadata_bucket(struct bch_fs *c, struct bch_dev *ca,
-                              size_t b, enum bch_data_type data_type,
-                              unsigned sectors, struct gc_pos pos,
-                              unsigned flags)
+int bch2_mark_metadata_bucket(struct bch_fs *c, struct bch_dev *ca,
+                             size_t b, enum bch_data_type data_type,
+                             unsigned sectors, struct gc_pos pos,
+                             unsigned flags)
 {
        struct bucket old, new, *g;
-       bool overflow;
+       int ret = 0;
 
        BUG_ON(!(flags & BTREE_TRIGGER_GC));
        BUG_ON(data_type != BCH_DATA_sb &&
@@ -640,7 +640,7 @@ void bch2_mark_metadata_bucket(struct bch_fs *c, struct bch_dev *ca,
         * Backup superblock might be past the end of our normal usable space:
         */
        if (b >= ca->mi.nbuckets)
-               return;
+               return 0;
 
        percpu_down_read(&c->mark_lock);
        g = gc_bucket(ca, b);
@@ -648,27 +648,34 @@ void bch2_mark_metadata_bucket(struct bch_fs *c, struct bch_dev *ca,
        bucket_lock(g);
        old = *g;
 
+       if (bch2_fs_inconsistent_on(g->data_type &&
+                       g->data_type != data_type, c,
+                       "different types of data in same bucket: %s, %s",
+                       bch2_data_types[g->data_type],
+                       bch2_data_types[data_type])) {
+               ret = -EIO;
+               goto err;
+       }
+
+       if (bch2_fs_inconsistent_on((u64) g->dirty_sectors + sectors > ca->mi.bucket_size, c,
+                       "bucket %u:%zu gen %u data type %s sector count overflow: %u + %u > bucket size",
+                       ca->dev_idx, b, g->gen,
+                       bch2_data_types[g->data_type ?: data_type],
+                       g->dirty_sectors, sectors)) {
+               ret = -EIO;
+               goto err;
+       }
+
+
        g->data_type = data_type;
        g->dirty_sectors += sectors;
-       overflow = g->dirty_sectors < sectors;
-
        new = *g;
+err:
        bucket_unlock(g);
-
-       bch2_fs_inconsistent_on(old.data_type &&
-                               old.data_type != data_type, c,
-               "different types of data in same bucket: %s, %s",
-               bch2_data_types[old.data_type],
-               bch2_data_types[data_type]);
-
-       bch2_fs_inconsistent_on(overflow, c,
-               "bucket %u:%zu gen %u data type %s sector count overflow: %u + %u > U16_MAX",
-               ca->dev_idx, b, new.gen,
-               bch2_data_types[old.data_type ?: data_type],
-               old.dirty_sectors, sectors);
-
-       bch2_dev_usage_update_m(c, ca, old, new, 0, true);
+       if (!ret)
+               bch2_dev_usage_update_m(c, ca, old, new, 0, true);
        percpu_up_read(&c->mark_lock);
+       return ret;
 }
 
 static s64 ptr_disk_sectors(s64 sectors, struct extent_ptr_decoded p)
@@ -811,25 +818,22 @@ static int mark_stripe_bucket(struct btree_trans *trans,
        old = *g;
 
        ret = check_bucket_ref(c, k, ptr, sectors, data_type,
-                              new.gen, new.data_type,
-                              new.dirty_sectors, new.cached_sectors);
-       if (ret) {
-               bucket_unlock(g);
+                              g->gen, g->data_type,
+                              g->dirty_sectors, g->cached_sectors);
+       if (ret)
                goto err;
-       }
 
-       new.dirty_sectors += sectors;
        if (data_type)
-               new.data_type = data_type;
+               g->data_type = data_type;
+       g->dirty_sectors += sectors;
 
        g->stripe               = k.k->p.offset;
        g->stripe_redundancy    = s->nr_redundant;
-
        new = *g;
-       bucket_unlock(g);
-
-       bch2_dev_usage_update_m(c, ca, old, new, journal_seq, true);
 err:
+       bucket_unlock(g);
+       if (!ret)
+               bch2_dev_usage_update_m(c, ca, old, new, journal_seq, true);
        percpu_up_read(&c->mark_lock);
        printbuf_exit(&buf);
        return ret;
@@ -875,29 +879,22 @@ static int bch2_mark_pointer(struct btree_trans *trans,
 
        percpu_down_read(&c->mark_lock);
        g = PTR_GC_BUCKET(ca, &p.ptr);
-
        bucket_lock(g);
        old = *g;
 
        bucket_data_type = g->data_type;
-
        ret = __mark_pointer(trans, k, &p.ptr, sectors,
                             data_type, g->gen,
                             &bucket_data_type,
                             &g->dirty_sectors,
                             &g->cached_sectors);
-       if (ret) {
-               bucket_unlock(g);
-               goto err;
-       }
-
-       g->data_type = bucket_data_type;
+       if (!ret)
+               g->data_type = bucket_data_type;
 
        new = *g;
        bucket_unlock(g);
-
-       bch2_dev_usage_update_m(c, ca, old, new, journal_seq, true);
-err:
+       if (!ret)
+               bch2_dev_usage_update_m(c, ca, old, new, journal_seq, true);
        percpu_up_read(&c->mark_lock);
 
        return ret;
index 31a56f1f4fcaa3fddc96f474170cc571ab3a5dd8..4675a1f5d189921d514c80410291552c309d7212 100644 (file)
@@ -194,9 +194,9 @@ bch2_fs_usage_read_short(struct bch_fs *);
 
 void bch2_fs_usage_initialize(struct bch_fs *);
 
-void bch2_mark_metadata_bucket(struct bch_fs *, struct bch_dev *,
-                              size_t, enum bch_data_type, unsigned,
-                              struct gc_pos, unsigned);
+int bch2_mark_metadata_bucket(struct bch_fs *, struct bch_dev *,
+                             size_t, enum bch_data_type, unsigned,
+                             struct gc_pos, unsigned);
 
 int bch2_mark_alloc(struct btree_trans *, struct bkey_s_c, struct bkey_s_c, unsigned);
 int bch2_mark_extent(struct btree_trans *, struct bkey_s_c, struct bkey_s_c, unsigned);