Once we have grabbed i_mutex, this will prevent any other writes from proceeding, so we don't need to worry about any writes to unwritten regions from taking place. So drop the aio_mutex so that if there are any other parallel writes happen to some other inode that happens to hash to the same hash table entry, we won't end up blocking that work. Signed-off-by: "Theodore Ts'o" <tytso@xxxxxxx> --- fs/ext4/file.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 3ec0c09..5e428d58 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c @@ -98,7 +98,6 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov, struct file *file = iocb->ki_filp; struct inode *inode = file_inode(iocb->ki_filp); struct blk_plug plug; - int unaligned_aio = 0; int overwrite = 0; size_t length = iov_length(iov, nr_segs); ssize_t ret; @@ -124,24 +123,26 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov, } if (unlikely(iocb->ki_filp->f_flags & O_DIRECT)) { - if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS) && - !is_sync_kiocb(iocb)) - unaligned_aio = ext4_unaligned_aio(inode, iov, - nr_segs, pos); + struct mutex *aio_mutex = NULL; /* Unaligned direct AIO must be serialized; see comment above */ - if (unaligned_aio) { - mutex_lock(ext4_aio_mutex(inode)); + if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS) && + !is_sync_kiocb(iocb) && + ext4_unaligned_aio(inode, iov, nr_segs, pos)) { + aio_mutex = ext4_aio_mutex(inode); + mutex_lock(aio_mutex); ext4_unwritten_wait(inode); } mutex_lock(&inode->i_mutex); + if (aio_mutex) + mutex_unlock(aio_mutex); blk_start_plug(&plug); iocb->private = &overwrite; /* check whether we do a DIO overwrite or not */ - if (ext4_should_dioread_nolock(inode) && !unaligned_aio && + if (ext4_should_dioread_nolock(inode) && !aio_mutex && !file->f_mapping->nrpages && pos + length <= i_size_read(inode)) { struct ext4_map_blocks map; unsigned int blkbits = inode->i_blkbits; @@ -181,9 +182,6 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov, ret = err; } blk_finish_plug(&plug); - - if (unaligned_aio) - mutex_unlock(ext4_aio_mutex(inode)); } else { mutex_lock(&inode->i_mutex); ret = __generic_file_aio_write(iocb, iov, nr_segs, -- 1.9.0 -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html