diff options
Diffstat (limited to 'fs/ext4/indirect.c')
| -rw-r--r-- | fs/ext4/indirect.c | 14 | 
1 files changed, 14 insertions, 0 deletions
diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c index 61f13e57975e..8d849dae8428 100644 --- a/fs/ext4/indirect.c +++ b/fs/ext4/indirect.c @@ -810,11 +810,25 @@ retry:  		if (unlikely(!list_empty(&ei->i_completed_io_list)))  			ext4_flush_completed_IO(inode); +		/* +		 * Nolock dioread optimization may be dynamically disabled +		 * via ext4_inode_block_unlocked_dio(). Check inode's state +		 * while holding extra i_dio_count ref. +		 */ +		atomic_inc(&inode->i_dio_count); +		smp_mb(); +		if (unlikely(ext4_test_inode_state(inode, +						    EXT4_STATE_DIOREAD_LOCK))) { +			inode_dio_done(inode); +			goto locked; +		}  		ret = __blockdev_direct_IO(rw, iocb, inode,  				 inode->i_sb->s_bdev, iov,  				 offset, nr_segs,  				 ext4_get_block, NULL, NULL, 0); +		inode_dio_done(inode);  	} else { +locked:  		ret = blockdev_direct_IO(rw, iocb, inode, iov,  				 offset, nr_segs, ext4_get_block);  | 
