bcachefs: Don't reuse reflink btree keyspace
authorKent Overstreet <kent.overstreet@linux.dev>
Fri, 26 May 2023 03:37:06 +0000 (23:37 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:10:02 +0000 (17:10 -0400)
We've been seeing difficult to debug "missing indirect extent" bugs,
that fsck doesn't seem to find.

One possibility is that there was a missing indirect extent, but then a
new indirect extent was created at the location of the previous indirect
extent.

This patch eliminates that possibility by always creating new indirect
extents right after the last one, at the end of the reflink btree.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/bcachefs.h
fs/bcachefs/reflink.c

index 39fd154477533aac55f90f3c48edd56852f64aef..0dfa42e297e04b95c90ae167b751ce8bef5f006c 100644 (file)
@@ -963,7 +963,6 @@ struct bch_fs {
        struct bio_set          ec_bioset;
 
        /* REFLINK */
-       u64                     reflink_hint;
        reflink_gc_table        reflink_gc_table;
        size_t                  reflink_gc_nr;
 
index 9430899a5a31633ddb56cb2fde5dae3f4869b29a..26f0275ff0afad6a0c170854b24c409782bd36eb 100644 (file)
@@ -167,24 +167,13 @@ static int bch2_make_extent_indirect(struct btree_trans *trans,
        if (orig->k.type == KEY_TYPE_inline_data)
                bch2_check_set_feature(c, BCH_FEATURE_reflink_inline_data);
 
-       for_each_btree_key_norestart(trans, reflink_iter, BTREE_ID_reflink,
-                          POS(0, c->reflink_hint),
-                          BTREE_ITER_SLOTS, k, ret) {
-               if (reflink_iter.pos.inode) {
-                       bch2_btree_iter_set_pos(&reflink_iter, POS_MIN);
-                       continue;
-               }
-
-               if (bkey_deleted(k.k) && orig->k.size <= k.k->size)
-                       break;
-       }
-
+       bch2_trans_iter_init(trans, &reflink_iter, BTREE_ID_reflink, POS_MAX,
+                            BTREE_ITER_INTENT);
+       k = bch2_btree_iter_peek_prev(&reflink_iter);
+       ret = bkey_err(k);
        if (ret)
                goto err;
 
-       /* rewind iter to start of hole, if necessary: */
-       bch2_btree_iter_set_pos_to_extent_start(&reflink_iter);
-
        r_v = bch2_trans_kmalloc(trans, sizeof(__le64) + bkey_bytes(&orig->k));
        ret = PTR_ERR_OR_ZERO(r_v);
        if (ret)
@@ -226,7 +215,6 @@ static int bch2_make_extent_indirect(struct btree_trans *trans,
        ret = bch2_trans_update(trans, extent_iter, &r_p->k_i,
                                BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE);
 err:
-       c->reflink_hint = reflink_iter.pos.offset;
        bch2_trans_iter_exit(trans, &reflink_iter);
 
        return ret;