bcachefs: Redo replicas gc mechanism
authorKent Overstreet <kent.overstreet@gmail.com>
Tue, 30 Apr 2019 21:15:39 +0000 (17:15 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:08:21 +0000 (17:08 -0400)
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/migrate.c
fs/bcachefs/move.c
fs/bcachefs/replicas.c
fs/bcachefs/replicas.h

index f9e6c9d9ef046ea564f0bb35cbf972d4dd155642..6b17d7918aa4b90be430ac2e5e0fc812bdf2aa07 100644 (file)
@@ -48,10 +48,6 @@ static int bch2_dev_usrdata_drop(struct bch_fs *c, unsigned dev_idx, int flags)
        iter = bch2_trans_get_iter(&trans, BTREE_ID_EXTENTS,
                                   POS_MIN, BTREE_ITER_PREFETCH);
 
-       mutex_lock(&c->replicas_gc_lock);
-       bch2_replicas_gc_start(c, (1 << BCH_DATA_USER)|(1 << BCH_DATA_CACHED));
-
-
        while ((k = bch2_btree_iter_peek(iter)).k &&
               !(ret = bkey_err(k))) {
                if (!bkey_extent_is_data(k.k) ||
@@ -97,12 +93,9 @@ static int bch2_dev_usrdata_drop(struct bch_fs *c, unsigned dev_idx, int flags)
                        break;
        }
 
-       BUG_ON(ret == -EINTR);
-
-       bch2_trans_exit(&trans);
+       ret = bch2_trans_exit(&trans) ?: ret;
 
-       bch2_replicas_gc_end(c, ret);
-       mutex_unlock(&c->replicas_gc_lock);
+       BUG_ON(ret == -EINTR);
 
        return ret;
 }
@@ -123,9 +116,6 @@ static int bch2_dev_metadata_drop(struct bch_fs *c, unsigned dev_idx, int flags)
        bch2_trans_init(&trans, c);
        closure_init_stack(&cl);
 
-       mutex_lock(&c->replicas_gc_lock);
-       bch2_replicas_gc_start(c, 1 << BCH_DATA_BTREE);
-
        for (id = 0; id < BTREE_ID_NR; id++) {
                for_each_btree_node(&trans, iter, id, POS_MIN,
                                    BTREE_ITER_PREFETCH, b) {
@@ -178,10 +168,9 @@ retry:
 
        ret = 0;
 err:
-       bch2_trans_exit(&trans);
+       ret = bch2_trans_exit(&trans) ?: ret;
 
-       ret = bch2_replicas_gc_end(c, ret);
-       mutex_unlock(&c->replicas_gc_lock);
+       BUG_ON(ret == -EINTR);
 
        return ret;
 }
@@ -189,5 +178,6 @@ err:
 int bch2_dev_data_drop(struct bch_fs *c, unsigned dev_idx, int flags)
 {
        return bch2_dev_usrdata_drop(c, dev_idx, flags) ?:
-               bch2_dev_metadata_drop(c, dev_idx, flags);
+               bch2_dev_metadata_drop(c, dev_idx, flags) ?:
+               bch2_replicas_gc2(c);
 }
index ff426a2c8e7abff8c3b4df7e94f44b6f61535429..64ac8244e1e0423b9b651ce505f96a1c40a4371c 100644 (file)
@@ -619,64 +619,6 @@ out:
        return ret;
 }
 
-static int bch2_gc_data_replicas(struct bch_fs *c)
-{
-       struct btree_trans trans;
-       struct btree_iter *iter;
-       struct bkey_s_c k;
-       int ret;
-
-       bch2_trans_init(&trans, c);
-
-       mutex_lock(&c->replicas_gc_lock);
-       bch2_replicas_gc_start(c, (1 << BCH_DATA_USER)|(1 << BCH_DATA_CACHED));
-
-       for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS, POS_MIN,
-                          BTREE_ITER_PREFETCH, k, ret) {
-               ret = bch2_mark_bkey_replicas(c, k);
-               if (ret)
-                       break;
-       }
-       ret = bch2_trans_exit(&trans) ?: ret;
-
-       bch2_replicas_gc_end(c, ret);
-       mutex_unlock(&c->replicas_gc_lock);
-
-       return ret;
-}
-
-static int bch2_gc_btree_replicas(struct bch_fs *c)
-{
-       struct btree_trans trans;
-       struct btree_iter *iter;
-       struct btree *b;
-       unsigned id;
-       int ret = 0;
-
-       bch2_trans_init(&trans, c);
-
-       mutex_lock(&c->replicas_gc_lock);
-       bch2_replicas_gc_start(c, 1 << BCH_DATA_BTREE);
-
-       for (id = 0; id < BTREE_ID_NR; id++) {
-               for_each_btree_node(&trans, iter, id, POS_MIN,
-                                   BTREE_ITER_PREFETCH, b) {
-                       ret = bch2_mark_bkey_replicas(c, bkey_i_to_s_c(&b->key));
-
-                       bch2_trans_cond_resched(&trans);
-               }
-
-               ret = bch2_trans_iter_free(&trans, iter) ?: ret;
-       }
-
-       bch2_trans_exit(&trans);
-
-       bch2_replicas_gc_end(c, ret);
-       mutex_unlock(&c->replicas_gc_lock);
-
-       return ret;
-}
-
 static int bch2_move_btree(struct bch_fs *c,
                           move_pred_fn pred,
                           void *arg,
@@ -803,14 +745,14 @@ int bch2_data_job(struct bch_fs *c,
                        bch2_journal_meta(&c->journal);
                }
 
-               ret = bch2_gc_btree_replicas(c) ?: ret;
+               ret = bch2_replicas_gc2(c) ?: ret;
 
                ret = bch2_move_data(c, NULL,
                                     writepoint_hashed((unsigned long) current),
                                     op.start,
                                     op.end,
                                     rereplicate_pred, c, stats) ?: ret;
-               ret = bch2_gc_data_replicas(c) ?: ret;
+               ret = bch2_replicas_gc2(c) ?: ret;
                break;
        case BCH_DATA_OP_MIGRATE:
                if (op.migrate.dev >= c->sb.nr_devices)
@@ -820,14 +762,14 @@ int bch2_data_job(struct bch_fs *c,
                ret = bch2_journal_flush_device_pins(&c->journal, op.migrate.dev);
 
                ret = bch2_move_btree(c, migrate_pred, &op, stats) ?: ret;
-               ret = bch2_gc_btree_replicas(c) ?: ret;
+               ret = bch2_replicas_gc2(c) ?: ret;
 
                ret = bch2_move_data(c, NULL,
                                     writepoint_hashed((unsigned long) current),
                                     op.start,
                                     op.end,
                                     migrate_pred, &op, stats) ?: ret;
-               ret = bch2_gc_data_replicas(c) ?: ret;
+               ret = bch2_replicas_gc2(c) ?: ret;
                break;
        default:
                ret = -EINVAL;
index 2482dbbbad38fb49cabd0e4f7f0f615f04326d84..7a9a7ec26c93d3285c7b10cdef3f2172ef9e9852 100644 (file)
@@ -571,6 +571,64 @@ int bch2_replicas_gc_start(struct bch_fs *c, unsigned typemask)
        return 0;
 }
 
+int bch2_replicas_gc2(struct bch_fs *c)
+{
+       struct bch_replicas_cpu new = { 0 };
+       unsigned i, nr;
+       int ret = 0;
+
+       bch2_journal_meta(&c->journal);
+retry:
+       nr              = READ_ONCE(c->replicas.nr);
+       new.entry_size  = READ_ONCE(c->replicas.entry_size);
+       new.entries     = kcalloc(nr, new.entry_size, GFP_KERNEL);
+       if (!new.entries)
+               return -ENOMEM;
+
+       mutex_lock(&c->sb_lock);
+       percpu_down_write(&c->mark_lock);
+
+       if (nr                  != c->replicas.nr ||
+           new.entry_size      != c->replicas.entry_size) {
+               percpu_up_write(&c->mark_lock);
+               mutex_unlock(&c->sb_lock);
+               kfree(new.entries);
+               goto retry;
+       }
+
+       for (i = 0; i < c->replicas.nr; i++) {
+               struct bch_replicas_entry *e =
+                       cpu_replicas_entry(&c->replicas, i);
+
+               if (e->data_type == BCH_DATA_JOURNAL ||
+                   c->usage_base->replicas[i] ||
+                   percpu_u64_get(&c->usage[0]->replicas[i]) ||
+                   percpu_u64_get(&c->usage[1]->replicas[i]))
+                       memcpy(cpu_replicas_entry(&new, new.nr++),
+                              e, new.entry_size);
+       }
+
+       bch2_cpu_replicas_sort(&new);
+
+       if (bch2_cpu_replicas_to_sb_replicas(c, &new)) {
+               ret = -ENOSPC;
+               goto err;
+       }
+
+       ret = replicas_table_update(c, &new);
+err:
+       kfree(new.entries);
+
+       percpu_up_write(&c->mark_lock);
+
+       if (!ret)
+               bch2_write_super(c);
+
+       mutex_unlock(&c->sb_lock);
+
+       return ret;
+}
+
 int bch2_replicas_set_usage(struct bch_fs *c,
                            struct bch_replicas_entry *r,
                            u64 sectors)
index 1ceedb6231fd26f7847cc73a245d9e3b69e2df48..0d6e191260217d125a76f36d5b1e70f1932fb6ae 100644 (file)
@@ -59,6 +59,7 @@ unsigned bch2_dev_has_data(struct bch_fs *, struct bch_dev *);
 
 int bch2_replicas_gc_end(struct bch_fs *, int);
 int bch2_replicas_gc_start(struct bch_fs *, unsigned);
+int bch2_replicas_gc2(struct bch_fs *);
 
 int bch2_replicas_set_usage(struct bch_fs *,
                            struct bch_replicas_entry *,