]> git.baikalelectronics.ru Git - kernel.git/commit
btrfs: fix deadlock with fsync+fiemap+transaction commit
authorJosef Bacik <josef@toxicpanda.com>
Mon, 13 Jun 2022 19:09:49 +0000 (15:09 -0400)
committerDavid Sterba <dsterba@suse.com>
Tue, 21 Jun 2022 12:47:08 +0000 (14:47 +0200)
commit2496bb92a8182ec4c086f91cdd129562511f0d3d
tree2aee6217a8bc95482711810a8ac697f1aa520ea7
parent7a6e319ac0875c199fc4f728528ba8db0a16c17f
btrfs: fix deadlock with fsync+fiemap+transaction commit

We are hitting the following deadlock in production occasionally

Task 1 Task 2 Task 3 Task 4 Task 5
fsync(A)
 start trans
start commit
falloc(A)
 lock 5m-10m
 start trans
  wait for commit
fiemap(A)
 lock 0-10m
  wait for 5m-10m
   (have 0-5m locked)

 have btrfs_need_log_full_commit
  !full_sync
  wait_ordered_extents
finish_ordered_io(A)
lock 0-5m
DEADLOCK

We have an existing dependency of file extent lock -> transaction.
However in fsync if we tried to do the fast logging, but then had to
fall back to committing the transaction, we will be forced to call
btrfs_wait_ordered_range() to make sure all of our extents are updated.

This creates a dependency of transaction -> file extent lock, because
btrfs_finish_ordered_io() will need to take the file extent lock in
order to run the ordered extents.

Fix this by stopping the transaction if we have to do the full commit
and we attempted to do the fast logging.  Then attach to the transaction
and commit it if we need to.

CC: stable@vger.kernel.org # 5.15+
Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/file.c