diff mbox series

btrfs: Unlock extents in btrfs_zero_range in case of errors

Message ID 20210223132042.1198894-1-nborisov@suse.com (mailing list archive)
State New, archived
Headers show
Series btrfs: Unlock extents in btrfs_zero_range in case of errors | expand

Commit Message

Nikolay Borisov Feb. 23, 2021, 1:20 p.m. UTC
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 processes try to lock the same extent.

Fixes: a7f8b1c2ac21 ("btrfs: file: reserve qgroup space after the hole punch range is locked")
Signed-off-by: Nikolay Borisov <nborisov@suse.com>
---
 fs/btrfs/file.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

Comments

Qu Wenruo Feb. 23, 2021, 1:24 p.m. UTC | #1
On 2021/2/23 下午9:20, Nikolay Borisov wrote:
> 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 processes try to lock the same extent.
>
> Fixes: a7f8b1c2ac21 ("btrfs: file: reserve qgroup space after the hole punch range is locked")
> Signed-off-by: Nikolay Borisov <nborisov@suse.com>

Reviewed-by: Qu Wenruo <wqu@suse.com>

Thanks,
Qu
> ---
>   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 1e68349c3884..af0253473508 100644
> --- a/fs/btrfs/file.c
> +++ b/fs/btrfs/file.c
> @@ -3259,8 +3259,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),
>
David Sterba Feb. 23, 2021, 2:01 p.m. UTC | #2
On Tue, Feb 23, 2021 at 03:20:42PM +0200, Nikolay Borisov wrote:
> 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 processes try to lock the same extent.
> 
> Fixes: a7f8b1c2ac21 ("btrfs: file: reserve qgroup space after the hole punch range is locked")
> Signed-off-by: Nikolay Borisov <nborisov@suse.com>

Added to misc-next, thanks.
diff mbox series

Patch

diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 1e68349c3884..af0253473508 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -3259,8 +3259,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),