fs: move inode_dio_done to the end_io handler
authorChristoph Hellwig <hch@infradead.org>
Fri, 24 Jun 2011 18:29:48 +0000 (14:29 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Thu, 21 Jul 2011 00:47:50 +0000 (20:47 -0400)
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>
fs/direct-io.c
fs/ext4/inode.c
fs/ocfs2/aops.c
fs/xfs/linux-2.6/xfs_aops.c

index 0a073c7125a677705872c5381699b810477b68b6..01d2d9ef609cb1619ee4159808699559ee0fe5d5 100644 (file)
@@ -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;
 }
 
index 1f35573a34e1de4de8c4a4a7373bead8064799ec..678cde834f1942c57cb9e2811e45b23a20f4082e 100644 (file)
@@ -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)
index 524d6167fb63e0da9692ac1c1b01dc91ba612069..c1efe939c774e2c9b909892f6c95434d6da760ee 100644 (file)
@@ -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);
 }
 
 /*
index 79ce38be15a14c97fdcfd09c4615452d6c9875bd..b3b418f519f3779492119c4eea9fefb84305db09 100644 (file)
@@ -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