Chandan Rajendra e8b5068b64 Btrfs: Fix deadlock between direct IO and fast fsync
[ Upstream commit 97dcdea076ecef41ea4aaa23d4397c2f622e4265 ]

The following deadlock is seen when executing generic/113 test,

 ---------------------------------------------------------+----------------------------------------------------
  Direct I/O task                                           Fast fsync task
 ---------------------------------------------------------+----------------------------------------------------
  btrfs_direct_IO
    __blockdev_direct_IO
     do_blockdev_direct_IO
      do_direct_IO
       btrfs_get_blocks_direct
        while (blocks needs to written)
         get_more_blocks (first iteration)
          btrfs_get_blocks_direct
           btrfs_create_dio_extent
             down_read(&BTRFS_I(inode) >dio_sem)
             Create and add extent map and ordered extent
             up_read(&BTRFS_I(inode) >dio_sem)
                                                            btrfs_sync_file
                                                              btrfs_log_dentry_safe
                                                               btrfs_log_inode_parent
                                                                btrfs_log_inode
                                                                 btrfs_log_changed_extents
                                                                  down_write(&BTRFS_I(inode) >dio_sem)
                                                                   Collect new extent maps and ordered extents
                                                                    wait for ordered extent completion
         get_more_blocks (second iteration)
          btrfs_get_blocks_direct
           btrfs_create_dio_extent
             down_read(&BTRFS_I(inode) >dio_sem)
 --------------------------------------------------------------------------------------------------------------

In the above description, Btrfs direct I/O code path has not yet started
submitting bios for file range covered by the initial ordered
extent. Meanwhile, The fast fsync task obtains the write semaphore and
waits for I/O on the ordered extent to get completed. However, the
Direct I/O task is now blocked on obtaining the read semaphore.

To resolve the deadlock, this commit modifies the Direct I/O code path
to obtain the read semaphore before invoking
__blockdev_direct_IO(). The semaphore is then given up after
__blockdev_direct_IO() returns. This allows the Direct I/O code to
complete I/O on all the ordered extents it creates.

Signed-off-by: Chandan Rajendra <chandan@linux.vnet.ibm.com>
Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2017-07-05 14:40:22 +02:00
..
2017-05-14 14:00:13 +02:00
2016-10-15 12:09:13 -07:00
2017-06-14 15:06:00 +02:00
2017-06-29 13:00:29 +02:00
2017-06-14 15:06:00 +02:00
2017-03-12 06:41:47 +01:00
2017-06-14 15:06:00 +02:00
2017-06-14 15:06:00 +02:00
2017-06-14 15:06:00 +02:00
2017-06-14 15:06:00 +02:00
2017-06-14 15:06:00 +02:00
2017-06-14 15:06:00 +02:00
2017-06-14 15:06:00 +02:00
2017-06-14 15:06:00 +02:00
2016-10-30 13:09:42 -04:00
2017-06-14 15:06:00 +02:00
2017-06-14 15:06:00 +02:00
2016-09-27 21:20:53 -04:00
2017-06-14 15:06:00 +02:00
2016-09-27 18:47:38 -04:00
2017-06-14 15:06:00 +02:00
2017-06-14 15:06:00 +02:00
2016-10-13 20:28:22 -07:00
2017-06-14 15:06:01 +02:00