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 <h...@lst.de> Index: linux-2.6/fs/direct-io.c =================================================================== --- linux-2.6.orig/fs/direct-io.c 2011-06-24 15:27:14.124896461 +0200 +++ linux-2.6/fs/direct-io.c 2011-06-24 15:47:03.358169584 +0200 @@ -293,11 +293,12 @@ static ssize_t dio_complete(struct dio * 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: linux-2.6/fs/ext4/inode.c =================================================================== --- linux-2.6.orig/fs/ext4/inode.c 2011-06-24 15:47:13.111502423 +0200 +++ linux-2.6/fs/ext4/inode.c 2011-06-24 15:50:13.471493302 +0200 @@ -3573,6 +3573,7 @@ static void ext4_end_io_dio(struct kiocb 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 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: linux-2.6/fs/ocfs2/aops.c =================================================================== --- linux-2.6.orig/fs/ocfs2/aops.c 2011-06-24 15:49:26.731495659 +0200 +++ linux-2.6/fs/ocfs2/aops.c 2011-06-24 15:49:48.324827901 +0200 @@ -577,6 +577,7 @@ static void ocfs2_dio_end_io(struct kioc if (is_async) aio_complete(iocb, ret, 0); + inode_dio_done(inode); } /* Index: linux-2.6/fs/xfs/linux-2.6/xfs_aops.c =================================================================== --- linux-2.6.orig/fs/xfs/linux-2.6/xfs_aops.c 2011-06-24 15:48:25.581498754 +0200 +++ linux-2.6/fs/xfs/linux-2.6/xfs_aops.c 2011-06-24 15:51:00.874824252 +0200 @@ -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 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html