aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/inode.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2013-09-04 09:04:39 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2013-09-04 09:23:46 -0400
commit7b7a8665edd8db733980389b098530f9e4f630b2 (patch)
tree968d570a9f0c4d861226aefed2f5f97a131c8d53 /fs/ext4/inode.c
parent4b6ccca701ef5977d0ffbc2c932430dea88b38b6 (diff)
direct-io: Implement generic deferred AIO completions
Add support to the core direct-io code to defer AIO completions to user context using a workqueue. This replaces opencoded and less efficient code in XFS and ext4 (we save a memory allocation for each direct IO) and will be needed to properly support O_(D)SYNC for AIO. The communication between the filesystem and the direct I/O code requires a new buffer head flag, which is a bit ugly but not avoidable until the direct I/O code stops abusing the buffer_head structure for communicating with the filesystems. Currently this creates a per-superblock unbound workqueue for these completions, which is taken from an earlier patch by Jan Kara. I'm not really convinced about this use and would prefer a "normal" global workqueue with a high concurrency limit, but this needs further discussion. JK: Fixed ext4 part, dynamic allocation of the workqueue. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/ext4/inode.c')
-rw-r--r--fs/ext4/inode.c28
1 files changed, 7 insertions, 21 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index c2ca04e67a4f..123bd81692d1 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -727,8 +727,12 @@ static int _ext4_get_block(struct inode *inode, sector_t iblock,
727 727
728 ret = ext4_map_blocks(handle, inode, &map, flags); 728 ret = ext4_map_blocks(handle, inode, &map, flags);
729 if (ret > 0) { 729 if (ret > 0) {
730 ext4_io_end_t *io_end = ext4_inode_aio(inode);
731
730 map_bh(bh, inode->i_sb, map.m_pblk); 732 map_bh(bh, inode->i_sb, map.m_pblk);
731 bh->b_state = (bh->b_state & ~EXT4_MAP_FLAGS) | map.m_flags; 733 bh->b_state = (bh->b_state & ~EXT4_MAP_FLAGS) | map.m_flags;
734 if (io_end && io_end->flag & EXT4_IO_END_UNWRITTEN)
735 set_buffer_defer_completion(bh);
732 bh->b_size = inode->i_sb->s_blocksize * map.m_len; 736 bh->b_size = inode->i_sb->s_blocksize * map.m_len;
733 ret = 0; 737 ret = 0;
734 } 738 }
@@ -2991,19 +2995,13 @@ static int ext4_get_block_write_nolock(struct inode *inode, sector_t iblock,
2991} 2995}
2992 2996
2993static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset, 2997static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
2994 ssize_t size, void *private, int ret, 2998 ssize_t size, void *private)
2995 bool is_async)
2996{ 2999{
2997 struct inode *inode = file_inode(iocb->ki_filp);
2998 ext4_io_end_t *io_end = iocb->private; 3000 ext4_io_end_t *io_end = iocb->private;
2999 3001
3000 /* if not async direct IO just return */ 3002 /* if not async direct IO just return */
3001 if (!io_end) { 3003 if (!io_end)
3002 inode_dio_done(inode);
3003 if (is_async)
3004 aio_complete(iocb, ret, 0);
3005 return; 3004 return;
3006 }
3007 3005
3008 ext_debug("ext4_end_io_dio(): io_end 0x%p " 3006 ext_debug("ext4_end_io_dio(): io_end 0x%p "
3009 "for inode %lu, iocb 0x%p, offset %llu, size %zd\n", 3007 "for inode %lu, iocb 0x%p, offset %llu, size %zd\n",
@@ -3013,11 +3011,7 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
3013 iocb->private = NULL; 3011 iocb->private = NULL;
3014 io_end->offset = offset; 3012 io_end->offset = offset;
3015 io_end->size = size; 3013 io_end->size = size;
3016 if (is_async) { 3014 ext4_put_io_end(io_end);
3017 io_end->iocb = iocb;
3018 io_end->result = ret;
3019 }
3020 ext4_put_io_end_defer(io_end);
3021} 3015}
3022 3016
3023/* 3017/*
@@ -3102,7 +3096,6 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
3102 ret = -ENOMEM; 3096 ret = -ENOMEM;
3103 goto retake_lock; 3097 goto retake_lock;
3104 } 3098 }
3105 io_end->flag |= EXT4_IO_END_DIRECT;
3106 /* 3099 /*
3107 * Grab reference for DIO. Will be dropped in ext4_end_io_dio() 3100 * Grab reference for DIO. Will be dropped in ext4_end_io_dio()
3108 */ 3101 */
@@ -3147,13 +3140,6 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
3147 if (ret <= 0 && ret != -EIOCBQUEUED && iocb->private) { 3140 if (ret <= 0 && ret != -EIOCBQUEUED && iocb->private) {
3148 WARN_ON(iocb->private != io_end); 3141 WARN_ON(iocb->private != io_end);
3149 WARN_ON(io_end->flag & EXT4_IO_END_UNWRITTEN); 3142 WARN_ON(io_end->flag & EXT4_IO_END_UNWRITTEN);
3150 WARN_ON(io_end->iocb);
3151 /*
3152 * Generic code already did inode_dio_done() so we
3153 * have to clear EXT4_IO_END_DIRECT to not do it for
3154 * the second time.
3155 */
3156 io_end->flag = 0;
3157 ext4_put_io_end(io_end); 3143 ext4_put_io_end(io_end);
3158 iocb->private = NULL; 3144 iocb->private = NULL;
3159 } 3145 }