btrfs: avoid repeated extent state processing when converting extent bits
authorFilipe Manana <fdmanana@suse.com>
Thu, 17 Apr 2025 15:44:34 +0000 (16:44 +0100)
committerDavid Sterba <dsterba@suse.com>
Thu, 15 May 2025 12:30:51 +0000 (14:30 +0200)
When converting bits for an extent range, if we find an extent state with
its start offset greater than current start offset, we insert a new extent
state to cover the gap, with its end offset computed and stored in the
@this_end local variable, and after the insertion we update the current
start offset to @this_end + 1. However if the insert_state() call resulted
in an extent state merge then the end offset of the merged extent may be
greater than @this_end and if that's the case, since we jump to the
'search_again' label, we'll do a full tree search that will leave us in
the same extent state - this is harmless but wastes time by doing a
pointless tree search and extent state processing.

So improve on this by updating the current start offset to the end offset
of the inserted state plus 1. This also removes the use of the @this_end
variable and directly set the value in the prealloc extent state to avoid
any confusion and misuse in the future.

Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/extent-io-tree.c

index d8d65a6a6cb1846e0d5a64d42c20fbe7a0ead20c..14383f92c38134f7b10404f0bbeb5ac29acd3aee 100644 (file)
@@ -1428,14 +1428,8 @@ hit_next:
         * extent we found.
         */
        if (state->start > start) {
-               u64 this_end;
                struct extent_state *inserted_state;
 
-               if (end < last_start)
-                       this_end = end;
-               else
-                       this_end = last_start - 1;
-
                prealloc = alloc_extent_state_atomic(prealloc);
                if (!prealloc) {
                        ret = -ENOMEM;
@@ -1447,7 +1441,11 @@ hit_next:
                 * extent.
                 */
                prealloc->start = start;
-               prealloc->end = this_end;
+               if (end < last_start)
+                       prealloc->end = end;
+               else
+                       prealloc->end = last_start - 1;
+
                inserted_state = insert_state(tree, prealloc, bits, NULL);
                if (IS_ERR(inserted_state)) {
                        ret = PTR_ERR(inserted_state);
@@ -1457,7 +1455,7 @@ hit_next:
                cache_state(inserted_state, cached_state);
                if (inserted_state == prealloc)
                        prealloc = NULL;
-               start = this_end + 1;
+               start = inserted_state->end + 1;
                goto search_again;
        }
        /*