diff options
author | Dmitry Monakhov <dmonakhov@openvz.org> | 2012-09-29 00:41:21 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2012-09-29 00:41:21 -0400 |
commit | 17335dcc471199717839b2fa3492ca36f70f1168 (patch) | |
tree | 5f39f51868f60f8be94ca7e811d34bba443ef288 /fs/ext4/indirect.c | |
parent | 28a535f9a0df060569dcc786e5bc2e1de43d7dc7 (diff) |
ext4: serialize dio nonlocked reads with defrag workers
Inode's block defrag and ext4_change_inode_journal_flag() may
affect nonlocked DIO reads result, so proper synchronization
required.
- Add missed inode_dio_wait() calls where appropriate
- Check inode state under extra i_dio_count reference.
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
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); |