From 3a4bf497e7a843cc50db413d30171c18d46750c0 Mon Sep 17 00:00:00 2001 From: Miao Xie Date: Fri, 8 Feb 2013 07:04:11 +0000 Subject: [PATCH] --- yaml --- r: 360447 b: refs/heads/master c: 38851cc19adbfa1def2b47106d8050a80e0a3673 h: refs/heads/master i: 360445: 732f97a912f44b53d381a1726e7154243231114a 360443: 40a24336e2119e8c76b6265c221c71a8050bc46c 360439: c8c423e30ad28be1ee61ad2086a609115436bf1d 360431: 649fa5c4bb278f6b74b50e7b4070c15509859095 360415: 214ebbc9f017f6fc542563e34fb933e2882c9805 360383: aa9403088f7fdfc7ceaa0f1c6821cc0c44b5ee3b 360319: 0e137718f537d00c505f76efa40afc3471dfd8ff 360191: efb9466eaf5c9fa72270c8b62b589734300572da 359935: 6ffb6bdf5f0fab6e6d187a005954665f2fa590cc 359423: afe6e6d0034aeffacd487b0093c9937658635232 358399: 13c6cfdfa75cf1bfd490bdc5a20e4b167ca7ae78 356351: 0d2f364b8505d37b42a748d7b7f8a1712c859fdf 352255: 8f9982fdf3a441684b407ac383e32c34ca4877a0 344063: 542864cb4e45606463ac92ca9294dbd9177bd875 327679: 9dd685fb495fdbf23aef974fab57f7f04898b12a v: v3 --- [refs] | 2 +- trunk/fs/btrfs/inode.c | 35 +++++++++++++++++++++++------------ 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/[refs] b/[refs] index 6207e15b10a0..a5cc1c0f8599 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 2e60a51e62185cce48758e596ae7cb2da673b58f +refs/heads/master: 38851cc19adbfa1def2b47106d8050a80e0a3673 diff --git a/trunk/fs/btrfs/inode.c b/trunk/fs/btrfs/inode.c index c6ee8f1063ff..fce61991213c 100644 --- a/trunk/fs/btrfs/inode.c +++ b/trunk/fs/btrfs/inode.c @@ -6677,28 +6677,36 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb, struct inode *inode = file->f_mapping->host; size_t count = 0; int flags = 0; - bool wakeup = false; + bool wakeup = true; + bool relock = false; ssize_t ret; if (check_direct_IO(BTRFS_I(inode)->root, rw, iocb, iov, offset, nr_segs)) return 0; + atomic_inc(&inode->i_dio_count); + smp_mb__after_atomic_inc(); + if (rw & WRITE) { count = iov_length(iov, nr_segs); + /* + * If the write DIO is beyond the EOF, we need update + * the isize, but it is protected by i_mutex. So we can + * not unlock the i_mutex at this case. + */ + if (offset + count <= inode->i_size) { + mutex_unlock(&inode->i_mutex); + relock = true; + } ret = btrfs_delalloc_reserve_space(inode, count); if (ret) - return ret; - } else { - atomic_inc(&inode->i_dio_count); - smp_mb__after_atomic_inc(); - if (unlikely(test_bit(BTRFS_INODE_READDIO_NEED_LOCK, - &BTRFS_I(inode)->runtime_flags))) { - inode_dio_done(inode); - flags = DIO_LOCKING | DIO_SKIP_HOLES; - } else { - wakeup = true; - } + goto out; + } else if (unlikely(test_bit(BTRFS_INODE_READDIO_NEED_LOCK, + &BTRFS_I(inode)->runtime_flags))) { + inode_dio_done(inode); + flags = DIO_LOCKING | DIO_SKIP_HOLES; + wakeup = false; } ret = __blockdev_direct_IO(rw, iocb, inode, @@ -6717,8 +6725,11 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb, } btrfs_delalloc_release_metadata(inode, 0); } +out: if (wakeup) inode_dio_done(inode); + if (relock) + mutex_lock(&inode->i_mutex); return ret; }