iomap: Call inode_dio_end() before generic_write_sync()
iomap complete routine can deadlock with btrfs_fallocate because of the call to generic_write_sync(). P0 P1 inode_lock() fallocate(FALLOC_FL_ZERO_RANGE) __iomap_dio_rw() inode_lock() <block> <submits IO> <completes IO> inode_unlock() <gets inode_lock()> inode_dio_wait() iomap_dio_complete() generic_write_sync() btrfs_file_fsync() inode_lock() <deadlock> inode_dio_end() is used to notify the end of DIO data in order to synchronize with truncate. Call inode_dio_end() before calling generic_write_sync(), so filesystems can lock i_rwsem during a sync. This matches the way it is done in fs/direct-io.c:dio_complete(). Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Josef Bacik <josef@toxicpanda.com> Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
This commit is contained in:
Родитель
c3d4ed1abe
Коммит
1a31182edd
|
@ -118,6 +118,7 @@ ssize_t iomap_dio_complete(struct iomap_dio *dio)
|
|||
dio_warn_stale_pagecache(iocb->ki_filp);
|
||||
}
|
||||
|
||||
inode_dio_end(file_inode(iocb->ki_filp));
|
||||
/*
|
||||
* If this is a DSYNC write, make sure we push it to stable storage now
|
||||
* that we've written data.
|
||||
|
@ -125,7 +126,6 @@ ssize_t iomap_dio_complete(struct iomap_dio *dio)
|
|||
if (ret > 0 && (dio->flags & IOMAP_DIO_NEED_SYNC))
|
||||
ret = generic_write_sync(iocb, ret);
|
||||
|
||||
inode_dio_end(file_inode(iocb->ki_filp));
|
||||
kfree(dio);
|
||||
|
||||
return ret;
|
||||
|
|
Загрузка…
Ссылка в новой задаче