summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2011-06-24 14:29:48 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2011-07-20 20:47:50 -0400
commit72c5052ddc3956d847f21c2b8d55c93664a51b2c (patch)
tree47b381f3f746cdc1612f432bd902278f8901f84a
parentaacfc19c626ebd3daa675652457d71019a1f583f (diff)
downloadlwn-72c5052ddc3956d847f21c2b8d55c93664a51b2c.tar.gz
lwn-72c5052ddc3956d847f21c2b8d55c93664a51b2c.zip
fs: move inode_dio_done to the end_io handler
For filesystems that delay their end_io processing we should keep our i_dio_count until the the processing is done. Enable this by moving the inode_dio_done call to the end_io handler if one exist. Note that the actual move to the workqueue for ext4 and XFS is not done in this patch yet, but left to the filesystem maintainers. At least for XFS it's not needed yet either as XFS has an internal equivalent to i_dio_count. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/direct-io.c7
-rw-r--r--fs/ext4/inode.c5
-rw-r--r--fs/ocfs2/aops.c1
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c3
4 files changed, 13 insertions, 3 deletions
diff --git a/fs/direct-io.c b/fs/direct-io.c
index 0a073c7125a6..01d2d9ef609c 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -293,11 +293,12 @@ static ssize_t dio_complete(struct dio *dio, loff_t offset, ssize_t ret, bool is
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);
+ } else {
+ if (is_async)
+ aio_complete(dio->iocb, ret, 0);
+ inode_dio_done(dio->inode);
}
- inode_dio_done(dio->inode);
return ret;
}
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 1f35573a34e1..678cde834f19 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -3573,6 +3573,7 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
ssize_t size, void *private, int ret,
bool is_async)
{
+ struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode;
ext4_io_end_t *io_end = iocb->private;
struct workqueue_struct *wq;
unsigned long flags;
@@ -3594,6 +3595,7 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
out:
if (is_async)
aio_complete(iocb, ret, 0);
+ inode_dio_done(inode);
return;
}
@@ -3614,6 +3616,9 @@ out:
/* queue the work to convert unwritten extents to written */
queue_work(wq, &io_end->work);
iocb->private = NULL;
+
+ /* XXX: probably should move into the real I/O completion handler */
+ inode_dio_done(inode);
}
static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate)
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index 524d6167fb63..c1efe939c774 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -577,6 +577,7 @@ static void ocfs2_dio_end_io(struct kiocb *iocb,
if (is_async)
aio_complete(iocb, ret, 0);
+ inode_dio_done(inode);
}
/*
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 79ce38be15a1..b3b418f519f3 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -1339,6 +1339,9 @@ xfs_end_io_direct_write(
} else {
xfs_finish_ioend_sync(ioend);
}
+
+ /* XXX: probably should move into the real I/O completion handler */
+ inode_dio_done(ioend->io_inode);
}
STATIC ssize_t