bcachefs: Refactor bch2_extent_trim_atomic() for reflink
authorKent Overstreet <kent.overstreet@gmail.com>
Fri, 16 Aug 2019 13:58:07 +0000 (09:58 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:08:25 +0000 (17:08 -0400)
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/btree_update_leaf.c
fs/bcachefs/buckets.c
fs/bcachefs/extents.c
fs/bcachefs/extents.h
fs/bcachefs/fs-io.c
fs/bcachefs/io.c
fs/bcachefs/recovery.c

index b878f9a9882cb6c4cd9127355d6776d716c6251b..5f94b6e9cf2865a692c7a195f7c4e3c8226d5eb2 100644 (file)
@@ -400,8 +400,7 @@ static inline void btree_insert_entry_checks(struct btree_trans *trans,
                BUG_ON(i->iter->level);
                BUG_ON(bkey_cmp(bkey_start_pos(&i->k->k), i->iter->pos));
                EBUG_ON((i->iter->flags & BTREE_ITER_IS_EXTENTS) &&
-                       !bch2_extent_is_atomic(i->k, i->iter));
-
+                       bkey_cmp(i->k->k.p, i->iter->l[0].b->key.k.p) > 0);
                EBUG_ON((i->iter->flags & BTREE_ITER_IS_EXTENTS) &&
                        !(trans->flags & BTREE_INSERT_ATOMIC));
        }
@@ -1031,7 +1030,10 @@ retry:
                        /* create the biggest key we can */
                        bch2_key_resize(&delete.k, max_sectors);
                        bch2_cut_back(end, &delete.k);
-                       bch2_extent_trim_atomic(&delete, iter);
+
+                       ret = bch2_extent_trim_atomic(&delete, iter);
+                       if (ret)
+                               break;
                }
 
                bch2_trans_update(trans, BTREE_INSERT_ENTRY(iter, &delete));
