mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-17 02:36:21 +00:00
btrfs: call iomap_dio_complete() without inode_lock
If direct writes are called with O_DIRECT | O_DSYNC, it will result in a deadlock because iomap_dio_rw() is called under i_rwsem which calls: iomap_dio_complete() generic_write_sync() btrfs_sync_file() btrfs_sync_file() requires i_rwsem, so call __iomap_dio_rw() with the i_rwsem locked, and call iomap_dio_complete() after unlocking i_rwsem. Reviewed-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
502756b380
commit
a42fa64316
@ -1906,6 +1906,7 @@ static ssize_t btrfs_direct_write(struct kiocb *iocb, struct iov_iter *from)
|
|||||||
loff_t endbyte;
|
loff_t endbyte;
|
||||||
ssize_t err;
|
ssize_t err;
|
||||||
unsigned int ilock_flags = 0;
|
unsigned int ilock_flags = 0;
|
||||||
|
struct iomap_dio *dio = NULL;
|
||||||
|
|
||||||
if (iocb->ki_flags & IOCB_NOWAIT)
|
if (iocb->ki_flags & IOCB_NOWAIT)
|
||||||
ilock_flags |= BTRFS_ILOCK_TRY;
|
ilock_flags |= BTRFS_ILOCK_TRY;
|
||||||
@ -1948,22 +1949,19 @@ relock:
|
|||||||
goto buffered;
|
goto buffered;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
dio = __iomap_dio_rw(iocb, from, &btrfs_dio_iomap_ops,
|
||||||
* This is actually a sync iocb, so we need our fancy endio to know if
|
&btrfs_dio_ops, is_sync_kiocb(iocb));
|
||||||
* we need to sync.
|
|
||||||
*/
|
|
||||||
if (current->journal_info)
|
|
||||||
written = iomap_dio_rw(iocb, from, &btrfs_dio_iomap_ops,
|
|
||||||
&btrfs_sync_dops, is_sync_kiocb(iocb));
|
|
||||||
else
|
|
||||||
written = iomap_dio_rw(iocb, from, &btrfs_dio_iomap_ops,
|
|
||||||
&btrfs_dio_ops, is_sync_kiocb(iocb));
|
|
||||||
|
|
||||||
if (written == -ENOTBLK)
|
|
||||||
written = 0;
|
|
||||||
|
|
||||||
btrfs_inode_unlock(inode, ilock_flags);
|
btrfs_inode_unlock(inode, ilock_flags);
|
||||||
|
|
||||||
|
if (IS_ERR_OR_NULL(dio)) {
|
||||||
|
err = PTR_ERR_OR_ZERO(dio);
|
||||||
|
if (err < 0 && err != -ENOTBLK)
|
||||||
|
goto out;
|
||||||
|
} else {
|
||||||
|
written = iomap_dio_complete(dio);
|
||||||
|
}
|
||||||
|
|
||||||
if (written < 0 || !iov_iter_count(from)) {
|
if (written < 0 || !iov_iter_count(from)) {
|
||||||
err = written;
|
err = written;
|
||||||
goto out;
|
goto out;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user