diff options
-rw-r--r-- | fs/btrfs/inode.c | 35 |
1 files changed, 23 insertions, 12 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index c6ee8f1063ff..fce61991213c 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -6677,28 +6677,36 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb, | |||
6677 | struct inode *inode = file->f_mapping->host; | 6677 | struct inode *inode = file->f_mapping->host; |
6678 | size_t count = 0; | 6678 | size_t count = 0; |
6679 | int flags = 0; | 6679 | int flags = 0; |
6680 | bool wakeup = false; | 6680 | bool wakeup = true; |
6681 | bool relock = false; | ||
6681 | ssize_t ret; | 6682 | ssize_t ret; |
6682 | 6683 | ||
6683 | if (check_direct_IO(BTRFS_I(inode)->root, rw, iocb, iov, | 6684 | if (check_direct_IO(BTRFS_I(inode)->root, rw, iocb, iov, |
6684 | offset, nr_segs)) | 6685 | offset, nr_segs)) |
6685 | return 0; | 6686 | return 0; |
6686 | 6687 | ||
6688 | atomic_inc(&inode->i_dio_count); | ||
6689 | smp_mb__after_atomic_inc(); | ||
6690 | |||
6687 | if (rw & WRITE) { | 6691 | if (rw & WRITE) { |
6688 | count = iov_length(iov, nr_segs); | 6692 | count = iov_length(iov, nr_segs); |
6693 | /* | ||
6694 | * If the write DIO is beyond the EOF, we need update | ||
6695 | * the isize, but it is protected by i_mutex. So we can | ||
6696 | * not unlock the i_mutex at this case. | ||
6697 | */ | ||
6698 | if (offset + count <= inode->i_size) { | ||
6699 | mutex_unlock(&inode->i_mutex); | ||
6700 | relock = true; | ||
6701 | } | ||
6689 | ret = btrfs_delalloc_reserve_space(inode, count); | 6702 | ret = btrfs_delalloc_reserve_space(inode, count); |
6690 | if (ret) | 6703 | if (ret) |
6691 | return ret; | 6704 | goto out; |
6692 | } else { | 6705 | } else if (unlikely(test_bit(BTRFS_INODE_READDIO_NEED_LOCK, |
6693 | atomic_inc(&inode->i_dio_count); | 6706 | &BTRFS_I(inode)->runtime_flags))) { |
6694 | smp_mb__after_atomic_inc(); | 6707 | inode_dio_done(inode); |
6695 | if (unlikely(test_bit(BTRFS_INODE_READDIO_NEED_LOCK, | 6708 | flags = DIO_LOCKING | DIO_SKIP_HOLES; |
6696 | &BTRFS_I(inode)->runtime_flags))) { | 6709 | wakeup = false; |
6697 | inode_dio_done(inode); | ||
6698 | flags = DIO_LOCKING | DIO_SKIP_HOLES; | ||
6699 | } else { | ||
6700 | wakeup = true; | ||
6701 | } | ||
6702 | } | 6710 | } |
6703 | 6711 | ||
6704 | ret = __blockdev_direct_IO(rw, iocb, inode, | 6712 | ret = __blockdev_direct_IO(rw, iocb, inode, |
@@ -6717,8 +6725,11 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb, | |||
6717 | } | 6725 | } |
6718 | btrfs_delalloc_release_metadata(inode, 0); | 6726 | btrfs_delalloc_release_metadata(inode, 0); |
6719 | } | 6727 | } |
6728 | out: | ||
6720 | if (wakeup) | 6729 | if (wakeup) |
6721 | inode_dio_done(inode); | 6730 | inode_dio_done(inode); |
6731 | if (relock) | ||
6732 | mutex_lock(&inode->i_mutex); | ||
6722 | 6733 | ||
6723 | return ret; | 6734 | return ret; |
6724 | } | 6735 | } |