Linux Btrfs filesystem development
 help / color / mirror / Atom feed
* [PATCH v2 0/7] btrfs: allocator perf improvements
@ 2026-10-22 17:06 Boris Burkov
  2026-10-22 17:06 ` [PATCH v2 1/7] btrfs: skip unhelpful size class relaxing allocation loops Boris Burkov
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Boris Burkov @ 2026-10-22 17:06 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

Working on the bugs to do with large fs-es and unused block groups

https://lore.kernel.org/linux-btrfs/20260916230447.GA1706558@zen.localdomain/T/#t
and
https://lore.kernel.org/linux-btrfs/cover.1790641111.git.boris@bur.io/T/#t

revealed some low hanging fruit in allocation performance for very large
mostly full fs-es. The gist is to try to skip unnecessary operations per block
group which adds up with 10s of thousands of obviously skippable block
groups. Running 20k fallocates in a loop on a sparse file fs improved from
~40s to ~7s.

Changelog:
v2:
- removed data_rwsem and delalloc_bytes from block_group and find_free_extent()


Boris Burkov (7):
  btrfs: skip unhelpful size class relaxing allocation loops
  btrfs: don't take block group references in find_free_extent()
  btrfs: remove redundant checks in find_free_extent() hint path
  btrfs: factor the find_free_extent() block group skip into a helper
  btrfs: find_free_extent checks full block groups unlocked
  btrfs: find_free_extent checks size class unlocked
  btrfs: remove block_group data_rwsem and delalloc_bytes

 fs/btrfs/block-group.c |  12 +--
 fs/btrfs/block-group.h |  13 +---
 fs/btrfs/direct-io.c   |   4 +-
 fs/btrfs/extent-tree.c | 166 +++++++++++++++++------------------------
 fs/btrfs/extent-tree.h |   9 ++-
 fs/btrfs/inode.c       |  36 +++------
 fs/btrfs/relocation.c  |  16 ++--
 fs/btrfs/space-info.c  |   5 +-
 8 files changed, 100 insertions(+), 161 deletions(-)

-- 
2.56.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v2 1/7] btrfs: skip unhelpful size class relaxing allocation loops
  2026-10-22 17:06 [PATCH v2 0/7] btrfs: allocator perf improvements Boris Burkov
@ 2026-10-22 17:06 ` Boris Burkov
  2026-10-22 17:07 ` [PATCH v2 2/7] btrfs: don't take block group references in find_free_extent() Boris Burkov
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Boris Burkov @ 2026-10-22 17:06 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

When size class was not a factor on a previous loop, there is no real
point to running a loop with relaxed size class rules. So track whether
we ever actually skipped a bg due to size class and only do those loops
when it is relevant.

Signed-off-by: Boris Burkov <boris@bur.io>
---
 fs/btrfs/extent-tree.c | 12 +++++++++++-
 fs/btrfs/extent-tree.h |  3 +++
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 9b0a5c6b96f3..f6f4f1ce3f1f 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -4361,6 +4361,9 @@ static int find_free_extent_update_loop(struct btrfs_fs_info *fs_info,
 	    (!ffe_ctl->orig_have_caching_bg && full_search))
 		ffe_ctl->loop++;
 	ffe_ctl->loop++;
+	/* Relaxing the size class cannot help if no block group was skipped for it. */
+	if (ffe_ctl->loop == LOOP_UNSET_SIZE_CLASS && !ffe_ctl->size_class_skipped)
+		ffe_ctl->loop++;
 
 	if (ffe_ctl->loop == LOOP_ALLOC_CHUNK) {
 		struct btrfs_trans_handle *trans;
@@ -4400,6 +4403,9 @@ static int find_free_extent_update_loop(struct btrfs_fs_info *fs_info,
 			return ret;
 	}
 
+	if (ffe_ctl->loop == LOOP_WRONG_SIZE_CLASS && !ffe_ctl->size_class_skipped)
+		ffe_ctl->loop++;
+
 	if (ffe_ctl->loop == LOOP_NO_EMPTY_SIZE) {
 		if (ffe_ctl->policy != BTRFS_EXTENT_ALLOC_CLUSTERED)
 			return -ENOSPC;
@@ -4414,6 +4420,7 @@ static int find_free_extent_update_loop(struct btrfs_fs_info *fs_info,
 		ffe_ctl->empty_cluster = 0;
 	}
 
+	ffe_ctl->size_class_skipped = false;
 	return 1;
 }
 
@@ -4577,6 +4584,7 @@ static noinline int find_free_extent(struct btrfs_root *root,
 	ffe_ctl->index = btrfs_bg_flags_to_raid_index(ffe_ctl->flags);
 	ffe_ctl->loop = 0;
 	ffe_ctl->retry_uncached = false;
+	ffe_ctl->size_class_skipped = false;
 	ffe_ctl->cached = 0;
 	ffe_ctl->max_extent_size = 0;
 	ffe_ctl->total_free_space = 0;
@@ -4738,8 +4746,10 @@ static noinline int find_free_extent(struct btrfs_root *root,
 			goto loop;
 		}
 
-		if (!find_free_extent_check_size_class(ffe_ctl, block_group))
+		if (!find_free_extent_check_size_class(ffe_ctl, block_group)) {
+			ffe_ctl->size_class_skipped = true;
 			goto loop;
+		}
 
 		bg_ret = NULL;
 		ret = do_allocation(block_group, ffe_ctl, &bg_ret);
diff --git a/fs/btrfs/extent-tree.h b/fs/btrfs/extent-tree.h
index ff330d4896d6..ecb2a1bf2435 100644
--- a/fs/btrfs/extent-tree.h
+++ b/fs/btrfs/extent-tree.h
@@ -59,6 +59,9 @@ struct find_free_extent_ctl {
 	/* Whether or not the allocator is currently following a hint. */
 	bool hinted;
 
+	/* A block group was skipped for its size class during this loop. */
+	bool size_class_skipped;
+
 	/* RAID index, converted from flags */
 	int index;
 
-- 
2.56.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 2/7] btrfs: don't take block group references in find_free_extent()
  2026-10-22 17:06 [PATCH v2 0/7] btrfs: allocator perf improvements Boris Burkov
  2026-10-22 17:06 ` [PATCH v2 1/7] btrfs: skip unhelpful size class relaxing allocation loops Boris Burkov
@ 2026-10-22 17:07 ` Boris Burkov
  2026-10-22 17:07 ` [PATCH v2 3/7] btrfs: remove redundant checks in find_free_extent() hint path Boris Burkov
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Boris Burkov @ 2026-10-22 17:07 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

The get/put pair inside the loop in find_free_extent() is pointless
because the loop is done while holding space_info->groups_sem which is
exclusive with any task deleting the block_group from the raid array,
which also holds a reference. So this can never be the last reference.

