bcachefs: Switch extent_handle_overwrites() to one key at a time
authorKent Overstreet <kent.overstreet@gmail.com>
Sun, 21 Mar 2021 01:04:57 +0000 (21:04 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:08:56 +0000 (17:08 -0400)
Prep work for snapshots

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/btree_update_leaf.c

index f8b493706c949d346d2882502a5ad3b0d5b2ab44..e76916cffd5b3cd4fc6f741e6325cb5ed568d47e 100644 (file)
@@ -690,8 +690,8 @@ bch2_trans_commit_get_rw_cold(struct btree_trans *trans)
        return 0;
 }
 
-static int __bch2_trans_update2(struct btree_trans *trans,
-                               struct btree_insert_entry n)
+static void __bch2_trans_update2(struct btree_trans *trans,
+                                struct btree_insert_entry n)
 {
        struct btree_insert_entry *i;
 
@@ -711,15 +711,13 @@ static int __bch2_trans_update2(struct btree_trans *trans,
        else
                array_insert_item(trans->updates2, trans->nr_updates2,
                                  i - trans->updates2, n);
-
-       return 0;
 }
 
-static int bch2_trans_update2(struct btree_trans *trans,
-                             struct btree_iter *iter,
-                             struct bkey_i *insert)
+static void bch2_trans_update2(struct btree_trans *trans,
+                              struct btree_iter *iter,
+                              struct bkey_i *insert)
 {
-       return __bch2_trans_update2(trans, (struct btree_insert_entry) {
+       __bch2_trans_update2(trans, (struct btree_insert_entry) {
                .bkey_type      = __btree_node_type(iter->level, iter->btree_id),
                .btree_id       = iter->btree_id,
                .level          = iter->level,
@@ -745,82 +743,81 @@ static int extent_update_to_keys(struct btree_trans *trans,
                                     BTREE_ITER_NOT_EXTENTS);
        n.is_extent = false;
 
-       ret = __bch2_trans_update2(trans, n);
+       __bch2_trans_update2(trans, n);
        bch2_trans_iter_put(trans, n.iter);
-       return ret;
+       return 0;
 }
 
 static int extent_handle_overwrites(struct btree_trans *trans,
                                    enum btree_id btree_id,
-                                   struct bpos start, struct bpos end)
+                                   struct bkey_i *insert)
 {
        struct btree_iter *iter, *update_iter;
+       struct bpos start = bkey_start_pos(&insert->k);
        struct bkey_i *update;
        struct bkey_s_c k;
        int ret = 0;
 
-       iter = bch2_trans_get_iter(trans, btree_id, start, BTREE_ITER_INTENT);
+       iter = bch2_trans_get_iter(trans, btree_id, start,
+                                  BTREE_ITER_INTENT);
        k = bch2_btree_iter_peek_with_updates(iter);
 
        while (k.k && !(ret = bkey_err(k))) {
-               if (bkey_cmp(end, bkey_start_pos(k.k)) <= 0)
+               if (bkey_cmp(insert->k.p, bkey_start_pos(k.k)) <= 0)
                        break;
 
                if (bkey_cmp(bkey_start_pos(k.k), start) < 0) {
                        update = bch2_trans_kmalloc(trans, bkey_bytes(k.k));
                        if ((ret = PTR_ERR_OR_ZERO(update)))
-                               goto err;
+                               break;
 
                        bkey_reassemble(update, k);
+
                        bch2_cut_back(start, update);
 
-                       update_iter = bch2_trans_copy_iter(trans, iter);
-                       update_iter->flags &= ~BTREE_ITER_IS_EXTENTS;
-                       bch2_btree_iter_set_pos(update_iter, update->k.p);
-                       ret = bch2_trans_update2(trans, update_iter, update);
+                       update_iter = bch2_trans_get_iter(trans, btree_id, update->k.p,
+                                                         BTREE_ITER_NOT_EXTENTS|
+                                                         BTREE_ITER_INTENT);
+                       bch2_trans_update2(trans, update_iter, update);
                        bch2_trans_iter_put(trans, update_iter);
-                       if (ret)
-                               goto err;
                }
 
-               if (bkey_cmp(k.k->p, end) > 0) {
-                       update = bch2_trans_kmalloc(trans, bkey_bytes(k.k));
+               if (bkey_cmp(k.k->p, insert->k.p) < 0 ||
+                   (!bkey_cmp(k.k->p, insert->k.p) && bkey_deleted(&insert->k))) {
+                       update = bch2_trans_kmalloc(trans, sizeof(struct bkey));
                        if ((ret = PTR_ERR_OR_ZERO(update)))
-                               goto err;
+                               break;
 
-                       bkey_reassemble(update, k);
-                       bch2_cut_front(end, update);
+                       bkey_init(&update->k);
+                       update->k.p = k.k->p;
 
-                       update_iter = bch2_trans_copy_iter(trans, iter);
-                       update_iter->flags &= ~BTREE_ITER_IS_EXTENTS;
-                       bch2_btree_iter_set_pos(update_iter, update->k.p);
-                       ret = bch2_trans_update2(trans, update_iter, update);
+                       update_iter = bch2_trans_get_iter(trans, btree_id, update->k.p,
+                                                         BTREE_ITER_NOT_EXTENTS|
+                                                         BTREE_ITER_INTENT);
+                       bch2_trans_update2(trans, update_iter, update);
                        bch2_trans_iter_put(trans, update_iter);
-                       if (ret)
-                               goto err;
-               } else {
-                       update = bch2_trans_kmalloc(trans, sizeof(struct bkey));
+               }
+
+               if (bkey_cmp(k.k->p, insert->k.p) > 0) {
+                       update = bch2_trans_kmalloc(trans, bkey_bytes(k.k));
                        if ((ret = PTR_ERR_OR_ZERO(update)))
-                               goto err;
+                               break;
 
-                       update->k = *k.k;
-                       set_bkey_val_u64s(&update->k, 0);
-                       update->k.type = KEY_TYPE_deleted;
-                       update->k.size = 0;
+                       bkey_reassemble(update, k);
+                       bch2_cut_front(insert->k.p, update);
 
-                       update_iter = bch2_trans_copy_iter(trans, iter);
-                       update_iter->flags &= ~BTREE_ITER_IS_EXTENTS;
-                       bch2_btree_iter_set_pos(update_iter, update->k.p);
-                       ret = bch2_trans_update2(trans, update_iter, update);
+                       update_iter = bch2_trans_get_iter(trans, btree_id, update->k.p,
+                                                         BTREE_ITER_NOT_EXTENTS|
+                                                         BTREE_ITER_INTENT);
+                       bch2_trans_update2(trans, update_iter, update);
                        bch2_trans_iter_put(trans, update_iter);
-                       if (ret)
-                               goto err;
+                       break;
                }
 
                k = bch2_btree_iter_next_with_updates(iter);
        }
-err:
        bch2_trans_iter_put(trans, iter);
+
        return ret;
 }
 
@@ -885,24 +882,16 @@ int __bch2_trans_commit(struct btree_trans *trans)
        /* Turn extents updates into keys: */
        trans_for_each_update(trans, i)
                if (i->is_extent) {
-                       struct bpos start = bkey_start_pos(&i->k->k);
-
-                       while (i + 1 < trans->updates + trans->nr_updates &&
-                              i[0].btree_id == i[1].btree_id &&
-                              !bkey_cmp(i[0].k->k.p, bkey_start_pos(&i[1].k->k)))
-                               i++;
-
-                       ret = extent_handle_overwrites(trans, i->btree_id,
-                                                      start, i->k->k.p);
-                       if (ret)
+                       ret = extent_handle_overwrites(trans, i->btree_id, i->k);
+                       if (unlikely(ret))
                                goto out;
                }
 
        trans_for_each_update(trans, i) {
                ret = i->is_extent
                        ? extent_update_to_keys(trans, *i)
-                       : __bch2_trans_update2(trans, *i);
-               if (ret)
+                       : (__bch2_trans_update2(trans, *i), 0);
+               if (unlikely(ret))
                        goto out;
        }