aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/indirect.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4/indirect.c')
-rw-r--r--fs/ext4/indirect.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
index 830e1b2bf145..792e388e7b44 100644
--- a/fs/ext4/indirect.c
+++ b/fs/ext4/indirect.c
@@ -807,16 +807,30 @@ ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb,
807 807
808retry: 808retry:
809 if (rw == READ && ext4_should_dioread_nolock(inode)) { 809 if (rw == READ && ext4_should_dioread_nolock(inode)) {
810 if (unlikely(!list_empty(&ei->i_completed_io_list))) { 810 if (unlikely(atomic_read(&EXT4_I(inode)->i_unwritten))) {
811 mutex_lock(&inode->i_mutex); 811 mutex_lock(&inode->i_mutex);
812 ext4_flush_completed_IO(inode); 812 ext4_flush_unwritten_io(inode);
813 mutex_unlock(&inode->i_mutex); 813 mutex_unlock(&inode->i_mutex);
814 } 814 }
815 /*
816 * Nolock dioread optimization may be dynamically disabled
817 * via ext4_inode_block_unlocked_dio(). Check inode's state
818 * while holding extra i_dio_count ref.
819 */
820 atomic_inc(&inode->i_dio_count);
821 smp_mb();
822 if (unlikely(ext4_test_inode_state(inode,
823 EXT4_STATE_DIOREAD_LOCK))) {
824 inode_dio_done(inode);
825 goto locked;
826 }
815 ret = __blockdev_direct_IO(rw, iocb, inode, 827 ret = __blockdev_direct_IO(rw, iocb, inode,
816 inode->i_sb->s_bdev, iov, 828 inode->i_sb->s_bdev, iov,
817 offset, nr_segs, 829 offset, nr_segs,
818 ext4_get_block, NULL, NULL, 0); 830 ext4_get_block, NULL, NULL, 0);
831 inode_dio_done(inode);
819 } else { 832 } else {
833locked:
820 ret = blockdev_direct_IO(rw, iocb, inode, iov, 834 ret = blockdev_direct_IO(rw, iocb, inode, iov,
821 offset, nr_segs, ext4_get_block); 835 offset, nr_segs, ext4_get_block);
822 836