• Josef Bacik's avatar
    btrfs: fix deadlock with fsync+fiemap+transaction commit · bf7ba8ee
    Josef Bacik authored
    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: default avatarFilipe Manana <fdmanana@suse.com>
    Signed-off-by: default avatarJosef Bacik <josef@toxicpanda.com>
    Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
    bf7ba8ee
file.c 105 KB