bcachefs: Handle replica marking fsck errors locally
authorKent Overstreet <kent.overstreet@gmail.com>
Sun, 28 Nov 2021 20:13:54 +0000 (15:13 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:18 +0000 (17:09 -0400)
This simplifies the code quite a bit and eliminates an inconsistency - a
given bkey doesn't necessarily translate to a single replicas entry for
disk space accounting.

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

index a6cba09dae3ecd2fb3a9acb32b95b0d001e1cc91..b692451f91b58e8560569972b03c6f65895e7bdc 100644 (file)
@@ -715,7 +715,6 @@ static int bch2_gc_mark_key(struct btree_trans *trans, enum btree_id btree_id,
        unsigned flags =
                BTREE_TRIGGER_GC|
                (initial ? BTREE_TRIGGER_NOATOMIC : 0);
-       char buf[200];
        int ret = 0;
 
        deleted.p = k->k->p;
@@ -733,18 +732,6 @@ static int bch2_gc_mark_key(struct btree_trans *trans, enum btree_id btree_id,
                                k->k->version.lo,
                                atomic64_read(&c->key_version)))
                        atomic64_set(&c->key_version, k->k->version.lo);
-
-               if (test_bit(BCH_FS_REBUILD_REPLICAS, &c->flags) ||
-                   fsck_err_on(!bch2_bkey_replicas_marked(c, *k), c,
-                               "superblock not marked as containing replicas\n"
-                               "  while marking %s",
-                               (bch2_bkey_val_to_text(&PBUF(buf), c, *k), buf))) {
-                       ret = bch2_mark_bkey_replicas(c, *k);
-                       if (ret) {
-                               bch_err(c, "error marking bkey replicas: %i", ret);
-                               goto err;
-                       }
-               }
        }
 
        ptrs = bch2_bkey_ptrs_c(*k);
index 78a134d5e63ba702d3a050580c4a90dd22920863..c4d72a49995531f7e0dff06cb2e7cb2e94a48813 100644 (file)
@@ -420,16 +420,30 @@ static inline int __update_replicas(struct bch_fs *c,
        return 0;
 }
 
