diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2021-08-25 01:03:25 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2021-08-25 15:31:31 -0400 |
commit | bb18d04ece24a36b34d32062ab5755646ddd5cca (patch) | |
tree | 28fc8f1e0fb7e29d967c543e4a30459f4b6b0c92 | |
parent | f8bce8272696eb2c1efdcf40d170a0386227f4ba (diff) |
bcachefs: Refactor bch2_trans_update_extent()
This consolidates the code for doing extent updates, and makes the btree
iterator usage a bit cleaner and more efficient.
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r-- | fs/bcachefs/btree_update_leaf.c | 269 |
1 files changed, 132 insertions, 137 deletions
diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c index daf8e73de90d..fbd40b1bab8f 100644 --- a/fs/bcachefs/btree_update_leaf.c +++ b/fs/bcachefs/btree_update_leaf.c @@ -739,116 +739,6 @@ bch2_trans_commit_get_rw_cold(struct btree_trans *trans) return 0; } -static int extent_handle_overwrites(struct btree_trans *trans, - struct btree_insert_entry *i) -{ - struct bch_fs *c = trans->c; - struct btree_iter *iter, *update_iter; - struct bpos start = bkey_start_pos(&i->k->k); - struct bkey_i *update; - struct bkey_s_c k; - int ret = 0, compressed_sectors; - - iter = bch2_trans_get_iter(trans, i->btree_id, start, - BTREE_ITER_INTENT| - BTREE_ITER_WITH_UPDATES| - BTREE_ITER_NOT_EXTENTS); - k = bch2_btree_iter_peek(iter); - if (!k.k || (ret = bkey_err(k))) - goto out; - - if (bch2_bkey_maybe_mergable(k.k, &i->k->k)) { - update = bch2_trans_kmalloc(trans, bkey_bytes(k.k)); - if ((ret = PTR_ERR_OR_ZERO(update))) - goto out; - - bkey_reassemble(update, k); - - if (bch2_bkey_merge(c, bkey_i_to_s(update), bkey_i_to_s_c(i->k))) { - update_iter = bch2_trans_copy_iter(trans, iter); - ret = bch2_btree_delete_at(trans, update_iter, i->flags); - bch2_trans_iter_put(trans, update_iter); - - if (ret) - goto out; - - i->k = update; - goto next; - } - } - - if (!bkey_cmp(k.k->p, bkey_start_pos(&i->k->k))) - goto next; - - while (bkey_cmp(i->k->k.p, bkey_start_pos(k.k)) > 0) { - /* - * If we're going to be splitting a compressed extent, note it - * so that __bch2_trans_commit() can increase our disk - * reservation: - */ - if (bkey_cmp(bkey_start_pos(k.k), start) < 0 && - bkey_cmp(k.k->p, i->k->k.p) > 0 && - (compressed_sectors = bch2_bkey_sectors_compressed(k))) - trans->extra_journal_res += compressed_sectors; - - 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 out; - - bkey_reassemble(update, k); - - bch2_cut_back(start, update); - - update_iter = bch2_trans_get_iter(trans, i->btree_id, update->k.p, - BTREE_ITER_NOT_EXTENTS| - BTREE_ITER_INTENT); - ret = bch2_btree_iter_traverse(update_iter); - if (ret) { - bch2_trans_iter_put(trans, update_iter); - goto out; - } - - bch2_trans_update(trans, update_iter, update, - BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE| - i->flags); - bch2_trans_iter_put(trans, update_iter); - } - - if (bkey_cmp(k.k->p, i->k->k.p) <= 0) { - update_iter = bch2_trans_copy_iter(trans, iter); - ret = bch2_btree_delete_at(trans, update_iter, - i->flags); - bch2_trans_iter_put(trans, update_iter); - - if (ret) - goto out; - } - - if (bkey_cmp(k.k->p, i->k->k.p) > 0) { - update = bch2_trans_kmalloc(trans, bkey_bytes(k.k)); - if ((ret = PTR_ERR_OR_ZERO(update))) - goto out; - - bkey_reassemble(update, k); - bch2_cut_front(i->k->k.p, update); - - bch2_trans_update(trans, iter, update, i->flags); - goto out; - } -next: - k = bch2_btree_iter_next(iter); - if (!k.k || (ret = bkey_err(k))) - goto out; - } - - bch2_bkey_merge(c, bkey_i_to_s(i->k), k); -out: - bch2_trans_iter_put(trans, iter); - - return ret; -} - int __bch2_trans_commit(struct btree_trans *trans) { struct btree_insert_entry *i = NULL; @@ -983,6 +873,133 @@ err: goto retry; } +static int bch2_trans_update_extent(struct btree_trans *trans, + struct btree_iter *orig_iter, + struct bkey_i *insert, + enum btree_update_flags flags) +{ + struct bch_fs *c = trans->c; + struct btree_iter *iter, *update_iter; + struct bpos start = bkey_start_pos(&insert->k); + struct bkey_i *update; + struct bkey_s_c k; + enum btree_id btree_id = orig_iter->btree_id; + int ret = 0, compressed_sectors; + + orig_iter->pos_after_commit = insert->k.p; + orig_iter->flags |= BTREE_ITER_SET_POS_AFTER_COMMIT; + + iter = bch2_trans_get_iter(trans, btree_id, start, + BTREE_ITER_INTENT| + BTREE_ITER_WITH_UPDATES| + BTREE_ITER_NOT_EXTENTS); + k = bch2_btree_iter_peek(iter); + if ((ret = bkey_err(k))) + goto err; + if (!k.k) + goto out; + + if (bch2_bkey_maybe_mergable(k.k, &insert->k)) { + update = bch2_trans_kmalloc(trans, bkey_bytes(k.k)); + if ((ret = PTR_ERR_OR_ZERO(update))) + goto err; + + bkey_reassemble(update, k); + + if (bch2_bkey_merge(c, bkey_i_to_s(update), bkey_i_to_s_c(insert))) { + update_iter = bch2_trans_copy_iter(trans, iter); + ret = bch2_btree_delete_at(trans, update_iter, flags); + bch2_trans_iter_put(trans, update_iter); + + if (ret) + goto err; + + insert = update; + goto next; + } + } + + if (!bkey_cmp(k.k->p, bkey_start_pos(&insert->k))) + goto next; + + while (bkey_cmp(insert->k.p, bkey_start_pos(k.k)) > 0) { + /* + * If we're going to be splitting a compressed extent, note it + * so that __bch2_trans_commit() can increase our disk + * reservation: + */ + if (bkey_cmp(bkey_start_pos(k.k), start) < 0 && + bkey_cmp(k.k->p, insert->k.p) > 0 && + (compressed_sectors = bch2_bkey_sectors_compressed(k))) + trans->extra_journal_res += compressed_sectors; + + 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; + + bkey_reassemble(update, k); + + bch2_cut_back(start, update); + + update_iter = bch2_trans_get_iter(trans, btree_id, update->k.p, + BTREE_ITER_NOT_EXTENTS| + BTREE_ITER_INTENT); + ret = bch2_btree_iter_traverse(update_iter) ?: + bch2_trans_update(trans, update_iter, update, + BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE| + flags); + bch2_trans_iter_put(trans, update_iter); + if (ret) + goto err; + } + + if (bkey_cmp(k.k->p, insert->k.p) <= 0) { + update_iter = bch2_trans_copy_iter(trans, iter); + ret = bch2_btree_delete_at(trans, update_iter, + flags); + bch2_trans_iter_put(trans, update_iter); + + if (ret) + goto err; + } + + 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; + + bkey_reassemble(update, k); + bch2_cut_front(insert->k.p, update); + + update_iter = bch2_trans_copy_iter(trans, iter); + bch2_trans_update(trans, update_iter, update, flags); + bch2_trans_iter_put(trans, update_iter); + goto out; + } +next: + k = bch2_btree_iter_next(iter); + if ((ret = bkey_err(k))) + goto err; + if (!k.k) + goto out; + } + + bch2_bkey_merge(c, bkey_i_to_s(insert), k); +out: + if (!bkey_deleted(&insert->k)) { + bch2_btree_iter_set_pos(iter, insert->k.p); + ret = bch2_btree_iter_traverse(iter) ?: + bch2_trans_update(trans, iter, insert, flags); + } else { + set_btree_iter_dontneed(trans, iter); + } +err: + bch2_trans_iter_put(trans, iter); + + return ret; +} + int bch2_trans_update(struct btree_trans *trans, struct btree_iter *iter, struct bkey_i *k, enum btree_update_flags flags) { @@ -995,41 +1012,19 @@ int bch2_trans_update(struct btree_trans *trans, struct btree_iter *iter, .k = k, .ip_allocated = _RET_IP_, }; - bool is_extent = (iter->flags & BTREE_ITER_IS_EXTENTS) != 0; - int ret = 0; - BUG_ON(trans->nr_updates >= BTREE_ITER_MAX); BUG_ON(!iter->should_be_locked); + if (iter->flags & BTREE_ITER_IS_EXTENTS) + return bch2_trans_update_extent(trans, iter, k, flags); + #ifdef CONFIG_BCACHEFS_DEBUG trans_for_each_update(trans, i) BUG_ON(i != trans->updates && btree_insert_entry_cmp(i - 1, i) >= 0); #endif - - if (is_extent) { - ret = extent_handle_overwrites(trans, &n); - if (ret) - return ret; - - iter->pos_after_commit = k->k.p; - iter->flags |= BTREE_ITER_SET_POS_AFTER_COMMIT; - - if (bkey_deleted(&n.k->k)) - return 0; - - n.iter = bch2_trans_get_iter(trans, n.btree_id, n.k->k.p, - BTREE_ITER_INTENT| - BTREE_ITER_NOT_EXTENTS); - n.iter->flags |= BTREE_ITER_KEEP_UNTIL_COMMIT; - ret = bch2_btree_iter_traverse(n.iter); - bch2_trans_iter_put(trans, n.iter); - - if (ret) - return ret; - } - - BUG_ON(n.iter->flags & BTREE_ITER_IS_EXTENTS); + BUG_ON(trans->nr_updates >= BTREE_ITER_MAX); + BUG_ON(bpos_cmp(n.k->k.p, n.iter->real_pos)); n.iter->flags |= BTREE_ITER_KEEP_UNTIL_COMMIT; |