diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2019-04-30 17:15:39 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-22 17:08:21 -0400 |
commit | ae0ff7b8b0ccf0643ea4d3968faabb2d5ee98c1c (patch) | |
tree | 059b8cb3b184eda983bed7f13e7d8910d5753804 /fs | |
parent | 9516950c0690b6a8bef4cc1c7ae269da996973d8 (diff) |
bcachefs: Redo replicas gc mechanism
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/bcachefs/migrate.c | 22 | ||||
-rw-r--r-- | fs/bcachefs/move.c | 66 | ||||
-rw-r--r-- | fs/bcachefs/replicas.c | 58 | ||||
-rw-r--r-- | fs/bcachefs/replicas.h | 1 |
4 files changed, 69 insertions, 78 deletions
diff --git a/fs/bcachefs/migrate.c b/fs/bcachefs/migrate.c index f9e6c9d9ef04..6b17d7918aa4 100644 --- a/fs/bcachefs/migrate.c +++ b/fs/bcachefs/migrate.c @@ -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); } diff --git a/fs/bcachefs/move.c b/fs/bcachefs/move.c index ff426a2c8e7a..64ac8244e1e0 100644 --- a/fs/bcachefs/move.c +++ b/fs/bcachefs/move.c @@ -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; diff --git a/fs/bcachefs/replicas.c b/fs/bcachefs/replicas.c index 2482dbbbad38..7a9a7ec26c93 100644 --- a/fs/bcachefs/replicas.c +++ b/fs/bcachefs/replicas.c @@ -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) diff --git a/fs/bcachefs/replicas.h b/fs/bcachefs/replicas.h index 1ceedb6231fd..0d6e19126021 100644 --- a/fs/bcachefs/replicas.h +++ b/fs/bcachefs/replicas.h @@ -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 *, |