]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
bcachefs: Fix btree iter flags in data move (2)
authorKent Overstreet <kent.overstreet@linux.dev>
Mon, 17 Mar 2025 19:07:06 +0000 (15:07 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Wed, 26 Mar 2025 20:26:35 +0000 (16:26 -0400)
Data move -> move_get_io_opts -> bch2_get_update_rebalance_opts

requires a not_extents iterator; this fixes the path where we're walking
the extents btree and chase a reflink pointer into the reflink btree.

bch2_lookup_indirect_extent() requires working with an extents iterator
(due to peek_slot() semantics), so we implement
bch2_lookup_indirect_extent_for_move().

This is simplified because there's no need to report
indirect_extent_missing_errors here, that can be deferred until fsck or
when a user reads that data.

Reported-by: Maƫl Kerbiriou <mael.kerbiriou@free.fr>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/move.c

index 8fcdc6984f6e0bf6099c259c5b4e7ee4136caa5b..5d41260e10da7d399b84618531d5248d37fd36c8 100644 (file)
@@ -528,6 +528,37 @@ 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(trans, iter);
+               return k;
+       }
+
+       if (bkey_lt(reflink_pos, bkey_start_pos(k.k))) {
+               bch2_trans_iter_exit(trans, iter);
+               return bkey_s_c_null;
+       }
+
+       return k;
+}
+
 static int bch2_move_data_btree(struct moving_context *ctxt,
                                struct bpos start,
                                struct bpos end,
@@ -592,17 +623,16 @@ static int bch2_move_data_btree(struct moving_context *ctxt,
                    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);
-                       s64 offset_into_extent  = 0;
 
                        bch2_trans_iter_exit(trans, &reflink_iter);
-                       k = bch2_lookup_indirect_extent(trans, &reflink_iter, &offset_into_extent, p, true, 0);
+                       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 (bkey_deleted(k.k))
+                       if (!k.k)
                                goto next_nondata;
 
                        /*
@@ -611,7 +641,6 @@ static int bch2_move_data_btree(struct moving_context *ctxt,
                         * pointer - need to fixup iter->k
                         */
                        extent_iter = &reflink_iter;
-                       offset_into_extent = 0;
                }
 
                if (!bkey_extent_is_direct_data(k.k))