index 569c9e4a55aa621a629bdb6967e5b11393a41ae9..baf9642d21caad9dbec8e48d43a11c26898b2080 100644 (file)
@@ -1255,9 +1255,6 @@ int bch2_mark_update(struct btree_trans *trans,
        if (!btree_node_type_needs_gc(iter->btree_id))
                return 0;
 
-       EBUG_ON(btree_node_is_extents(b) &&
-               !bch2_extent_is_atomic(insert->k, insert->iter));
-
        if (!(trans->flags & BTREE_INSERT_NOMARK_INSERT))
                bch2_mark_key_locked(c, bkey_i_to_s_c(insert->k),
                        0, insert->k->k.size,
@@ -1636,9 +1633,6 @@ int bch2_trans_mark_update(struct btree_trans *trans,
        if (!btree_node_type_needs_gc(iter->btree_id))
                return 0;
 
-       EBUG_ON(btree_node_is_extents(b) &&
-               !bch2_extent_is_atomic(insert, iter));
-
        ret = bch2_trans_mark_key(trans, bkey_i_to_s_c(insert),
                        0, insert->k.size, BCH_BUCKET_MARK_INSERT);
        if (ret)
index 0e43e81065b6f8c4425f04e2900af779522d6be2..11defa3d99a546a1682af163c59615660bccf408 100644 (file)
@@ -949,47 +949,104 @@ static unsigned bch2_bkey_nr_alloc_ptrs(struct bkey_s_c k)
        return ret;
 }
 
-static inline struct bpos
-bch2_extent_atomic_end(struct bkey_i *insert, struct btree_iter *iter)
+static int __bch2_extent_atomic_end(struct btree_trans *trans,
+                                   struct bkey_s_c k,
+                                   unsigned offset,
+                                   struct bpos *end,
+                                   unsigned *nr_iters,
+                                   unsigned max_iters)
+{
+       int ret = 0;
+
+       switch (k.k->type) {
+       case KEY_TYPE_extent:
+               *nr_iters += bch2_bkey_nr_alloc_ptrs(k);
+
+               if (*nr_iters >= max_iters) {
+                       *end = bpos_min(*end, k.k->p);
+                       return 0;
+               }
+
+               break;
+       }
+
+       return ret;
+}
+
+int bch2_extent_atomic_end(struct btree_trans *trans,
+                          struct btree_iter *iter,
+                          struct bkey_i *insert,
+                          struct bpos *end)
 {
        struct btree *b = iter->l[0].b;
        struct btree_node_iter  node_iter = iter->l[0].iter;
        struct bkey_packed      *_k;
-       unsigned                nr_alloc_ptrs =
+       unsigned                nr_iters =
                bch2_bkey_nr_alloc_ptrs(bkey_i_to_s_c(insert));
+       int ret = 0;
 
        BUG_ON(iter->uptodate > BTREE_ITER_NEED_PEEK);
        BUG_ON(bkey_cmp(bkey_start_pos(&insert->k), b->data->min_key) < 0);
 
-       while ((_k = bch2_btree_node_iter_peek_filter(&node_iter, b,
+       *end = bpos_min(insert->k.p, b->key.k.p);
+
+       ret = __bch2_extent_atomic_end(trans, bkey_i_to_s_c(insert),
+                                      0, end, &nr_iters, 10);
+       if (ret)
+               return ret;
+
+       while (nr_iters < 20 &&
+              (_k = bch2_btree_node_iter_peek_filter(&node_iter, b,
                                                      KEY_TYPE_discard))) {
                struct bkey     unpacked;
                struct bkey_s_c k = bkey_disassemble(b, _k, &unpacked);
+               unsigned offset = 0;
 
-               if (bkey_cmp(insert->k.p, bkey_start_pos(k.k)) <= 0)
+               if (bkey_cmp(bkey_start_pos(k.k), *end) >= 0)
                        break;
 
-               nr_alloc_ptrs += bch2_bkey_nr_alloc_ptrs(k);
+               if (bkey_cmp(bkey_start_pos(&insert->k),
+                            bkey_start_pos(k.k)) > 0)
+                       offset = bkey_start_offset(&insert->k) -
+                               bkey_start_offset(k.k);
 
-               if (nr_alloc_ptrs > 20) {
-                       BUG_ON(bkey_cmp(k.k->p, bkey_start_pos(&insert->k)) <= 0);
-                       return bpos_min(insert->k.p, k.k->p);
-               }
+               ret = __bch2_extent_atomic_end(trans, k, offset,
+                                              end, &nr_iters, 20);
+               if (ret)
+                       return ret;
+
+               if (nr_iters >= 20)
+                       break;
 
                bch2_btree_node_iter_advance(&node_iter, b);
        }
 
-       return bpos_min(insert->k.p, b->key.k.p);
+       return 0;
 }
 
-void bch2_extent_trim_atomic(struct bkey_i *k, struct btree_iter *iter)
+int bch2_extent_trim_atomic(struct bkey_i *k, struct btree_iter *iter)
 {
-       bch2_cut_back(bch2_extent_atomic_end(k, iter), &k->k);
+       struct bpos end;
+       int ret;
+
+       ret = bch2_extent_atomic_end(iter->trans, iter, k, &end);
+       if (ret)
+               return ret;
+
+       bch2_cut_back(end, &k->k);
+       return 0;
 }
 
-bool bch2_extent_is_atomic(struct bkey_i *k, struct btree_iter *iter)
+int bch2_extent_is_atomic(struct bkey_i *k, struct btree_iter *iter)
 {
-       return !bkey_cmp(bch2_extent_atomic_end(k, iter), k->k.p);
+       struct bpos end;
+       int ret;
+
+       ret = bch2_extent_atomic_end(iter->trans, iter, k, &end);
+       if (ret)
+               return ret;
+
+       return !bkey_cmp(end, k->k.p);
 }
 
 enum btree_insert_ret
index 035d15bbca39798892afe58708438adbd6ec32a9..156d8e37045ad078279525c019f84f243c09bf9d 100644 (file)
@@ -425,8 +425,10 @@ enum merge_result bch2_reservation_merge(struct bch_fs *,
        .key_merge      = bch2_reservation_merge,               \
 }
 
-void bch2_extent_trim_atomic(struct bkey_i *, struct btree_iter *);
-bool bch2_extent_is_atomic(struct bkey_i *, struct btree_iter *);
+int bch2_extent_atomic_end(struct btree_trans *, struct btree_iter *,
+                          struct bkey_i *, struct bpos *);
+int bch2_extent_trim_atomic(struct bkey_i *, struct btree_iter *);
+int bch2_extent_is_atomic(struct bkey_i *, struct btree_iter *);
 
 enum btree_insert_ret
 bch2_extent_can_insert(struct btree_trans *, struct btree_insert_entry *,
index 91a34ca5e4e1a83271e64153c0adb99013d0a075..ef94aecaa7cbd9f02a83f587982c6c3753ce74c3 100644 (file)
@@ -310,7 +310,9 @@ int bch2_extent_update(struct btree_trans *trans,
        if (ret)
                return ret;
 
-       bch2_extent_trim_atomic(k, extent_iter);
+       ret = bch2_extent_trim_atomic(k, extent_iter);
+       if (ret)
+               return ret;
 
        ret = sum_sector_overwrites(trans, extent_iter,
                                    k, &allocating,
@@ -2634,7 +2636,9 @@ static long bch2_fcollapse(struct bch_inode_info *inode,
                bch2_cut_front(src->pos, &copy.k);
                copy.k.k.p.offset -= len >> 9;
 
-               bch2_extent_trim_atomic(&copy.k, dst);
+               ret = bch2_extent_trim_atomic(&copy.k, dst);
+               if (ret)
+                       goto bkey_err;
 
                BUG_ON(bkey_cmp(dst->pos, bkey_start_pos(&copy.k.k)));
 
index fd1aceea35532a025844d759ce252b5649f438cb..ed84572a9e676029bb25daef05ea1b1aa17cdcda 100644 (file)
@@ -274,6 +274,8 @@ int bch2_write_index_default(struct bch_write_op *op)
        bch2_verify_keylist_sorted(keys);
 
        bch2_trans_init(&trans, c, BTREE_ITER_MAX, 256);
+retry:
+       bch2_trans_begin(&trans);
 
        iter = bch2_trans_get_iter(&trans, BTREE_ID_EXTENTS,
                                   bkey_start_pos(&bch2_keylist_front(keys)->k),
@@ -284,7 +286,9 @@ int bch2_write_index_default(struct bch_write_op *op)
 
                bkey_copy(&split.k, bch2_keylist_front(keys));
 
-               bch2_extent_trim_atomic(&split.k, iter);
+               ret = bch2_extent_trim_atomic(&split.k, iter);
+               if (ret)
+                       break;
 
                bch2_trans_update(&trans,
                                  BTREE_INSERT_ENTRY(iter, &split.k));
@@ -301,6 +305,11 @@ int bch2_write_index_default(struct bch_write_op *op)
                        bch2_keylist_pop_front(keys);
        } while (!bch2_keylist_empty(keys));
 
+       if (ret == -EINTR) {
+               ret = 0;
+               goto retry;
+       }
+
        bch2_trans_exit(&trans);
 
        return ret;
index a7fc3fe4284a8a8ccc14b7247925cea58d5bd830..3742b241807c3e47a67dd96980781f06901daa18 100644 (file)
@@ -247,6 +247,7 @@ static int bch2_extent_replay_key(struct bch_fs *c, struct bkey_i *k)
        struct disk_reservation disk_res =
                bch2_disk_reservation_init(c, 0);
        struct bkey_i *split;
+       struct bpos atomic_end;
        bool split_compressed = false;
        int ret;
 
@@ -273,9 +274,14 @@ retry:
                if (ret)
                        goto err;
 
+               ret = bch2_extent_atomic_end(&trans, split_iter,
+                                            k, &atomic_end);
+               if (ret)
+                       goto err;
+
                if (!split_compressed &&
                    bch2_extent_is_compressed(bkey_i_to_s_c(k)) &&
-                   !bch2_extent_is_atomic(k, split_iter)) {
+                   bkey_cmp(atomic_end, k->k.p) < 0) {
                        ret = bch2_disk_reservation_add(c, &disk_res,
                                        k->k.size *
                                        bch2_bkey_nr_dirty_ptrs(bkey_i_to_s_c(k)),
@@ -287,7 +293,7 @@ retry:
 
                bkey_copy(split, k);
                bch2_cut_front(split_iter->pos, split);
-               bch2_extent_trim_atomic(split, split_iter);
+               bch2_cut_back(atomic_end, &split->k);
 
                bch2_trans_update(&trans, BTREE_INSERT_ENTRY(split_iter, split));
                bch2_btree_iter_set_pos(iter, split->k.p);