-static inline int update_replicas(struct bch_fs *c,
+static inline int update_replicas(struct bch_fs *c, struct bkey_s_c k,
                        struct bch_replicas_entry *r, s64 sectors,
                        unsigned journal_seq, bool gc)
 {
        struct bch_fs_usage __percpu *fs_usage;
        int idx, ret = 0;
+       char buf[200];
 
        percpu_down_read(&c->mark_lock);
 
        idx = bch2_replicas_entry_idx(c, r);
+       if (idx < 0 &&
+           (test_bit(BCH_FS_REBUILD_REPLICAS, &c->flags) ||
+            fsck_err(c, "no replicas entry\n"
+                     "  while marking %s",
+                     (bch2_bkey_val_to_text(&PBUF(buf), c, k), buf)))) {
+               percpu_up_read(&c->mark_lock);
+               ret = bch2_mark_replicas(c, r);
+               if (ret)
+                       return ret;
+
+               percpu_down_read(&c->mark_lock);
+               idx = bch2_replicas_entry_idx(c, r);
+       }
        if (idx < 0) {
                ret = -1;
                goto err;
@@ -441,11 +455,13 @@ static inline int update_replicas(struct bch_fs *c,
        fs_usage->replicas[idx]         += sectors;
        preempt_enable();
 err:
+fsck_err:
        percpu_up_read(&c->mark_lock);
        return ret;
 }
 
 static inline int update_cached_sectors(struct bch_fs *c,
+                       struct bkey_s_c k,
                        unsigned dev, s64 sectors,
                        unsigned journal_seq, bool gc)
 {
@@ -453,7 +469,7 @@ static inline int update_cached_sectors(struct bch_fs *c,
 
        bch2_replicas_entry_cached(&r.e, dev);
 
-       return update_replicas(c, &r.e, sectors, journal_seq, gc);
+       return update_replicas(c, k, &r.e, sectors, journal_seq, gc);
 }
 
 static struct replicas_delta_list *
@@ -618,8 +634,9 @@ static int bch2_mark_alloc(struct btree_trans *trans,
 
        if ((flags & BTREE_TRIGGER_BUCKET_INVALIDATE) &&
            old_m.cached_sectors) {
-               ret = update_cached_sectors(c, ca->dev_idx, -old_m.cached_sectors,
-                                         journal_seq, gc);
+               ret = update_cached_sectors(c, new, ca->dev_idx,
+                                           -old_m.cached_sectors,
+                                           journal_seq, gc);
                if (ret) {
                        bch2_fs_fatal_error(c, "bch2_mark_alloc(): no replicas entry while updating cached sectors");
                        return ret;
@@ -920,6 +937,7 @@ err:
 }
 
 static int bch2_mark_stripe_ptr(struct btree_trans *trans,
+                               struct bkey_s_c k,
                                struct bch_extent_stripe_ptr p,
                                enum bch_data_type data_type,
                                s64 sectors,
@@ -959,7 +977,7 @@ static int bch2_mark_stripe_ptr(struct btree_trans *trans,
        spin_unlock(&c->ec_stripes_heap_lock);
 
        r.e.data_type = data_type;
-       update_replicas(c, &r.e, sectors, trans->journal_res.seq, gc);
+       update_replicas(c, k, &r.e, sectors, trans->journal_res.seq, gc);
 
        return 0;
 }
@@ -1005,8 +1023,8 @@ static int bch2_mark_extent(struct btree_trans *trans,
 
                if (p.ptr.cached) {
                        if (!stale) {
-                               ret = update_cached_sectors(c, p.ptr.dev, disk_sectors,
-                                                           journal_seq, gc);
+                               ret = update_cached_sectors(c, k, p.ptr.dev,
+                                               disk_sectors, journal_seq, gc);
                                if (ret) {
                                        bch2_fs_fatal_error(c, "bch2_mark_extent(): no replicas entry while updating cached sectors");
                                        return ret;
@@ -1016,7 +1034,7 @@ static int bch2_mark_extent(struct btree_trans *trans,
                        dirty_sectors          += disk_sectors;
                        r.e.devs[r.e.nr_devs++] = p.ptr.dev;
                } else {
-                       ret = bch2_mark_stripe_ptr(trans, p.ec, data_type,
+                       ret = bch2_mark_stripe_ptr(trans, k, p.ec, data_type,
                                        disk_sectors, flags);
                        if (ret)
                                return ret;
@@ -1031,7 +1049,7 @@ static int bch2_mark_extent(struct btree_trans *trans,
        }
 
        if (r.e.nr_devs) {
-               ret = update_replicas(c, &r.e, dirty_sectors, journal_seq, gc);
+               ret = update_replicas(c, k, &r.e, dirty_sectors, journal_seq, gc);
                if (ret) {
                        char buf[200];
 
@@ -1119,7 +1137,7 @@ static int bch2_mark_stripe(struct btree_trans *trans,
                                return ret;
                }
 
-               ret = update_replicas(c, &m->r.e,
+               ret = update_replicas(c, new, &m->r.e,
                                      ((s64) m->sectors * m->nr_redundant),
                                      journal_seq, gc);
                if (ret) {
index 9bfe7fa51d32fcf83efa61a41b05e71c3a41e572..33bba6fdb180bf090730e7412e486c331555e493 100644 (file)
@@ -434,45 +434,6 @@ int bch2_mark_replicas(struct bch_fs *c, struct bch_replicas_entry *r)
        return __bch2_mark_replicas(c, r, false);
 }
 
-static int __bch2_mark_bkey_replicas(struct bch_fs *c, struct bkey_s_c k,
-                                    bool check)
-{
-       struct bch_replicas_padded search;
-       struct bch_devs_list cached = bch2_bkey_cached_devs(k);
-       unsigned i;
-       int ret;
-
-       memset(&search, 0, sizeof(search));
-
-       for (i = 0; i < cached.nr; i++) {
-               bch2_replicas_entry_cached(&search.e, cached.devs[i]);
-
-               ret = __bch2_mark_replicas(c, &search.e, check);
-               if (ret)
-                       return ret;
-       }
-
-       bch2_bkey_to_replicas(&search.e, k);
-
-       ret = __bch2_mark_replicas(c, &search.e, check);
-       if (ret)
-               return ret;
-
-       if (search.e.data_type == BCH_DATA_parity) {
-               search.e.data_type = BCH_DATA_cached;
-               ret = __bch2_mark_replicas(c, &search.e, check);
-               if (ret)
-                       return ret;
-
-               search.e.data_type = BCH_DATA_user;
-               ret = __bch2_mark_replicas(c, &search.e, check);
-               if (ret)
-                       return ret;
-       }
-
-       return 0;
-}
-
 /* replicas delta list: */
 
 int bch2_replicas_delta_list_mark(struct bch_fs *c,
@@ -487,19 +448,6 @@ int bch2_replicas_delta_list_mark(struct bch_fs *c,
        return ret;
 }
 
-/* bkey replicas: */
-
-bool bch2_bkey_replicas_marked(struct bch_fs *c,
-                              struct bkey_s_c k)
-{
-       return __bch2_mark_bkey_replicas(c, k, true) == 0;
-}
-
-int bch2_mark_bkey_replicas(struct bch_fs *c, struct bkey_s_c k)
-{
-       return __bch2_mark_bkey_replicas(c, k, false);
-}
-
 /*
  * Old replicas_gc mechanism: only used for journal replicas entries now, should
  * die at some point:
index 66ca88deb0c0cc428fb5cc573be247f07276c8b0..d237d7c51ccb9b9faa771e72ba123fb505914c16 100644 (file)
@@ -51,8 +51,6 @@ replicas_delta_next(struct replicas_delta *d)
 int bch2_replicas_delta_list_mark(struct bch_fs *, struct replicas_delta_list *);
 
 void bch2_bkey_to_replicas(struct bch_replicas_entry *, struct bkey_s_c);
-bool bch2_bkey_replicas_marked(struct bch_fs *, struct bkey_s_c);
-int bch2_mark_bkey_replicas(struct bch_fs *, struct bkey_s_c);
 
 static inline void bch2_replicas_entry_cached(struct bch_replicas_entry *e,
                                              unsigned dev)