]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
btrfs: fix reservation leak in some error paths when inserting inline extent
authorFilipe Manana <fdmanana@suse.com>
Fri, 12 Dec 2025 17:18:25 +0000 (17:18 +0000)
committerDavid Sterba <dsterba@suse.com>
Tue, 16 Dec 2025 21:53:15 +0000 (22:53 +0100)
If we fail to allocate a path or join a transaction, we return from
__cow_file_range_inline() without freeing the reserved qgroup data,
resulting in a leak. Fix this by ensuring we call btrfs_qgroup_free_data()
in such cases.

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/inode.c

index c4c370b6aae9748fc04381b74d0e2ea44a1e95c9..03337fa7a61c05b3ec861b3faf1d3ce39d287399 100644 (file)
@@ -617,19 +617,22 @@ static noinline int __cow_file_range_inline(struct btrfs_inode *inode,
        struct btrfs_drop_extents_args drop_args = { 0 };
        struct btrfs_root *root = inode->root;
        struct btrfs_fs_info *fs_info = root->fs_info;
-       struct btrfs_trans_handle *trans;
+       struct btrfs_trans_handle *trans = NULL;
        u64 data_len = (compressed_size ?: size);
        int ret;
        struct btrfs_path *path;
 
        path = btrfs_alloc_path();
-       if (!path)
-               return -ENOMEM;
+       if (!path) {
+               ret = -ENOMEM;
+               goto out;
+       }
 
        trans = btrfs_join_transaction(root);
        if (IS_ERR(trans)) {
-               btrfs_free_path(path);
-               return PTR_ERR(trans);
+               ret = PTR_ERR(trans);
+               trans = NULL;
+               goto out;
        }
        trans->block_rsv = &inode->block_rsv;
 
@@ -680,7 +683,8 @@ out:
        if (ret <= 0)
                btrfs_qgroup_free_data(inode, NULL, 0, fs_info->sectorsize, NULL);
        btrfs_free_path(path);
-       btrfs_end_transaction(trans);
+       if (trans)
+               btrfs_end_transaction(trans);
        return ret;
 }