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 |
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), >
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 --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),
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(-)