diff options
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/ext4.h | 17 | ||||
-rw-r--r-- | fs/ext4/indirect.c | 14 | ||||
-rw-r--r-- | fs/ext4/inode.c | 5 | ||||
-rw-r--r-- | fs/ext4/move_extent.c | 8 |
4 files changed, 44 insertions, 0 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index edb049579420..1be2b4472a83 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -1358,6 +1358,8 @@ enum { | |||
1358 | EXT4_STATE_DIO_UNWRITTEN, /* need convert on dio done*/ | 1358 | EXT4_STATE_DIO_UNWRITTEN, /* need convert on dio done*/ |
1359 | EXT4_STATE_NEWENTRY, /* File just added to dir */ | 1359 | EXT4_STATE_NEWENTRY, /* File just added to dir */ |
1360 | EXT4_STATE_DELALLOC_RESERVED, /* blks already reserved for delalloc */ | 1360 | EXT4_STATE_DELALLOC_RESERVED, /* blks already reserved for delalloc */ |
1361 | EXT4_STATE_DIOREAD_LOCK, /* Disable support for dio read | ||
1362 | nolocking */ | ||
1361 | }; | 1363 | }; |
1362 | 1364 | ||
1363 | #define EXT4_INODE_BIT_FNS(name, field, offset) \ | 1365 | #define EXT4_INODE_BIT_FNS(name, field, offset) \ |
@@ -2469,6 +2471,21 @@ static inline void set_bitmap_uptodate(struct buffer_head *bh) | |||
2469 | set_bit(BH_BITMAP_UPTODATE, &(bh)->b_state); | 2471 | set_bit(BH_BITMAP_UPTODATE, &(bh)->b_state); |
2470 | } | 2472 | } |
2471 | 2473 | ||
2474 | /* | ||
2475 | * Disable DIO read nolock optimization, so new dioreaders will be forced | ||
2476 | * to grab i_mutex | ||
2477 | */ | ||
2478 | static inline void ext4_inode_block_unlocked_dio(struct inode *inode) | ||
2479 | { | ||
2480 | ext4_set_inode_state(inode, EXT4_STATE_DIOREAD_LOCK); | ||
2481 | smp_mb(); | ||
2482 | } | ||
2483 | static inline void ext4_inode_resume_unlocked_dio(struct inode *inode) | ||
2484 | { | ||
2485 | smp_mb(); | ||
2486 | ext4_clear_inode_state(inode, EXT4_STATE_DIOREAD_LOCK); | ||
2487 | } | ||
2488 | |||
2472 | #define in_range(b, first, len) ((b) >= (first) && (b) <= (first) + (len) - 1) | 2489 | #define in_range(b, first, len) ((b) >= (first) && (b) <= (first) + (len) - 1) |
2473 | 2490 | ||
2474 | /* For ioend & aio unwritten conversion wait queues */ | 2491 | /* For ioend & aio unwritten conversion wait queues */ |
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: | |||
810 | if (unlikely(!list_empty(&ei->i_completed_io_list))) | 810 | if (unlikely(!list_empty(&ei->i_completed_io_list))) |
811 | ext4_flush_completed_IO(inode); | 811 | ext4_flush_completed_IO(inode); |
812 | 812 | ||
813 | /* | ||
814 | * Nolock dioread optimization may be dynamically disabled | ||
815 | * via ext4_inode_block_unlocked_dio(). Check inode's state | ||
816 | * while holding extra i_dio_count ref. | ||
817 | */ | ||
818 | atomic_inc(&inode->i_dio_count); | ||
819 | smp_mb(); | ||
820 | if (unlikely(ext4_test_inode_state(inode, | ||
821 | EXT4_STATE_DIOREAD_LOCK))) { | ||
822 | inode_dio_done(inode); | ||
823 | goto locked; | ||
824 | } | ||
813 | ret = __blockdev_direct_IO(rw, iocb, inode, | 825 | ret = __blockdev_direct_IO(rw, iocb, inode, |
814 | inode->i_sb->s_bdev, iov, | 826 | inode->i_sb->s_bdev, iov, |
815 | offset, nr_segs, | 827 | offset, nr_segs, |
816 | ext4_get_block, NULL, NULL, 0); | 828 | ext4_get_block, NULL, NULL, 0); |
829 | inode_dio_done(inode); | ||
817 | } else { | 830 | } else { |
831 | locked: | ||
818 | ret = blockdev_direct_IO(rw, iocb, inode, iov, | 832 | ret = blockdev_direct_IO(rw, iocb, inode, iov, |
819 | offset, nr_segs, ext4_get_block); | 833 | offset, nr_segs, ext4_get_block); |
820 | 834 | ||
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 09d0488e9a15..bdd399bc2abf 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -4720,6 +4720,10 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val) | |||
4720 | return err; | 4720 | return err; |
4721 | } | 4721 | } |
4722 | 4722 | ||
4723 | /* Wait for all existing dio workers */ | ||
4724 | ext4_inode_block_unlocked_dio(inode); | ||
4725 | inode_dio_wait(inode); | ||
4726 | |||
4723 | jbd2_journal_lock_updates(journal); | 4727 | jbd2_journal_lock_updates(journal); |
4724 | 4728 | ||
4725 | /* | 4729 | /* |
@@ -4739,6 +4743,7 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val) | |||
4739 | ext4_set_aops(inode); | 4743 | ext4_set_aops(inode); |
4740 | 4744 | ||
4741 | jbd2_journal_unlock_updates(journal); | 4745 | jbd2_journal_unlock_updates(journal); |
4746 | ext4_inode_resume_unlocked_dio(inode); | ||
4742 | 4747 | ||
4743 | /* Finally we can mark the inode as dirty. */ | 4748 | /* Finally we can mark the inode as dirty. */ |
4744 | 4749 | ||
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index 8076b96b5299..292daeeed455 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c | |||
@@ -1323,6 +1323,12 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, | |||
1323 | /* Protect orig and donor inodes against a truncate */ | 1323 | /* Protect orig and donor inodes against a truncate */ |
1324 | mext_inode_double_lock(orig_inode, donor_inode); | 1324 | mext_inode_double_lock(orig_inode, donor_inode); |
1325 | 1325 | ||
1326 | /* Wait for all existing dio workers */ | ||
1327 | ext4_inode_block_unlocked_dio(orig_inode); | ||
1328 | ext4_inode_block_unlocked_dio(donor_inode); | ||
1329 | inode_dio_wait(orig_inode); | ||
1330 | inode_dio_wait(donor_inode); | ||
1331 | |||
1326 | /* Protect extent tree against block allocations via delalloc */ | 1332 | /* Protect extent tree against block allocations via delalloc */ |
1327 | double_down_write_data_sem(orig_inode, donor_inode); | 1333 | double_down_write_data_sem(orig_inode, donor_inode); |
1328 | /* Check the filesystem environment whether move_extent can be done */ | 1334 | /* Check the filesystem environment whether move_extent can be done */ |
@@ -1521,6 +1527,8 @@ out: | |||
1521 | kfree(holecheck_path); | 1527 | kfree(holecheck_path); |
1522 | } | 1528 | } |
1523 | double_up_write_data_sem(orig_inode, donor_inode); | 1529 | double_up_write_data_sem(orig_inode, donor_inode); |
1530 | ext4_inode_resume_unlocked_dio(orig_inode); | ||
1531 | ext4_inode_resume_unlocked_dio(donor_inode); | ||
1524 | mext_inode_double_unlock(orig_inode, donor_inode); | 1532 | mext_inode_double_unlock(orig_inode, donor_inode); |
1525 | 1533 | ||
1526 | return ret; | 1534 | return ret; |