| From stable+bounces-164821-greg=kroah.com@vger.kernel.org Sat Jul 26 04:25:14 2025 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Fri, 25 Jul 2025 22:25:03 -0400 |
| Subject: btrfs: fix qgroup reservation leak on failure to allocate ordered extent |
| To: stable@vger.kernel.org |
| Cc: Filipe Manana <fdmanana@suse.com>, Boris Burkov <boris@bur.io>, Qu Wenruo <wqu@suse.com>, David Sterba <dsterba@suse.com>, Sasha Levin <sashal@kernel.org> |
| Message-ID: <20250726022503.2023611-1-sashal@kernel.org> |
| |
| From: Filipe Manana <fdmanana@suse.com> |
| |
| [ Upstream commit 1f2889f5594a2bc4c6a52634c4a51b93e785def5 ] |
| |
| If we fail to allocate an ordered extent for a COW write we end up leaking |
| a qgroup data reservation since we called btrfs_qgroup_release_data() but |
| we didn't call btrfs_qgroup_free_refroot() (which would happen when |
| running the respective data delayed ref created by ordered extent |
| completion or when finishing the ordered extent in case an error happened). |
| |
| So make sure we call btrfs_qgroup_free_refroot() if we fail to allocate an |
| ordered extent for a COW write. |
| |
| Fixes: 7dbeaad0af7d ("btrfs: change timing for qgroup reserved space for ordered extents to fix reserved space leak") |
| CC: stable@vger.kernel.org # 6.1+ |
| Reviewed-by: Boris Burkov <boris@bur.io> |
| Reviewed-by: Qu Wenruo <wqu@suse.com> |
| Signed-off-by: Filipe Manana <fdmanana@suse.com> |
| Signed-off-by: David Sterba <dsterba@suse.com> |
| [ adjust to code movements ] |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| fs/btrfs/ordered-data.c | 12 +++++++++--- |
| 1 file changed, 9 insertions(+), 3 deletions(-) |
| |
| --- a/fs/btrfs/ordered-data.c |
| +++ b/fs/btrfs/ordered-data.c |
| @@ -173,9 +173,10 @@ int btrfs_add_ordered_extent(struct btrf |
| struct btrfs_ordered_extent *entry; |
| int ret; |
| u64 qgroup_rsv = 0; |
| + const bool is_nocow = (flags & |
| + ((1U << BTRFS_ORDERED_NOCOW) | (1U << BTRFS_ORDERED_PREALLOC))); |
| |
| - if (flags & |
| - ((1 << BTRFS_ORDERED_NOCOW) | (1 << BTRFS_ORDERED_PREALLOC))) { |
| + if (is_nocow) { |
| /* For nocow write, we can release the qgroup rsv right now */ |
| ret = btrfs_qgroup_free_data(inode, NULL, file_offset, num_bytes, &qgroup_rsv); |
| if (ret < 0) |
| @@ -191,8 +192,13 @@ int btrfs_add_ordered_extent(struct btrf |
| return ret; |
| } |
| entry = kmem_cache_zalloc(btrfs_ordered_extent_cache, GFP_NOFS); |
| - if (!entry) |
| + if (!entry) { |
| + if (!is_nocow) |
| + btrfs_qgroup_free_refroot(inode->root->fs_info, |
| + btrfs_root_id(inode->root), |
| + qgroup_rsv, BTRFS_QGROUP_RSV_DATA); |
| return -ENOMEM; |
| + } |
| |
| entry->file_offset = file_offset; |
| entry->num_bytes = num_bytes; |