Signed-off-by: Kent Overstreet <[email protected]>
---
 fs/bcachefs/move.c      | 69 ++---------------------------------------
 fs/bcachefs/rebalance.c | 32 +++++++++++++++++--
 2 files changed, 33 insertions(+), 68 deletions(-)

diff --git a/fs/bcachefs/move.c b/fs/bcachefs/move.c
index e96443e67b29..5adeca883ecd 100644
--- a/fs/bcachefs/move.c
+++ b/fs/bcachefs/move.c
@@ -580,37 +580,6 @@ int bch2_move_ratelimit(struct moving_context *ctxt)
        return 0;
 }
 
-/*
- * Move requires non extents iterators, and there's also no need for it to
- * signal indirect_extent_missing_error:
- */
-static struct bkey_s_c bch2_lookup_indirect_extent_for_move(struct btree_trans 
*trans,
-                                           struct btree_iter *iter,
-                                           struct bkey_s_c_reflink_p p)
-{
-       if (unlikely(REFLINK_P_ERROR(p.v)))
-               return bkey_s_c_null;
-
-       struct bpos reflink_pos = POS(0, REFLINK_P_IDX(p.v));
-
-       bch2_trans_iter_init(trans, iter,
-                            BTREE_ID_reflink, reflink_pos,
-                            BTREE_ITER_not_extents);
-
-       struct bkey_s_c k = bch2_btree_iter_peek(iter);
-       if (!k.k || bkey_err(k)) {
-               bch2_trans_iter_exit(iter);
-               return k;
-       }
-
-       if (bkey_lt(reflink_pos, bkey_start_pos(k.k))) {
-               bch2_trans_iter_exit(iter);
-               return bkey_s_c_null;
-       }
-
-       return k;
-}
-
 int bch2_move_data_btree(struct moving_context *ctxt,
                         struct bpos start,
                         struct bpos end,
@@ -625,12 +594,6 @@ int bch2_move_data_btree(struct moving_context *ctxt,
        struct btree_iter iter, reflink_iter = {};
        struct bkey_s_c k;
        struct data_update_opts data_opts;
-       /*
-        * If we're moving a single file, also process reflinked data it points
-        * to (this includes propagating changed io_opts from the inode to the
-        * extent):
-        */
-       bool walk_indirect = start.inode == end.inode;
        int ret = 0, ret2;
 
        per_snapshot_io_opts_init(&snapshot_io_opts, c);
@@ -695,8 +658,6 @@ int bch2_move_data_btree(struct moving_context *ctxt,
                bch2_ratelimit_reset(ctxt->rate);
 
        while (!bch2_move_ratelimit(ctxt)) {
-               struct btree_iter *extent_iter = &iter;
-
                bch2_trans_begin(trans);
 
                k = bch2_btree_iter_peek(&iter);
@@ -715,41 +676,17 @@ int bch2_move_data_btree(struct moving_context *ctxt,
                if (ctxt->stats)
                        ctxt->stats->pos = BBPOS(iter.btree_id, iter.pos);
 
-               if (walk_indirect &&
-                   k.k->type == KEY_TYPE_reflink_p &&
-                   REFLINK_P_MAY_UPDATE_OPTIONS(bkey_s_c_to_reflink_p(k).v)) {
-                       struct bkey_s_c_reflink_p p = bkey_s_c_to_reflink_p(k);
-
-                       bch2_trans_iter_exit(&reflink_iter);
-                       k = bch2_lookup_indirect_extent_for_move(trans, 
&reflink_iter, p);
-                       ret = bkey_err(k);
-                       if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
-                               continue;
-                       if (ret)
-                               break;
-
-                       if (!k.k)
-                               goto next_nondata;
-
-                       /*
-                        * XXX: reflink pointers may point to multiple indirect
-                        * extents, so don't advance past the entire reflink
-                        * pointer - need to fixup iter->k
-                        */
-                       extent_iter = &reflink_iter;
-               }
-
                if (!bkey_extent_is_direct_data(k.k))
                        goto next_nondata;
 
                io_opts = bch2_move_get_io_opts(trans, &snapshot_io_opts,
-                                               iter.pos, extent_iter, k);
+                                               iter.pos, &iter, k);
                ret = PTR_ERR_OR_ZERO(io_opts);
                if (ret)
                        continue;
 
                memset(&data_opts, 0, sizeof(data_opts));
-               if (!pred(c, arg, extent_iter->btree_id, k, io_opts, 
&data_opts))
+               if (!pred(c, arg, iter.btree_id, k, io_opts, &data_opts))
                        goto next;
 
                /*
@@ -760,7 +697,7 @@ int bch2_move_data_btree(struct moving_context *ctxt,
                k = bkey_i_to_s_c(sk.k);
 
                if (!level)
-                       ret2 = bch2_move_extent(ctxt, NULL, extent_iter, k, 
*io_opts, data_opts);
+                       ret2 = bch2_move_extent(ctxt, NULL, &iter, k, *io_opts, 
data_opts);
                else if (!data_opts.scrub)
                        ret2 = bch2_btree_node_rewrite_pos(trans, btree_id, 
level,
                                                          k.k->p, 
data_opts.target, 0);
diff --git a/fs/bcachefs/rebalance.c b/fs/bcachefs/rebalance.c
index a9d772642b3f..2bb634ee0f48 100644
--- a/fs/bcachefs/rebalance.c
+++ b/fs/bcachefs/rebalance.c
@@ -482,6 +482,29 @@ static int do_rebalance_extent(struct moving_context *ctxt,
        return ret;
 }
 
+static int do_rebalance_scan_indirect(struct btree_trans *trans,
+                                     struct bkey_s_c_reflink_p p,
+                                     struct bch_inode_opts *opts)
+{
+       u64 idx = REFLINK_P_IDX(p.v) - le32_to_cpu(p.v->front_pad);
+       u64 end = REFLINK_P_IDX(p.v) + p.k->size + le32_to_cpu(p.v->back_pad);
+       u32 restart_count = trans->restart_count;
+
+       int ret = for_each_btree_key(trans, iter, BTREE_ID_reflink,
+                                    POS(0, idx), BTREE_ITER_not_extents, k, ({
+               if (bpos_ge(bkey_start_pos(k.k), POS(0, end)))
+                       break;
+               bch2_get_update_rebalance_opts(trans, opts, &iter, k,
+                                              
SET_NEEDS_REBALANCE_opt_change_indirect);
+       }));
+       if (ret)
+               return ret;
+
+       /* suppress trans_was_restarted() check */
+       trans->restart_count = restart_count;
+       return 0;
+}
+
 static int do_rebalance_scan(struct moving_context *ctxt,
                             u64 inum, u64 cookie, u64 *sectors_scanned)
 {
@@ -511,9 +534,14 @@ static int do_rebalance_scan(struct moving_context *ctxt,
                                         BTREE_ITER_prefetch, k, ({
                ctxt->stats->pos = BBPOS(iter.btree_id, iter.pos);
 
-               struct bch_inode_opts *io_opts = bch2_move_get_io_opts(trans,
+               struct bch_inode_opts *opts = bch2_move_get_io_opts(trans,
                                        &snapshot_io_opts, iter.pos, &iter, k);
-               PTR_ERR_OR_ZERO(io_opts);
+               PTR_ERR_OR_ZERO(opts) ?:
+               (inum &&
+                k.k->type == KEY_TYPE_reflink_p &&
+                REFLINK_P_MAY_UPDATE_OPTIONS(bkey_s_c_to_reflink_p(k).v)
+                ? do_rebalance_scan_indirect(trans, bkey_s_c_to_reflink_p(k), 
opts)
+                : 0);
        })) ?:
        commit_do(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
                  bch2_clear_rebalance_needs_scan(trans, inum, cookie));
-- 
2.50.1


Reply via email to