Therefore, we can skip the bother of inc/dec-ing the refcount which can
save a considerable amount of time on filesystems with a large number of
full block groups.

A little care must be taken to properly put the refcount for the hint
and bg cluster cases that pick a bg more directly.

Measured on a 30T single-device filesystem on a tmpfs-backed loop device:
  20k sequential 1G fallocates:                     40.1s -> 27.1s
  sync of 20k new 64K files after 20k full 1G bgs:  18.4s -> 13.0s

Assisted-by: LLM
Signed-off-by: Boris Burkov <boris@bur.io>
---
 fs/btrfs/extent-tree.c | 23 ++++++++++++++---------
 1 file changed, 14 insertions(+), 9 deletions(-)

diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index f6f4f1ce3f1f..2c06d3f17746 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -3773,12 +3773,11 @@ btrfs_lock_block_group(struct btrfs_block_group *cache, bool delalloc)
 		down_read(&cache->data_rwsem);
 }
 
-static inline void btrfs_grab_block_group(struct btrfs_block_group *cache,
-					  bool delalloc)
+static inline void
+btrfs_unlock_block_group(struct btrfs_block_group *cache, bool delalloc)
 {
-	btrfs_get_block_group(cache);
 	if (delalloc)
-		down_read(&cache->data_rwsem);
+		up_read(&cache->data_rwsem);
 }
 
 static struct btrfs_block_group *btrfs_lock_cluster(
@@ -4222,7 +4221,7 @@ static void release_block_group(struct btrfs_block_group *block_group,
 
 	BUG_ON(btrfs_bg_flags_to_raid_index(block_group->flags) !=
 	       ffe_ctl->index);
-	btrfs_release_block_group(block_group, delalloc);
+	btrfs_unlock_block_group(block_group, delalloc);
 }
 
 static void found_extent_clustered(struct find_free_extent_ctl *ffe_ctl,
@@ -4655,6 +4654,7 @@ static noinline int find_free_extent(struct btrfs_root *root,
 			} else {
 				ffe_ctl->index = btrfs_bg_flags_to_raid_index(
 							block_group->flags);
+				btrfs_put_block_group(block_group);
 				btrfs_lock_block_group(block_group,
 						       ffe_ctl->delalloc);
 				ffe_ctl->hinted = true;
@@ -4686,7 +4686,7 @@ static noinline int find_free_extent(struct btrfs_root *root,
 			continue;
 		}
 
-		btrfs_grab_block_group(block_group, ffe_ctl->delalloc);
+		btrfs_lock_block_group(block_group, ffe_ctl->delalloc);
 		ffe_ctl->search_start = block_group->start;
 
 		/*
@@ -4713,7 +4713,7 @@ static noinline int find_free_extent(struct btrfs_root *root,
 			 * It's possible that we have MIXED_GROUP flag but no
 			 * block group is mixed.  Just skip such block group.
 			 */
-			btrfs_release_block_group(block_group, ffe_ctl->delalloc);
+			btrfs_unlock_block_group(block_group, ffe_ctl->delalloc);
 			continue;
 		}
 
@@ -4757,7 +4757,12 @@ static noinline int find_free_extent(struct btrfs_root *root,
 			goto loop;
 
 		if (bg_ret && bg_ret != block_group) {
-			btrfs_release_block_group(block_group, ffe_ctl->delalloc);
+			btrfs_unlock_block_group(block_group, ffe_ctl->delalloc);
+			/*
+			 * bg_ret is still on the list: btrfs_remove_block_group()
+			 * detaches it from the cluster before list_del_init().
+			 */
+			btrfs_put_block_group(bg_ret);
 			block_group = bg_ret;
 		}
 
@@ -4796,7 +4801,7 @@ static noinline int find_free_extent(struct btrfs_root *root,
 		ins->offset = ffe_ctl->num_bytes;
 
 		trace_btrfs_reserve_extent(block_group, ffe_ctl);
-		btrfs_release_block_group(block_group, ffe_ctl->delalloc);
+		btrfs_unlock_block_group(block_group, ffe_ctl->delalloc);
 		break;
 loop:
 		if (!ffe_ctl->cached && ffe_ctl->loop > LOOP_CACHING_NOWAIT &&
-- 
2.56.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 3/7] btrfs: remove redundant checks in find_free_extent() hint path
  2026-10-22 17:06 [PATCH v2 0/7] btrfs: allocator perf improvements Boris Burkov
  2026-10-22 17:06 ` [PATCH v2 1/7] btrfs: skip unhelpful size class relaxing allocation loops Boris Burkov
  2026-10-22 17:07 ` [PATCH v2 2/7] btrfs: don't take block group references in find_free_extent() Boris Burkov
@ 2026-10-22 17:07 ` Boris Burkov
  2026-10-22 17:07 ` [PATCH v2 4/7] btrfs: factor the find_free_extent() block group skip into a helper Boris Burkov
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Boris Burkov @ 2026-10-22 17:07 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

The hint is a long lasting loose reference to a block group which can
outlast the block group or race its destruction. Therefore, using it
from the hint must check that it is still attached to the list of block
groups. However, the other checks are not special to hints and can be
shared with block groups reached normally. So make the hint path check
only the thing that is truly relevant to hints.

Assisted-by: LLM
Signed-off-by: Boris Burkov <boris@bur.io>
---
 fs/btrfs/extent-tree.c | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 2c06d3f17746..afa9332ee2ec 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -4640,12 +4640,10 @@ static noinline int find_free_extent(struct btrfs_root *root,
 		    block_group->space_info == space_info &&
 		    block_group->cached != BTRFS_CACHE_NO) {
 			down_read(&space_info->groups_sem);
-			if (list_empty(&block_group->list) ||
-			    block_group->ro ||
-			    (block_group->flags & BTRFS_BLOCK_GROUP_REMAPPED)) {
+			if (list_empty(&block_group->list)) {
 				/*
 				 * someone is removing this block group,
-				 * we can't jump into the have_block_group
+				 * we can't jump into the check_block_group
 				 * target because our list pointers are not
 				 * valid
 				 */
@@ -4655,10 +4653,8 @@ static noinline int find_free_extent(struct btrfs_root *root,
 				ffe_ctl->index = btrfs_bg_flags_to_raid_index(
 							block_group->flags);
 				btrfs_put_block_group(block_group);
-				btrfs_lock_block_group(block_group,
-						       ffe_ctl->delalloc);
 				ffe_ctl->hinted = true;
-				goto have_block_group;
+				goto check_block_group;
 			}
 		} else if (block_group) {
 			btrfs_put_block_group(block_group);
@@ -4676,6 +4672,8 @@ static noinline int find_free_extent(struct btrfs_root *root,
 		struct btrfs_block_group *bg_ret;
 
 		ffe_ctl->hinted = false;
+		ffe_ctl->search_start = block_group->start;
+check_block_group:
 		/* If the block group is read-only, we can skip it entirely. */
 		if (unlikely(block_group->ro ||
 			     (block_group->flags & BTRFS_BLOCK_GROUP_REMAPPED))) {
@@ -4687,7 +4685,6 @@ static noinline int find_free_extent(struct btrfs_root *root,
 		}
 
 		btrfs_lock_block_group(block_group, ffe_ctl->delalloc);
-		ffe_ctl->search_start = block_group->start;
 
 		/*
 		 * this can happen if we end up cycling through all the
-- 
2.56.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 4/7] btrfs: factor the find_free_extent() block group skip into a helper
  2026-10-22 17:06 [PATCH v2 0/7] btrfs: allocator perf improvements Boris Burkov
                   ` (2 preceding siblings ...)
  2026-10-22 17:07 ` [PATCH v2 3/7] btrfs: remove redundant checks in find_free_extent() hint path Boris Burkov
@ 2026-10-22 17:07 ` Boris Burkov
  2026-10-22 17:07 ` [PATCH v2 5/7] btrfs: find_free_extent checks full block groups unlocked Boris Burkov
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Boris Burkov @ 2026-10-22 17:07 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

find_free_extent() is already quite unwieldy so I believe a well defined
"usability check" is a helpful thing to pull out into a named static
function just to break things down into easier to grok components.

No functional change.

Signed-off-by: Boris Burkov <boris@bur.io>
---
 fs/btrfs/extent-tree.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index afa9332ee2ec..67765797554c 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -4317,6 +4317,18 @@ static int can_allocate_chunk(struct btrfs_fs_info *fs_info,
 	}
 }
 
+static bool find_free_extent_skip_block_group(struct btrfs_block_group *block_group,
+					      struct find_free_extent_ctl *ffe_ctl)
+{
+	if (likely(!block_group->ro && !(block_group->flags & BTRFS_BLOCK_GROUP_REMAPPED)))
+		return false;
+	if (ffe_ctl->for_treelog)
+		btrfs_clear_treelog_bg(block_group);
+	if (ffe_ctl->for_data_reloc)
+		btrfs_clear_data_reloc_bg(block_group);
+	return true;
+}
+
 /*
  * Return >0 means caller needs to re-search for free extent
  * Return 0 means we have the needed free extent.
@@ -4674,15 +4686,8 @@ static noinline int find_free_extent(struct btrfs_root *root,
 		ffe_ctl->hinted = false;
 		ffe_ctl->search_start = block_group->start;
 check_block_group:
-		/* If the block group is read-only, we can skip it entirely. */
-		if (unlikely(block_group->ro ||
-			     (block_group->flags & BTRFS_BLOCK_GROUP_REMAPPED))) {
-			if (ffe_ctl->for_treelog)
-				btrfs_clear_treelog_bg(block_group);
-			if (ffe_ctl->for_data_reloc)
-				btrfs_clear_data_reloc_bg(block_group);
+		if (find_free_extent_skip_block_group(block_group, ffe_ctl))
 			continue;
-		}
 
 		btrfs_lock_block_group(block_group, ffe_ctl->delalloc);
 
-- 
2.56.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 5/7] btrfs: find_free_extent checks full block groups unlocked
  2026-10-22 17:06 [PATCH v2 0/7] btrfs: allocator perf improvements Boris Burkov
                   ` (3 preceding siblings ...)
  2026-10-22 17:07 ` [PATCH v2 4/7] btrfs: factor the find_free_extent() block group skip into a helper Boris Burkov
@ 2026-10-22 17:07 ` Boris Burkov
  2026-10-22 17:07 ` [PATCH v2 6/7] btrfs: find_free_extent checks size class unlocked Boris Burkov
  2026-10-22 17:07 ` [PATCH v2 7/7] btrfs: remove block_group data_rwsem and delalloc_bytes Boris Burkov
  6 siblings, 0 replies; 8+ messages in thread
From: Boris Burkov @ 2026-10-22 17:07 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

No matter how you slice it, a block group with less free space than the
allocation requires cannot satisfy the allocation, so we can skip it. We
can do this check without taking a lock because it saying yes does *not*
mean that we definitely do find the space locked properly later when
doing the real allocation. But racing with a free and skipping here,
even if we might have said yes could still have raced the same way with
the lock and the allocation still would have failed. On top of that,
this has many fallbacks like the multiple find_free_extent loops and the
fact that on failure we reduce the allocation size and try again.

This helps improve performance on a common case where we have many full
block groups in a large filesystem and want to rapidly skip them.

Measured on a 30T single-device filesystem on a tmpfs-backed loop device:
  20k sequential 1G fallocates:                           26.9s -> 6.7s
  sync of 20k new 64K files after 20k full 1G bgs:        12.7s -> 3.7s
  sync of 20k new 64K files after 20k 1000M fallocates:   12.6s -> 13.2s

Assisted-by: LLM
Signed-off-by: Boris Burkov <boris@bur.io>
---
 fs/btrfs/extent-tree.c | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 67765797554c..8b57798c2d94 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -4320,7 +4320,23 @@ static int can_allocate_chunk(struct btrfs_fs_info *fs_info,
 static bool find_free_extent_skip_block_group(struct btrfs_block_group *block_group,
 					      struct find_free_extent_ctl *ffe_ctl)
 {
-	if (likely(!block_group->ro && !(block_group->flags & BTRFS_BLOCK_GROUP_REMAPPED)))
+	bool skip = block_group->ro || (block_group->flags & BTRFS_BLOCK_GROUP_REMAPPED);
+
+	/*
+	 * caching_thread() sets FINISHED under a a separate block_group->lock
+	 * critical section after it is done populating, so smp_load_acquire
+	 * guarantees we see the block group as populated by caching.
+	 */
+	if (!skip && smp_load_acquire(&block_group->cached) == BTRFS_CACHE_FINISHED) {
+		u64 free_space = data_race(block_group->free_space_ctl->free_space);
+
+		if (free_space < ffe_ctl->num_bytes) {
+			ffe_ctl->total_free_space = max(ffe_ctl->total_free_space,
+							free_space);
+			skip = true;
+		}
+	}
+	if (!skip)
 		return false;
 	if (ffe_ctl->for_treelog)
 		btrfs_clear_treelog_bg(block_group);
-- 
2.56.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 6/7] btrfs: find_free_extent checks size class unlocked
  2026-10-22 17:06 [PATCH v2 0/7] btrfs: allocator perf improvements Boris Burkov
                   ` (4 preceding siblings ...)
  2026-10-22 17:07 ` [PATCH v2 5/7] btrfs: find_free_extent checks full block groups unlocked Boris Burkov
@ 2026-10-22 17:07 ` Boris Burkov
  2026-10-22 17:07 ` [PATCH v2 7/7] btrfs: remove block_group data_rwsem and delalloc_bytes Boris Burkov
  6 siblings, 0 replies; 8+ messages in thread
From: Boris Burkov @ 2026-10-22 17:07 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

Similar to the free space check, it doesn't hurt to skip a block group
for having the wrong size class even if it maybe was just about to
get reset to no size class. Furthermore, setting the size class already
admits that races are possible and that there is no guarantee of
perfection of matching size classes, just that we only set it once per
bg per reset.

This can also help quickly iterate past thousands of wrong size class
bgs in a large fs without taking bg locks on each pass.

Measured on a 30T single-device filesystem on a tmpfs-backed loop device:
  20k sequential 1G fallocates:                            6.7s -> 7.0s
  sync of 20k new 64K files after 20k full 1G bgs:         3.7s -> 3.8s
  sync of 20k new 64K files after 20k 1000M fallocates:   13.2s -> 4.8s

Assisted-by: LLM
Signed-off-by: Boris Burkov <boris@bur.io>
---
 fs/btrfs/extent-tree.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 8b57798c2d94..80f2c735f432 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -4334,6 +4334,9 @@ static bool find_free_extent_skip_block_group(struct btrfs_block_group *block_gr
 			ffe_ctl->total_free_space = max(ffe_ctl->total_free_space,
 							free_space);
 			skip = true;
+		} else if (!find_free_extent_check_size_class(ffe_ctl, block_group)) {
+			ffe_ctl->size_class_skipped = true;
+			skip = true;
 		}
 	}
 	if (!skip)
-- 
2.56.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 7/7] btrfs: remove block_group data_rwsem and delalloc_bytes
  2026-10-22 17:06 [PATCH v2 0/7] btrfs: allocator perf improvements Boris Burkov
                   ` (5 preceding siblings ...)
  2026-10-22 17:07 ` [PATCH v2 6/7] btrfs: find_free_extent checks size class unlocked Boris Burkov
@ 2026-10-22 17:07 ` Boris Burkov
  6 siblings, 0 replies; 8+ messages in thread
From: Boris Burkov @ 2026-10-22 17:07 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

The v1 space cache was the only real user of the two fields.

994a93e11f49 ("btrfs: remove the v1 space cache write path") removed the
v1 space cache so now data_rwsem has no code path that write locks it
and delalloc_bytes is only printed, so both can be removed.

Luckily, this also removes a bunch of confusing indirection machinery
dedicated to separating delalloc calls to btrfs_reserve_extent() from
non-delalloc calls.

Assisted-by: LLM
Signed-off-by: Boris Burkov <boris@bur.io>
---
 fs/btrfs/block-group.c | 12 +-----
 fs/btrfs/block-group.h | 13 +-----
 fs/btrfs/direct-io.c   |  4 +-
 fs/btrfs/extent-tree.c | 94 +++++++-----------------------------------
 fs/btrfs/extent-tree.h |  6 +--
 fs/btrfs/inode.c       | 36 ++++------------
 fs/btrfs/relocation.c  | 16 +++----
 fs/btrfs/space-info.c  |  5 +--
 8 files changed, 43 insertions(+), 143 deletions(-)

diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c
index 477c14fbcb4c..8c41ec5ce570 100644
--- a/fs/btrfs/block-group.c
+++ b/fs/btrfs/block-group.c
@@ -2435,7 +2435,6 @@ static struct btrfs_block_group *btrfs_create_block_group(
 
 	refcount_set(&cache->refs, 1);
 	spin_lock_init(&cache->lock);
-	init_rwsem(&cache->data_rwsem);
 	INIT_LIST_HEAD(&cache->list);
 	INIT_LIST_HEAD(&cache->cluster_list);
 	INIT_LIST_HEAD(&cache->bg_list);
@@ -3643,14 +3642,13 @@ int btrfs_update_block_group(struct btrfs_trans_handle *trans,
  * @ram_bytes:  The number of bytes of file content, and will be same to
  *              @num_bytes except for the compress path.
  * @num_bytes:	The number of bytes in question
- * @delalloc:   The blocks are allocated for the delalloc write
  *
  * This is called by the allocator when it reserves space. If this is a
  * reservation and the block group has become read only we cannot make the
  * reservation and return -EAGAIN, otherwise this function always succeeds.
  */
 int btrfs_add_reserved_bytes(struct btrfs_block_group *cache,
-			     u64 ram_bytes, u64 num_bytes, bool delalloc,
+			     u64 ram_bytes, u64 num_bytes,
 			     bool force_wrong_size_class)
 {
 	struct btrfs_space_info *space_info = cache->space_info;
@@ -3672,8 +3670,6 @@ int btrfs_add_reserved_bytes(struct btrfs_block_group *cache,
 	}
 
 	cache->reserved += num_bytes;
-	if (delalloc)
-		cache->delalloc_bytes += num_bytes;
 
 	trace_btrfs_space_reservation(cache->fs_info, "space_info",
 				      space_info->flags, num_bytes, 1);
@@ -3703,15 +3699,13 @@ int btrfs_add_reserved_bytes(struct btrfs_block_group *cache,
  *
  * @cache:       The cache we are manipulating.
  * @num_bytes:   The number of bytes in question.
- * @is_delalloc: Whether the blocks are allocated for a delalloc write.
  *
  * This is called by somebody who is freeing space that was never actually used
  * on disk.  For example if you reserve some space for a new leaf in transaction
  * A and before transaction A commits you free that leaf, you call this with
  * reserve set to 0 in order to clear the reservation.
  */
-void btrfs_free_reserved_bytes(struct btrfs_block_group *cache, u64 num_bytes,
-			       bool is_delalloc)
+void btrfs_free_reserved_bytes(struct btrfs_block_group *cache, u64 num_bytes)
 {
 	struct btrfs_space_info *space_info = cache->space_info;
 	bool bg_ro;
@@ -3721,8 +3715,6 @@ void btrfs_free_reserved_bytes(struct btrfs_block_group *cache, u64 num_bytes,
 	bg_ro = cache->ro;
 	cache->reserved -= num_bytes;
 	btrfs_maybe_reset_size_class(cache);
-	if (is_delalloc)
-		cache->delalloc_bytes -= num_bytes;
 	spin_unlock(&cache->lock);
 
 	if (bg_ro)
diff --git a/fs/btrfs/block-group.h b/fs/btrfs/block-group.h
index d567ed822e55..b33705dc088c 100644
--- a/fs/btrfs/block-group.h
+++ b/fs/btrfs/block-group.h
@@ -121,7 +121,6 @@ struct btrfs_block_group {
 	u64 pinned;
 	u64 reserved;
 	u64 used;
-	u64 delalloc_bytes;
 	u64 bytes_super;
 	u64 flags;
 	u64 global_root_id;
@@ -152,13 +151,6 @@ struct btrfs_block_group {
 	 */
 	u32 bitmap_low_thresh;
 
-	/*
-	 * It is just used for the delayed data space allocation because
-	 * only the data space allocation and the relative metadata update
-	 * can be done cross the transaction.
-	 */
-	struct rw_semaphore data_rwsem;
-
 	/* For raid56, this is a full stripe, without parity */
 	unsigned long full_stripe_len;
 	unsigned long runtime_flags;
@@ -358,10 +350,9 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans);
 int btrfs_update_block_group(struct btrfs_trans_handle *trans,
 			     u64 bytenr, u64 num_bytes, bool alloc);
 int btrfs_add_reserved_bytes(struct btrfs_block_group *cache,
-			     u64 ram_bytes, u64 num_bytes, bool delalloc,
+			     u64 ram_bytes, u64 num_bytes,
 			     bool force_wrong_size_class);
-void btrfs_free_reserved_bytes(struct btrfs_block_group *cache, u64 num_bytes,
-			       bool is_delalloc);
+void btrfs_free_reserved_bytes(struct btrfs_block_group *cache, u64 num_bytes);
 int btrfs_chunk_alloc(struct btrfs_trans_handle *trans,
 		      struct btrfs_space_info *space_info, u64 flags,
 		      enum btrfs_chunk_alloc_enum force);
diff --git a/fs/btrfs/direct-io.c b/fs/btrfs/direct-io.c
index ed3914257d39..96c0c9ccc179 100644
--- a/fs/btrfs/direct-io.c
+++ b/fs/btrfs/direct-io.c
@@ -186,7 +186,7 @@ static struct extent_map *btrfs_new_extent_direct(struct btrfs_inode *inode,
 	alloc_hint = btrfs_get_extent_allocation_hint(inode, start, len);
 again:
 	ret = btrfs_reserve_extent(root, len, len, fs_info->sectorsize,
-				   0, alloc_hint, &ins, true, true);
+				   0, alloc_hint, &ins, true);
 	if (ret == -EAGAIN) {
 		ASSERT(btrfs_is_zoned(fs_info));
 		wait_on_bit_io(&inode->root->fs_info->flags, BTRFS_FS_NEED_ZONE_FINISH,
@@ -206,7 +206,7 @@ static struct extent_map *btrfs_new_extent_direct(struct btrfs_inode *inode,
 				     BTRFS_ORDERED_REGULAR);
 	btrfs_dec_block_group_reservations(fs_info, ins.objectid);
 	if (IS_ERR(em))
-		btrfs_free_reserved_extent(fs_info, ins.objectid, ins.offset, true);
+		btrfs_free_reserved_extent(fs_info, ins.objectid, ins.offset);
 
 	return em;
 }
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 80f2c735f432..cce2d314a000 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -3695,7 +3695,7 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans,
 	WARN_ON(test_bit(EXTENT_BUFFER_DIRTY, &buf->bflags));
 
 	btrfs_add_free_space(bg, buf->start, buf->len);
-	btrfs_free_reserved_bytes(bg, buf->len, false);
+	btrfs_free_reserved_bytes(bg, buf->len);
 	btrfs_put_block_group(bg);
 	trace_btrfs_reserved_extent_free(fs_info, buf->start, buf->len);
 
@@ -3766,65 +3766,18 @@ enum btrfs_loop_type {
 	LOOP_NO_EMPTY_SIZE,
 };
 
-static inline void
-btrfs_lock_block_group(struct btrfs_block_group *cache, bool delalloc)
-{
-	if (delalloc)
-		down_read(&cache->data_rwsem);
-}
-
-static inline void
-btrfs_unlock_block_group(struct btrfs_block_group *cache, bool delalloc)
-{
-	if (delalloc)
-		up_read(&cache->data_rwsem);
-}
-
 static struct btrfs_block_group *btrfs_lock_cluster(
 		   struct btrfs_block_group *block_group,
-		   struct btrfs_free_cluster *cluster,
-		   bool delalloc)
+		   struct btrfs_free_cluster *cluster)
 	__acquires(&cluster->refill_lock)
 {
-	struct btrfs_block_group *used_bg = NULL;
+	struct btrfs_block_group *used_bg;
 
 	spin_lock(&cluster->refill_lock);
-	while (1) {
-		used_bg = cluster->block_group;
-		if (!used_bg)
-			return NULL;
-
-		if (used_bg == block_group)
-			return used_bg;
-
+	used_bg = cluster->block_group;
+	if (used_bg && used_bg != block_group)
 		btrfs_get_block_group(used_bg);
-
-		if (!delalloc)
-			return used_bg;
-
-		if (down_read_trylock(&used_bg->data_rwsem))
-			return used_bg;
-
-		spin_unlock(&cluster->refill_lock);
-
-		/* We should only have one-level nested. */
-		down_read_nested(&used_bg->data_rwsem, SINGLE_DEPTH_NESTING);
-
-		spin_lock(&cluster->refill_lock);
-		if (used_bg == cluster->block_group)
-			return used_bg;
-
-		up_read(&used_bg->data_rwsem);
-		btrfs_put_block_group(used_bg);
-	}
-}
-
-static inline void
-btrfs_release_block_group(struct btrfs_block_group *cache, bool delalloc)
-{
-	if (delalloc)
-		up_read(&cache->data_rwsem);
-	btrfs_put_block_group(cache);
+	return used_bg;
 }
 
 static bool find_free_extent_check_size_class(const struct find_free_extent_ctl *ffe_ctl,
@@ -3859,7 +3812,7 @@ static int find_free_extent_clustered(struct btrfs_block_group *bg,
 	u64 offset;
 	int ret;
 
-	cluster_bg = btrfs_lock_cluster(bg, last_ptr, ffe_ctl->delalloc);
+	cluster_bg = btrfs_lock_cluster(bg, last_ptr);
 	if (!cluster_bg)
 		goto refill_cluster;
 	if (cluster_bg != bg && (cluster_bg->ro ||
@@ -3894,7 +3847,7 @@ static int find_free_extent_clustered(struct btrfs_block_group *bg,
 	 */
 	if (ffe_ctl->loop >= LOOP_NO_EMPTY_SIZE && cluster_bg != bg) {
 		spin_unlock(&last_ptr->refill_lock);
-		btrfs_release_block_group(cluster_bg, ffe_ctl->delalloc);
+		btrfs_put_block_group(cluster_bg);
 		return -ENOENT;
 	}
 
@@ -3902,7 +3855,7 @@ static int find_free_extent_clustered(struct btrfs_block_group *bg,
 	btrfs_return_cluster_to_free_space(NULL, last_ptr);
 
 	if (cluster_bg != bg)
-		btrfs_release_block_group(cluster_bg, ffe_ctl->delalloc);
+		btrfs_put_block_group(cluster_bg);
 
 refill_cluster:
 	if (ffe_ctl->loop >= LOOP_NO_EMPTY_SIZE) {
@@ -4205,8 +4158,7 @@ static int do_allocation(struct btrfs_block_group *block_group,
 }
 
 static void release_block_group(struct btrfs_block_group *block_group,
-				struct find_free_extent_ctl *ffe_ctl,
-				bool delalloc)
+				struct find_free_extent_ctl *ffe_ctl)
 {
 	switch (ffe_ctl->policy) {
 	case BTRFS_EXTENT_ALLOC_CLUSTERED:
@@ -4221,7 +4173,6 @@ static void release_block_group(struct btrfs_block_group *block_group,
 
 	BUG_ON(btrfs_bg_flags_to_raid_index(block_group->flags) !=
 	       ffe_ctl->index);
-	btrfs_unlock_block_group(block_group, delalloc);
 }
 
 static void found_extent_clustered(struct find_free_extent_ctl *ffe_ctl,
@@ -4708,8 +4659,6 @@ static noinline int find_free_extent(struct btrfs_root *root,
 		if (find_free_extent_skip_block_group(block_group, ffe_ctl))
 			continue;
 
-		btrfs_lock_block_group(block_group, ffe_ctl->delalloc);
-
 		/*
 		 * this can happen if we end up cycling through all the
 		 * raid types, but we want to make sure we only allocate
@@ -4734,7 +4683,6 @@ static noinline int find_free_extent(struct btrfs_root *root,
 			 * It's possible that we have MIXED_GROUP flag but no
 			 * block group is mixed.  Just skip such block group.
 			 */
-			btrfs_unlock_block_group(block_group, ffe_ctl->delalloc);
 			continue;
 		}
 
@@ -4778,7 +4726,6 @@ static noinline int find_free_extent(struct btrfs_root *root,
 			goto loop;
 
 		if (bg_ret && bg_ret != block_group) {
-			btrfs_unlock_block_group(block_group, ffe_ctl->delalloc);
 			/*
 			 * bg_ret is still on the list: btrfs_remove_block_group()
 			 * detaches it from the cluster before list_del_init().
@@ -4807,7 +4754,6 @@ static noinline int find_free_extent(struct btrfs_root *root,
 
 		ret = btrfs_add_reserved_bytes(block_group, ffe_ctl->ram_bytes,
 					       ffe_ctl->num_bytes,
-					       ffe_ctl->delalloc,
 					       ffe_ctl->loop >= LOOP_WRONG_SIZE_CLASS);
 		if (ret == -EAGAIN) {
 			btrfs_add_free_space_unused(block_group,
@@ -4822,7 +4768,6 @@ static noinline int find_free_extent(struct btrfs_root *root,
 		ins->offset = ffe_ctl->num_bytes;
 
 		trace_btrfs_reserve_extent(block_group, ffe_ctl);
-		btrfs_unlock_block_group(block_group, ffe_ctl->delalloc);
 		break;
 loop:
 		if (!ffe_ctl->cached && ffe_ctl->loop > LOOP_CACHING_NOWAIT &&
@@ -4834,7 +4779,7 @@ static noinline int find_free_extent(struct btrfs_root *root,
 						ffe_ctl->empty_size);
 			goto have_block_group;
 		}
-		release_block_group(block_group, ffe_ctl, ffe_ctl->delalloc);
+		release_block_group(block_group, ffe_ctl);
 		cond_resched();
 	}
 	up_read(&space_info->groups_sem);
@@ -4897,11 +4842,6 @@ static noinline int find_free_extent(struct btrfs_root *root,
  * @is_data        -	Boolean flag indicating whether an extent is
  *			allocated for data (true) or metadata (false)
  *
- * @delalloc       -	Boolean flag indicating whether this allocation is for
- *			delalloc or not. If 'true' data_rwsem of block groups
- *			is going to be acquired.
- *
- *
  * Returns 0 when an allocation succeeded or < 0 when an error occurred. In
  * case -ENOSPC is returned then @ins->offset will contain the size of the
  * largest available hole the allocator managed to find.
@@ -4909,7 +4849,7 @@ static noinline int find_free_extent(struct btrfs_root *root,
 int btrfs_reserve_extent(struct btrfs_root *root, u64 ram_bytes,
 			 u64 num_bytes, u64 min_alloc_size,
 			 u64 empty_size, u64 hint_byte,
-			 struct btrfs_key *ins, bool is_data, bool delalloc)
+			 struct btrfs_key *ins, bool is_data)
 {
 	struct btrfs_fs_info *fs_info = root->fs_info;
 	struct find_free_extent_ctl ffe_ctl = {};
@@ -4928,7 +4868,6 @@ int btrfs_reserve_extent(struct btrfs_root *root, u64 ram_bytes,
 	ffe_ctl.min_alloc_size = min_alloc_size;
 	ffe_ctl.empty_size = empty_size;
 	ffe_ctl.flags = flags;
-	ffe_ctl.delalloc = delalloc;
 	ffe_ctl.hint_byte = hint_byte;
 	ffe_ctl.for_treelog = for_treelog;
 	ffe_ctl.for_data_reloc = for_data_reloc;
@@ -4961,8 +4900,7 @@ int btrfs_reserve_extent(struct btrfs_root *root, u64 ram_bytes,
 	return ret;
 }
 
-int btrfs_free_reserved_extent(struct btrfs_fs_info *fs_info, u64 start, u64 len,
-			       bool is_delalloc)
+int btrfs_free_reserved_extent(struct btrfs_fs_info *fs_info, u64 start, u64 len)
 {
 	struct btrfs_block_group *cache;
 
@@ -4974,7 +4912,7 @@ int btrfs_free_reserved_extent(struct btrfs_fs_info *fs_info, u64 start, u64 len
 	}
 
 	btrfs_add_free_space(cache, start, len);
-	btrfs_free_reserved_bytes(cache, len, is_delalloc);
+	btrfs_free_reserved_bytes(cache, len);
 	trace_btrfs_reserved_extent_free(fs_info, start, len);
 
 	btrfs_put_block_group(cache);
@@ -5406,7 +5344,7 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans,
 		return ERR_CAST(block_rsv);
 
 	ret = btrfs_reserve_extent(root, blocksize, blocksize, blocksize,
-				   empty_size, hint, &ins, false, false);
+				   empty_size, hint, &ins, false);
 	if (ret)
 		goto out_unuse;
 
@@ -5468,7 +5406,7 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans,
 	btrfs_tree_unlock(buf);
 	free_extent_buffer(buf);
 out_free_reserved:
-	btrfs_free_reserved_extent(fs_info, ins.objectid, ins.offset, false);
+	btrfs_free_reserved_extent(fs_info, ins.objectid, ins.offset);
 out_unuse:
 	btrfs_unuse_block_rsv(fs_info, block_rsv, blocksize);
 	return ERR_PTR(ret);
diff --git a/fs/btrfs/extent-tree.h b/fs/btrfs/extent-tree.h
index ecb2a1bf2435..b2895bad41dd 100644
--- a/fs/btrfs/extent-tree.h
+++ b/fs/btrfs/extent-tree.h
@@ -39,7 +39,6 @@ struct find_free_extent_ctl {
 	struct btrfs_free_cluster *last_ptr;
 	bool use_cluster;
 
-	bool delalloc;
 	bool have_caching_bg;
 	bool orig_have_caching_bg;
 
@@ -140,7 +139,7 @@ int btrfs_alloc_logged_file_extent(struct btrfs_trans_handle *trans,
 				   struct btrfs_key *ins);
 int btrfs_reserve_extent(struct btrfs_root *root, u64 ram_bytes, u64 num_bytes,
 			 u64 min_alloc_size, u64 empty_size, u64 hint_byte,
-			 struct btrfs_key *ins, bool is_data, bool delalloc);
+			 struct btrfs_key *ins, bool is_data);
 int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 		  struct extent_buffer *buf, bool full_backref);
 int btrfs_dec_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
@@ -151,8 +150,7 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_ref *ref);
 
 u64 btrfs_get_extent_owner_root(struct btrfs_fs_info *fs_info,
 				struct extent_buffer *leaf, int slot);
-int btrfs_free_reserved_extent(struct btrfs_fs_info *fs_info, u64 start, u64 len,
-			       bool is_delalloc);
+int btrfs_free_reserved_extent(struct btrfs_fs_info *fs_info, u64 start, u64 len);
 int btrfs_pin_reserved_extent(struct btrfs_trans_handle *trans,
 			      const struct extent_buffer *eb);
 int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index b071ed59a583..f66d3034b555 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -1072,7 +1072,7 @@ static void submit_one_async_extent(struct async_chunk *async_chunk,
 	compressed_size = async_extent->cb->bbio.bio.bi_iter.bi_size;
 	ret = btrfs_reserve_extent(root, async_extent->ram_size,
 				   compressed_size, compressed_size,
-				   0, *alloc_hint, &ins, true, true);
+				   0, *alloc_hint, &ins, true);
 	if (ret) {
 		/*
 		 * We can't reserve contiguous space for the compressed size.
@@ -1131,7 +1131,7 @@ static void submit_one_async_extent(struct async_chunk *async_chunk,
 
 out_free_reserve:
 	btrfs_dec_block_group_reservations(fs_info, ins.objectid);
-	btrfs_free_reserved_extent(fs_info, ins.objectid, ins.offset, true);
+	btrfs_free_reserved_extent(fs_info, ins.objectid, ins.offset);
 	mapping_set_error(inode->vfs_inode.i_mapping, -EIO);
 	extent_clear_unlock_delalloc(inode, start, end,
 				     NULL, &cached,
@@ -1217,7 +1217,7 @@ static int cow_one_range(struct btrfs_inode *inode, struct folio *locked_folio,
 	int ret;
 
 	ret = btrfs_reserve_extent(root, num_bytes, num_bytes, min_alloc_size,
-				   0, alloc_hint, ins, true, true);
+				   0, alloc_hint, ins, true);
 	if (ret < 0) {
 		*ret_alloc_size = cur_len;
 		return ret;
@@ -1314,7 +1314,7 @@ static int cow_one_range(struct btrfs_inode *inode, struct folio *locked_folio,
 				     PAGE_END_WRITEBACK);
 	btrfs_qgroup_free_data(inode, NULL, file_offset, cur_len, NULL);
 	btrfs_dec_block_group_reservations(fs_info, ins->objectid);
-	btrfs_free_reserved_extent(fs_info, ins->objectid, ins->offset, true);
+	btrfs_free_reserved_extent(fs_info, ins->objectid, ins->offset);
 	mapping_set_error(inode->vfs_inode.i_mapping, -EIO);
 	*ret_alloc_size = cur_len;
 	/*
@@ -3135,21 +3135,6 @@ static int insert_reserved_file_extent(struct btrfs_trans_handle *trans,
 						qgroup_reserved, &ins);
 }
 
-static void btrfs_release_delalloc_bytes(struct btrfs_fs_info *fs_info,
-					 u64 start, u64 len)
-{
-	struct btrfs_block_group *cache;
-
-	cache = btrfs_lookup_block_group(fs_info, start);
-	ASSERT(cache);
-
-	spin_lock(&cache->lock);
-	cache->delalloc_bytes -= len;
-	spin_unlock(&cache->lock);
-
-	btrfs_put_block_group(cache);
-}
-
 static int insert_ordered_extent_file_extent(struct btrfs_trans_handle *trans,
 					     struct btrfs_ordered_extent *oe)
 {
@@ -3310,9 +3295,6 @@ int btrfs_finish_one_ordered(struct btrfs_ordered_extent *ordered_extent)
 			goto out;
 		}
 		clear_reserved_extent = false;
-		btrfs_release_delalloc_bytes(fs_info,
-					     ordered_extent->disk_bytenr,
-					     ordered_extent->disk_num_bytes);
 	}
 
 	ret = btrfs_unpin_extent_cache(inode, ordered_extent->file_offset,
@@ -3400,7 +3382,7 @@ int btrfs_finish_one_ordered(struct btrfs_ordered_extent *ordered_extent)
 						NULL, true);
 			btrfs_free_reserved_extent(fs_info,
 					ordered_extent->disk_bytenr,
-					ordered_extent->disk_num_bytes, true);
+					ordered_extent->disk_num_bytes);
 			/*
 			 * Actually free the qgroup rsv which was released when
 			 * the ordered extent was created.
@@ -9195,7 +9177,7 @@ int btrfs_prealloc_file_range(struct inode *inode, int mode,
 		 */
 		cur_bytes = min(cur_bytes, last_alloc);
 		ret = btrfs_reserve_extent(root, cur_bytes, cur_bytes,
-				min_size, 0, *alloc_hint, &ins, true, false);
+				min_size, 0, *alloc_hint, &ins, true);
 		if (ret)
 			break;
 
@@ -9221,7 +9203,7 @@ int btrfs_prealloc_file_range(struct inode *inode, int mode,
 		if (IS_ERR(trans)) {
 			ret = PTR_ERR(trans);
 			btrfs_free_reserved_extent(fs_info, ins.objectid,
-						   ins.offset, false);
+						   ins.offset);
 			break;
 		}
 
@@ -10021,7 +10003,7 @@ ssize_t btrfs_do_encoded_write(struct kiocb *iocb, struct iov_iter *from,
 	}
 
 	ret = btrfs_reserve_extent(root, disk_num_bytes, disk_num_bytes,
-				   disk_num_bytes, 0, 0, &ins, true, true);
+				   disk_num_bytes, 0, 0, &ins, true);
 	if (ret)
 		goto out_delalloc_release;
 	extent_reserved = true;
@@ -10062,7 +10044,7 @@ ssize_t btrfs_do_encoded_write(struct kiocb *iocb, struct iov_iter *from,
 
 out_free_reserved:
 	btrfs_dec_block_group_reservations(fs_info, ins.objectid);
-	btrfs_free_reserved_extent(fs_info, ins.objectid, ins.offset, true);
+	btrfs_free_reserved_extent(fs_info, ins.objectid, ins.offset);
 out_delalloc_release:
 	btrfs_delalloc_release_extents(inode, num_bytes);
 	btrfs_delalloc_release_metadata(inode, disk_num_bytes, ret < 0);
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index b2ac5b836b21..8575ee0a2de9 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -4286,7 +4286,7 @@ static int move_existing_remap(struct btrfs_fs_info *fs_info,
 		min_size = fs_info->nodesize;
 
 	ret = btrfs_reserve_extent(fs_info->fs_root, length, length, min_size,
-				   0, 0, &ins, is_data, false);
+				   0, 0, &ins, is_data);
 	if (unlikely(ret)) {
 		spin_lock(&sinfo->lock);
 		btrfs_space_info_update_bytes_may_use(sinfo, -length);
@@ -4309,7 +4309,7 @@ static int move_existing_remap(struct btrfs_fs_info *fs_info,
 		u64 new_length = ALIGN_DOWN(dest_length, fs_info->nodesize);
 
 		btrfs_free_reserved_extent(fs_info, dest_addr + new_length,
-					   dest_length - new_length, 0);
+					   dest_length - new_length);
 
 		dest_length = new_length;
 	}
@@ -4443,14 +4443,14 @@ static int move_existing_remap(struct btrfs_fs_info *fs_info,
 	btrfs_dec_block_group_reservations(fs_info, dest_addr);
 
 	if (unlikely(ret)) {
-		btrfs_free_reserved_extent(fs_info, dest_addr, dest_length, 0);
+		btrfs_free_reserved_extent(fs_info, dest_addr, dest_length);
 
 		if (trans) {
 			btrfs_abort_transaction(trans, ret);
 			btrfs_end_transaction(trans);
 		}
 	} else {
-		btrfs_free_reserved_bytes(dest_bg, dest_length, 0);
+		btrfs_free_reserved_bytes(dest_bg, dest_length);
 
 		ret = btrfs_commit_transaction(trans);
 	}
@@ -5115,7 +5115,7 @@ static int do_remap_reloc_trans(struct btrfs_fs_info *fs_info,
 	 * rest of it the next time round.
 	 */
 	ret = btrfs_reserve_extent(fs_info->fs_root, remap_length, remap_length,
-				   min_size, 0, 0, &ins, is_data, false);
+				   min_size, 0, 0, &ins, is_data);
 	if (ret) {
 		spin_lock(&sinfo->lock);
 		btrfs_space_info_update_bytes_may_use(sinfo, -remap_length);
@@ -5141,7 +5141,7 @@ static int do_remap_reloc_trans(struct btrfs_fs_info *fs_info,
 		u64 new_length = ALIGN_DOWN(length, fs_info->nodesize);
 
 		btrfs_free_reserved_extent(fs_info, new_addr + new_length,
-					   length - new_length, 0);
+					   length - new_length);
 
 		length = new_length;
 	}
@@ -5180,7 +5180,7 @@ static int do_remap_reloc_trans(struct btrfs_fs_info *fs_info,
 	}
 
 	adjust_block_group_remap_bytes(trans, dest_bg, length);
-	btrfs_free_reserved_bytes(dest_bg, length, 0);
+	btrfs_free_reserved_bytes(dest_bg, length);
 
 	spin_lock(&sinfo->lock);
 	sinfo->bytes_readonly += length;
@@ -5224,7 +5224,7 @@ static int do_remap_reloc_trans(struct btrfs_fs_info *fs_info,
 	if (dest_bg)
 		btrfs_put_block_group(dest_bg);
 
-	btrfs_free_reserved_extent(fs_info, new_addr, length, 0);
+	btrfs_free_reserved_extent(fs_info, new_addr, length);
 
 	mutex_unlock(&fs_info->remap_mutex);
 	btrfs_end_transaction(trans);
diff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c
index 82d4ac418a2d..e2355c844a50 100644
--- a/fs/btrfs/space-info.c
+++ b/fs/btrfs/space-info.c
@@ -685,10 +685,9 @@ void btrfs_dump_space_info(struct btrfs_space_info *info, u64 bytes,
 		spin_lock(&cache->lock);
 		avail = btrfs_block_group_available_space(cache);
 		btrfs_info(fs_info,
-"block group %llu has %llu bytes, %llu used %llu pinned %llu reserved %llu delalloc %llu super %llu zone_unusable (%llu bytes available) %s",
+"block group %llu has %llu bytes, %llu used %llu pinned %llu reserved %llu super %llu zone_unusable (%llu bytes available) %s",
 			   cache->start, cache->length, cache->used, cache->pinned,
-			   cache->reserved, cache->delalloc_bytes,
-			   cache->bytes_super, cache->zone_unusable,
+			   cache->reserved, cache->bytes_super, cache->zone_unusable,
 			   avail, cache->ro ? "[readonly]" : "");
 		spin_unlock(&cache->lock);
 		btrfs_dump_free_space(cache, bytes);
-- 
2.56.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2026-10-22 17:06 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-22 17:06 [PATCH v2 0/7] btrfs: allocator perf improvements Boris Burkov
2026-10-22 17:06 ` [PATCH v2 1/7] btrfs: skip unhelpful size class relaxing allocation loops Boris Burkov
2026-10-22 17:07 ` [PATCH v2 2/7] btrfs: don't take block group references in find_free_extent() Boris Burkov
2026-10-22 17:07 ` [PATCH v2 3/7] btrfs: remove redundant checks in find_free_extent() hint path Boris Burkov
2026-10-22 17:07 ` [PATCH v2 4/7] btrfs: factor the find_free_extent() block group skip into a helper Boris Burkov
2026-10-22 17:07 ` [PATCH v2 5/7] btrfs: find_free_extent checks full block groups unlocked Boris Burkov
2026-10-22 17:07 ` [PATCH v2 6/7] btrfs: find_free_extent checks size class unlocked Boris Burkov
2026-10-22 17:07 ` [PATCH v2 7/7] btrfs: remove block_group data_rwsem and delalloc_bytes Boris Burkov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox