btrfs: fix deadlock when cloning inline extents and low on available space
authorFilipe Manana <fdmanana@suse.com>
Tue, 25 May 2021 10:05:28 +0000 (11:05 +0100)
committerDavid Sterba <dsterba@suse.com>
Thu, 27 May 2021 21:31:52 +0000 (23:31 +0200)
commit76a6d5cd74479e7ec8a7f9a29bce63d5549b6b2e
tree04f513fddd4dce3173d7deade4f371b564c3df0e
parentea7036de0d36c4e6c9508f68789e9567d514333a
btrfs: fix deadlock when cloning inline extents and low on available space

There are a few cases where cloning an inline extent requires copying data
into a page of the destination inode. For these cases we are allocating
the required data and metadata space while holding a leaf locked. This can
result in a deadlock when we are low on available space because allocating
the space may flush delalloc and two deadlock scenarios can happen:

1) When starting writeback for an inode with a very small dirty range that
   fits in an inline extent, we deadlock during the writeback when trying
   to insert the inline extent, at cow_file_range_inline(), if the extent
   is going to be located in the leaf for which we are already holding a
   read lock;

2) After successfully starting writeback, for non-inline extent cases,
   the async reclaim thread will hang waiting for an ordered extent to
   complete if the ordered extent completion needs to modify the leaf
   for which the clone task is holding a read lock (for adding or
   replacing file extent items). So the cloning task will wait forever
   on the async reclaim thread to make progress, which in turn is
   waiting for the ordered extent completion which in turn is waiting
   to acquire a write lock on the same leaf.

So fix this by making sure we release the path (and therefore the leaf)
every time we need to copy the inline extent's data into a page of the
destination inode, as by that time we do not need to have the leaf locked.

Fixes: 05a5a7621ce66c ("Btrfs: implement full reflink support for inline extents")
CC: stable@vger.kernel.org # 5.10+
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/reflink.c