aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r--fs/btrfs/inode.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index d11f38d8696c..c6ee8f1063ff 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -3888,6 +3888,12 @@ static int btrfs_setsize(struct inode *inode, struct iattr *attr)
3888 3888
3889 /* we don't support swapfiles, so vmtruncate shouldn't fail */ 3889 /* we don't support swapfiles, so vmtruncate shouldn't fail */
3890 truncate_setsize(inode, newsize); 3890 truncate_setsize(inode, newsize);
3891
3892 /* Disable nonlocked read DIO to avoid the end less truncate */
3893 btrfs_inode_block_unlocked_dio(inode);
3894 inode_dio_wait(inode);
3895 btrfs_inode_resume_unlocked_dio(inode);
3896
3891 ret = btrfs_truncate(inode); 3897 ret = btrfs_truncate(inode);
3892 if (ret && inode->i_nlink) 3898 if (ret && inode->i_nlink)
3893 btrfs_orphan_del(NULL, inode); 3899 btrfs_orphan_del(NULL, inode);
@@ -6670,6 +6676,8 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb,
6670 struct file *file = iocb->ki_filp; 6676 struct file *file = iocb->ki_filp;
6671 struct inode *inode = file->f_mapping->host; 6677 struct inode *inode = file->f_mapping->host;
6672 size_t count = 0; 6678 size_t count = 0;
6679 int flags = 0;
6680 bool wakeup = false;
6673 ssize_t ret; 6681 ssize_t ret;
6674 6682
6675 if (check_direct_IO(BTRFS_I(inode)->root, rw, iocb, iov, 6683 if (check_direct_IO(BTRFS_I(inode)->root, rw, iocb, iov,
@@ -6681,13 +6689,22 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb,
6681 ret = btrfs_delalloc_reserve_space(inode, count); 6689 ret = btrfs_delalloc_reserve_space(inode, count);
6682 if (ret) 6690 if (ret)
6683 return ret; 6691 return ret;
6692 } else {
6693 atomic_inc(&inode->i_dio_count);
6694 smp_mb__after_atomic_inc();
6695 if (unlikely(test_bit(BTRFS_INODE_READDIO_NEED_LOCK,
6696 &BTRFS_I(inode)->runtime_flags))) {
6697 inode_dio_done(inode);
6698 flags = DIO_LOCKING | DIO_SKIP_HOLES;
6699 } else {
6700 wakeup = true;
6701 }
6684 } 6702 }
6685 6703
6686 ret = __blockdev_direct_IO(rw, iocb, inode, 6704 ret = __blockdev_direct_IO(rw, iocb, inode,
6687 BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev, 6705 BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev,
6688 iov, offset, nr_segs, btrfs_get_blocks_direct, NULL, 6706 iov, offset, nr_segs, btrfs_get_blocks_direct, NULL,
6689 btrfs_submit_direct, 0); 6707 btrfs_submit_direct, flags);
6690
6691 if (rw & WRITE) { 6708 if (rw & WRITE) {
6692 if (ret < 0 && ret != -EIOCBQUEUED) 6709 if (ret < 0 && ret != -EIOCBQUEUED)
6693 btrfs_delalloc_release_space(inode, count); 6710 btrfs_delalloc_release_space(inode, count);
@@ -6700,6 +6717,8 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb,
6700 } 6717 }
6701 btrfs_delalloc_release_metadata(inode, 0); 6718 btrfs_delalloc_release_metadata(inode, 0);
6702 } 6719 }
6720 if (wakeup)
6721 inode_dio_done(inode);
6703 6722
6704 return ret; 6723 return ret;
6705} 6724}