This obsoletes BCH_DATA_OP_drop_extra_replicas, BCH_DATA_OP_rereplicate. (And the code is taken from drop_extra_replicas_pred() and rereplicate_pred() in move.c).
Changes to the data_replicas setting will now automatically be applied to existing data without any additional user action. NOTE: we don't yet have a mechanism for guessing how much space an option change will require (and reserving said space), until we have that users will have to be careful not to run a filesystem out of free space with an option change. XXX: support metadata XXX: BCH_DATA_OP_rereplicate additionally calls bch2_replicas_gc2(): this clears out stale replicas entries from the superblock (based on the accounting btree), ensuring the "can we mount degraded without missing data?" table is accurate. We'll need to figure out a new place to plumb this. Signed-off-by: Kent Overstreet <[email protected]> --- fs/bcachefs/rebalance.c | 42 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/fs/bcachefs/rebalance.c b/fs/bcachefs/rebalance.c index 7ebd1c982810..29e12dbf3710 100644 --- a/fs/bcachefs/rebalance.c +++ b/fs/bcachefs/rebalance.c @@ -593,6 +593,48 @@ static struct bkey_s_c next_rebalance_extent(struct btree_trans *trans, data_opts->target = opts->background_target; data_opts->write_flags |= BCH_WRITE_only_specified_devs; + if (r.need_rb & BIT(BCH_REBALANCE_data_replicas)) { + unsigned durability = bch2_bkey_durability(c, k); + struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k); + unsigned ptr_bit = 1; + + guard(rcu)(); + if (durability <= opts->data_replicas) { + bkey_for_each_ptr(ptrs, ptr) { + struct bch_dev *ca = bch2_dev_rcu_noerror(c, ptr->dev); + if (ca && !ptr->cached && !ca->mi.durability) + data_opts->kill_ptrs |= ptr_bit; + ptr_bit <<= 1; + } + + data_opts->extra_replicas = opts->data_replicas - durability; + } else { + const union bch_extent_entry *entry; + struct extent_ptr_decoded p; + + bkey_for_each_ptr_decode(k.k, ptrs, p, entry) { + unsigned d = bch2_extent_ptr_durability(c, &p); + + if (d && durability - d >= opts->data_replicas) { + data_opts->kill_ptrs |= ptr_bit; + durability -= d; + } + + ptr_bit <<= 1; + } + + ptr_bit = 1; + bkey_for_each_ptr_decode(k.k, ptrs, p, entry) { + if (p.has_ec && durability - p.ec.redundancy >= opts->data_replicas) { + data_opts->kill_ec_ptrs |= ptr_bit; + durability -= p.ec.redundancy; + } + + ptr_bit <<= 1; + } + } + } + if (!data_opts->rewrite_ptrs && !data_opts->kill_ptrs && !data_opts->kill_ec_ptrs && -- 2.50.1
