From 002dc45ff258b1435845ac04f8b487ad355c873e Mon Sep 17 00:00:00 2001 From: Nikolay Borisov Date: Tue, 23 Mar 2021 12:01:11 +0000 Subject: [PATCH] btrfs: unlock extents in btrfs_zero_range in case of quota reservation errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit stable inclusion from stable-5.10.22 commit e6ba61aaff88ec5b8b2b8035431f75071d8b1690 bugzilla: 50796 -------------------------------- commit 4f6a49de64fd1b1dba5229c02047376da7cf24fd upstream. If btrfs_qgroup_reserve_data returns an error (i.e quota limit reached) the handling logic directly goes to the 'out' label without first unlocking the extent range between lockstart, lockend. This results in deadlocks as other processes try to lock the same extent. Fixes: a7f8b1c2ac21 ("btrfs: file: reserve qgroup space after the hole punch range is locked") CC: stable@vger.kernel.org # 5.10+ Reviewed-by: Qu Wenruo Signed-off-by: Nikolay Borisov Reviewed-by: David Sterba Signed-off-by: David Sterba Signed-off-by: Greg Kroah-Hartman Signed-off-by: Chen Jun Acked-by:  Weilong Chen Signed-off-by: Zheng Zengkai --- fs/btrfs/file.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 4373da7bcc0d..c81a20cc10dc 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -3236,8 +3236,11 @@ static int btrfs_zero_range(struct inode *inode, goto out; ret = btrfs_qgroup_reserve_data(BTRFS_I(inode), &data_reserved, alloc_start, bytes_to_reserve); - if (ret) + if (ret) { + unlock_extent_cached(&BTRFS_I(inode)->io_tree, lockstart, + lockend, &cached_state); goto out; + } ret = btrfs_prealloc_file_range(inode, mode, alloc_start, alloc_end - alloc_start, i_blocksize(inode), -- GitLab