aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2016-09-30 01:03:17 -0400
committerTheodore Ts'o <tytso@mit.edu>2016-09-30 01:03:17 -0400
commit16c54688592ce8eea85d2a26d37b64fa07e3e233 (patch)
tree9c8b9ce94df5b69a6c1befcc735f9ba665b6cba2 /fs/ext4
parentcca32b7eeb4ea24fa6596650e06279ad9130af98 (diff)
ext4: Allow parallel DIO reads
We can easily support parallel direct IO reads. We only have to make sure we cannot expose uninitialized data by reading allocated block to which data was not written yet, or which was already truncated. That is easily achieved by holding inode_lock in shared mode - that excludes all writes, truncates, hole punches. We also have to guard against page writeback allocating blocks for delay-allocated pages - that race is handled by the fact that we writeback all the pages in the affected range and the lock protects us from new pages being created there. Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/inode.c40
1 files changed, 18 insertions, 22 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 39883158b970..d8a4afc5eedb 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -3528,35 +3528,31 @@ out:
3528 3528
3529static ssize_t ext4_direct_IO_read(struct kiocb *iocb, struct iov_iter *iter) 3529static ssize_t ext4_direct_IO_read(struct kiocb *iocb, struct iov_iter *iter)
3530{ 3530{
3531 int unlocked = 0; 3531 struct address_space *mapping = iocb->ki_filp->f_mapping;
3532 struct inode *inode = iocb->ki_filp->f_mapping->host; 3532 struct inode *inode = mapping->host;
3533 ssize_t ret; 3533 ssize_t ret;
3534 3534
3535 if (ext4_should_dioread_nolock(inode)) { 3535 /*
3536 /* 3536 * Shared inode_lock is enough for us - it protects against concurrent
3537 * Nolock dioread optimization may be dynamically disabled 3537 * writes & truncates and since we take care of writing back page cache,
3538 * via ext4_inode_block_unlocked_dio(). Check inode's state 3538 * we are protected against page writeback as well.
3539 * while holding extra i_dio_count ref. 3539 */
3540 */ 3540 inode_lock_shared(inode);
3541 inode_dio_begin(inode);
3542 smp_mb();
3543 if (unlikely(ext4_test_inode_state(inode,
3544 EXT4_STATE_DIOREAD_LOCK)))
3545 inode_dio_end(inode);
3546 else
3547 unlocked = 1;
3548 }
3549 if (IS_DAX(inode)) { 3541 if (IS_DAX(inode)) {
3550 ret = dax_do_io(iocb, inode, iter, ext4_dio_get_block, 3542 ret = dax_do_io(iocb, inode, iter, ext4_dio_get_block, NULL, 0);
3551 NULL, unlocked ? 0 : DIO_LOCKING);
3552 } else { 3543 } else {
3544 size_t count = iov_iter_count(iter);
3545
3546 ret = filemap_write_and_wait_range(mapping, iocb->ki_pos,
3547 iocb->ki_pos + count);
3548 if (ret)
3549 goto out_unlock;
3553 ret = __blockdev_direct_IO(iocb, inode, inode->i_sb->s_bdev, 3550 ret = __blockdev_direct_IO(iocb, inode, inode->i_sb->s_bdev,
3554 iter, ext4_dio_get_block, 3551 iter, ext4_dio_get_block,
3555 NULL, NULL, 3552 NULL, NULL, 0);
3556 unlocked ? 0 : DIO_LOCKING);
3557 } 3553 }
3558 if (unlocked) 3554out_unlock:
3559 inode_dio_end(inode); 3555 inode_unlock_shared(inode);
3560 return ret; 3556 return ret;
3561} 3557}
3562 3558