diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2021-06-02 00:18:34 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-22 17:09:06 -0400 |
commit | 8e6bbc4181c9eb1bc8dcb0a96522447c6b6ad76e (patch) | |
tree | 272d302979217f8a7bd6cab484f2b3def734f2cf /fs/bcachefs/btree_update_leaf.c | |
parent | b1d87f527d7e6eb89395d4a0218b7e4e3974ff1b (diff) |
bcachefs: Move extent_handle_overwrites() to bch2_trans_update()
This lifts handling of overlapping extents out of __bch2_trans_commit()
and moves it to where we first do the update - which means that
BTREE_ITER_WITH_UPDATES can now work correctly in extents mode.
Also, this patch reworks how extent triggers work: previously, on
partial extent overwrite we would pass this information to the trigger,
telling it what part of the extent was being overwritten. But, this
approach has had too many subtle corner cases - now, we only mark whole
extents, meaning on partial extent overwrite we unmark the old extent
and mark the new extent.
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Diffstat (limited to 'fs/bcachefs/btree_update_leaf.c')
-rw-r--r-- | fs/bcachefs/btree_update_leaf.c | 157 |
1 files changed, 41 insertions, 116 deletions
diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c index 123127980853..0a31270e3caf 100644 --- a/fs/bcachefs/btree_update_leaf.c +++ b/fs/bcachefs/btree_update_leaf.c @@ -775,7 +775,7 @@ bch2_trans_commit_get_rw_cold(struct btree_trans *trans) return 0; } -static void __bch2_trans_update2(struct btree_trans *trans, +static void bch2_trans_update2(struct btree_trans *trans, struct btree_insert_entry n) { struct btree_insert_entry *i; @@ -798,44 +798,23 @@ static void __bch2_trans_update2(struct btree_trans *trans, i - trans->updates2, n); } -static void bch2_trans_update2(struct btree_trans *trans, - struct btree_iter *iter, - struct bkey_i *insert) -{ - __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, - .iter = iter, - .k = insert, - }); -} - static int extent_update_to_keys(struct btree_trans *trans, struct btree_insert_entry n) { - int ret; - - ret = bch2_extent_can_insert(trans, n.iter, n.k); - if (ret) - return ret; - - if (bkey_deleted(&n.k->k)) - return 0; - n.iter = bch2_trans_get_iter(trans, n.iter->btree_id, n.k->k.p, BTREE_ITER_INTENT| BTREE_ITER_NOT_EXTENTS); n.is_extent = false; - __bch2_trans_update2(trans, n); + bch2_trans_update2(trans, n); bch2_trans_iter_put(trans, n.iter); return 0; } static int extent_handle_overwrites(struct btree_trans *trans, enum btree_id btree_id, - struct bkey_i *insert) + struct bkey_i *insert, + unsigned trigger_flags) { struct btree_iter *iter, *update_iter; struct bpos start = bkey_start_pos(&insert->k); @@ -861,7 +840,8 @@ static int extent_handle_overwrites(struct btree_trans *trans, 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_update(trans, update_iter, update, + trigger_flags); bch2_trans_iter_put(trans, update_iter); } @@ -877,7 +857,8 @@ static int extent_handle_overwrites(struct btree_trans *trans, 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_update(trans, update_iter, update, + trigger_flags); bch2_trans_iter_put(trans, update_iter); } @@ -892,7 +873,8 @@ static int extent_handle_overwrites(struct btree_trans *trans, 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_update(trans, update_iter, update, + trigger_flags); bch2_trans_iter_put(trans, update_iter); break; } @@ -962,18 +944,10 @@ int __bch2_trans_commit(struct btree_trans *trans) } } while (trans_trigger_run); - /* Turn extents updates into keys: */ - trans_for_each_update(trans, i) - if (i->is_extent) { - 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), 0); + : (bch2_trans_update2(trans, *i), 0); if (unlikely(ret)) goto out; } @@ -1051,6 +1025,7 @@ int bch2_trans_update(struct btree_trans *trans, struct btree_iter *iter, .iter = iter, .k = k }; + int ret = 0; BUG_ON(trans->nr_updates >= BTREE_ITER_MAX); @@ -1067,97 +1042,47 @@ int bch2_trans_update(struct btree_trans *trans, struct btree_iter *iter, } #endif - iter->flags |= BTREE_ITER_KEEP_UNTIL_COMMIT; - if (n.is_extent) { + ret = bch2_extent_can_insert(trans, n.iter, n.k); + if (ret) + return ret; + + ret = extent_handle_overwrites(trans, n.btree_id, n.k, flags); + 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.iter->btree_id, n.k->k.p, + BTREE_ITER_INTENT| + BTREE_ITER_NOT_EXTENTS); + bch2_trans_iter_put(trans, n.iter); + n.is_extent = false; } + BUG_ON(n.iter->flags & BTREE_ITER_IS_EXTENTS); + + n.iter->flags |= BTREE_ITER_KEEP_UNTIL_COMMIT; + /* * Pending updates are kept sorted: first, find position of new update, * then delete/trim any updates the new update overwrites: */ - if (!n.is_extent) { - trans_for_each_update(trans, i) - if (btree_insert_entry_cmp(&n, i) <= 0) - break; - - if (i < trans->updates + trans->nr_updates && - !btree_insert_entry_cmp(&n, i)) - *i = n; - else - array_insert_item(trans->updates, trans->nr_updates, - i - trans->updates, n); - } else { - trans_for_each_update(trans, i) - if (btree_insert_entry_cmp(&n, i) < 0) - break; - - while (i > trans->updates && - i[-1].btree_id == n.btree_id && - bkey_cmp(bkey_start_pos(&n.k->k), - bkey_start_pos(&i[-1].k->k)) <= 0) { - --i; - array_remove_item(trans->updates, trans->nr_updates, - i - trans->updates); - } - - if (i > trans->updates && - i[-1].btree_id == n.btree_id && - bkey_cmp(bkey_start_pos(&n.k->k), i[-1].k->k.p) < 0) - bch2_cut_back(bkey_start_pos(&n.k->k), i[-1].k); - - if (i < trans->updates + trans->nr_updates && - i->btree_id == n.btree_id && - bkey_cmp(n.k->k.p, bkey_start_pos(&i->k->k)) > 0) { - if (bkey_cmp(bkey_start_pos(&n.k->k), - bkey_start_pos(&i->k->k)) > 0) { - struct btree_insert_entry split = *i; - int ret; - - BUG_ON(trans->nr_updates + 1 >= BTREE_ITER_MAX); - - split.k = bch2_trans_kmalloc(trans, bkey_bytes(&i->k->k)); - ret = PTR_ERR_OR_ZERO(split.k); - if (ret) - return ret; - - bkey_copy(split.k, i->k); - bch2_cut_back(bkey_start_pos(&n.k->k), split.k); - - split.iter = bch2_trans_get_iter(trans, split.btree_id, - bkey_start_pos(&split.k->k), - BTREE_ITER_INTENT); - split.iter->flags |= BTREE_ITER_KEEP_UNTIL_COMMIT; - bch2_trans_iter_put(trans, split.iter); - array_insert_item(trans->updates, trans->nr_updates, - i - trans->updates, split); - i++; - } - - /* - * When we have an extent that overwrites the start of another - * update, trimming that extent will mean the iterator's - * position has to change since the iterator position has to - * match the extent's start pos - but we don't want to change - * the iterator pos if some other code is using it, so we may - * need to clone it: - */ - if (btree_iter_live(trans, i->iter)) { - i->iter = bch2_trans_copy_iter(trans, i->iter); - - i->iter->flags |= BTREE_ITER_KEEP_UNTIL_COMMIT; - bch2_trans_iter_put(trans, i->iter); - } - - bch2_cut_front(n.k->k.p, i->k); - bch2_btree_iter_set_pos(i->iter, n.k->k.p); - } + trans_for_each_update(trans, i) + if (btree_insert_entry_cmp(&n, i) <= 0) + break; + if (i < trans->updates + trans->nr_updates && + !btree_insert_entry_cmp(&n, i)) { + BUG_ON(i->trans_triggers_run); + *i = n; + } else array_insert_item(trans->updates, trans->nr_updates, i - trans->updates, n); - } return 0; } |