]> git.ipfire.org Git - thirdparty/kernel/linux.git/commit
btrfs: avoid GFP_ATOMIC allocations in qgroup free paths
authorLeo Martins <loemra.dev@gmail.com>
Thu, 19 Mar 2026 23:49:08 +0000 (16:49 -0700)
committerDavid Sterba <dsterba@suse.com>
Tue, 7 Apr 2026 16:56:05 +0000 (18:56 +0200)
commite0a85137a882db789b1bccc1e7db06356ac8c69f
tree5ce6d2de5a3c0527cee1dfe7c1c86ccab1cd35ac
parent390aa432f3268c0947f903ab2d60ae2c7cafd11b
btrfs: avoid GFP_ATOMIC allocations in qgroup free paths

When qgroups are enabled, __btrfs_qgroup_release_data() and
qgroup_free_reserved_data() pass an extent_changeset to
btrfs_clear_record_extent_bits() to track how many bytes had their
EXTENT_QGROUP_RESERVED bits cleared. Inside the extent IO tree spinlock,
add_extent_changeset() calls ulist_add() with GFP_ATOMIC to record each
changed range. If this allocation fails, it hits a BUG_ON and panics the
kernel.

However, both of these callers only read changeset.bytes_changed
afterwards — the range_changed ulist is populated and immediately freed
without ever being iterated. The GFP_ATOMIC allocation is entirely
unnecessary for these paths.

Introduce extent_changeset_init_bytes_only() which uses a sentinel value
(EXTENT_CHANGESET_BYTES_ONLY) on the ulist's prealloc field to signal
that only bytes_changed should be tracked. add_extent_changeset() checks
for this sentinel and returns early after updating bytes_changed,
skipping the ulist_add() call entirely. This eliminates the GFP_ATOMIC
allocation and makes the BUG_ON unreachable for these paths.

Callers that need range tracking (qgroup_reserve_data,
qgroup_unreserve_range, btrfs_qgroup_check_reserved_leak) continue to
use extent_changeset_init() and are unaffected.

Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Leo Martins <loemra.dev@gmail.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/extent-io-tree.c
fs/btrfs/extent_io.h
fs/btrfs/qgroup.c