summaryrefslogtreecommitdiff
path: root/fs/direct-io.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-08-03 14:33:38 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-03 14:33:38 -0700
commit51102ee5b8853d230e534cbcd0d888f0134738a3 (patch)
tree5a34844b3040dbc099dd0d3ebc2e6fca0bc65855 /fs/direct-io.c
parent54161df1fb1469d66bce3a3b14d8281adbb69263 (diff)
parent6b0a2996a0c023d84bc27ec7528a6e54cb5ea264 (diff)
Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs
* 'for-linus' of git://oss.sgi.com/xfs/xfs: (49 commits) xfs simplify and speed up direct I/O completions xfs: move aio completion after unwritten extent conversion direct-io: move aio_complete into ->end_io xfs: fix big endian build xfs: clean up xfs_bmap_get_bp xfs: simplify xfs_truncate_file xfs: kill the b_strat callback in xfs_buf xfs: remove obsolete osyncisosync mount option xfs: clean up filestreams helpers xfs: fix gcc 4.6 set but not read and unused statement warnings xfs: Fix build when CONFIG_XFS_POSIX_ACL=n xfs: fix unsigned underflow in xfs_free_eofblocks xfs: use GFP_NOFS for page cache allocation xfs: fix memory reclaim recursion deadlock on locked inode buffer xfs: fix xfs_trans_add_item() lockdep warnings xfs: simplify and remove xfs_ireclaim xfs: don't block on buffer read errors xfs: move inode shrinker unregister even earlier xfs: remove a dmapi leftover xfs: writepage always has buffers ...
Diffstat (limited to 'fs/direct-io.c')
-rw-r--r--fs/direct-io.c26
1 files changed, 14 insertions, 12 deletions
diff --git a/fs/direct-io.c b/fs/direct-io.c
index 7600aacf531..a10cb91cade 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -218,7 +218,7 @@ static struct page *dio_get_page(struct dio *dio)
* filesystems can use it to hold additional state between get_block calls and
* dio_complete.
*/
-static int dio_complete(struct dio *dio, loff_t offset, int ret)
+static int dio_complete(struct dio *dio, loff_t offset, int ret, bool is_async)
{
ssize_t transferred = 0;
@@ -239,14 +239,6 @@ static int dio_complete(struct dio *dio, loff_t offset, int ret)
transferred = dio->i_size - offset;
}
- if (dio->end_io && dio->result)
- dio->end_io(dio->iocb, offset, transferred,
- dio->map_bh.b_private);
-
- if (dio->flags & DIO_LOCKING)
- /* lockdep: non-owner release */
- up_read_non_owner(&dio->inode->i_alloc_sem);
-
if (ret == 0)
ret = dio->page_errors;
if (ret == 0)
@@ -254,6 +246,17 @@ static int dio_complete(struct dio *dio, loff_t offset, int ret)
if (ret == 0)
ret = transferred;
+ if (dio->end_io && dio->result) {
+ dio->end_io(dio->iocb, offset, transferred,
+ dio->map_bh.b_private, ret, is_async);
+ } else if (is_async) {
+ aio_complete(dio->iocb, ret, 0);
+ }
+
+ if (dio->flags & DIO_LOCKING)
+ /* lockdep: non-owner release */
+ up_read_non_owner(&dio->inode->i_alloc_sem);
+
return ret;
}
@@ -277,8 +280,7 @@ static void dio_bio_end_aio(struct bio *bio, int error)
spin_unlock_irqrestore(&dio->bio_lock, flags);
if (remaining == 0) {
- int ret = dio_complete(dio, dio->iocb->ki_pos, 0);
- aio_complete(dio->iocb, ret, 0);
+ dio_complete(dio, dio->iocb->ki_pos, 0, true);
kfree(dio);
}
}
@@ -1126,7 +1128,7 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode,
spin_unlock_irqrestore(&dio->bio_lock, flags);
if (ret2 == 0) {
- ret = dio_complete(dio, offset, ret);
+ ret = dio_complete(dio, offset, ret, false);
kfree(dio);
} else
BUG_ON(ret != -EIOCBQUEUED);