aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authorjiayingz@google.com (Jiaying Zhang) <>2010-07-27 11:56:06 -0400
committerTheodore Ts'o <tytso@mit.edu>2010-07-27 11:56:06 -0400
commit5b3ff237bef43b9e7fb7d1eb858e29b73fd664f9 (patch)
treee3810d974a0e51a8c4b9046abdd36a5a4022abb3 /fs/ext4
parent552ef8024f909d9b3a7442d0ab0d48a22de24e9e (diff)
ext4: move aio completion after unwritten extent conversion
This patch is to be applied upon Christoph's "direct-io: move aio_complete into ->end_io" patch. It adds iocb and result fields to struct ext4_io_end_t, so that we can call aio_complete from ext4_end_io_nolock() after the extent conversion has finished. I have verified with Christoph's aio-dio test that used to fail after a few runs on an original kernel but now succeeds on the patched kernel. See http://thread.gmane.org/gmane.comp.file-systems.ext4/19659 for details. Signed-off-by: Jiaying Zhang <jiayingz@google.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/ext4.h4
-rw-r--r--fs/ext4/inode.c17
2 files changed, 15 insertions, 6 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 4c7d4727d6ba..fbb39478df28 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -170,13 +170,15 @@ struct mpage_da_data {
170}; 170};
171#define EXT4_IO_UNWRITTEN 0x1 171#define EXT4_IO_UNWRITTEN 0x1
172typedef struct ext4_io_end { 172typedef struct ext4_io_end {
173 struct list_head list; /* per-file finished AIO list */ 173 struct list_head list; /* per-file finished IO list */
174 struct inode *inode; /* file being written to */ 174 struct inode *inode; /* file being written to */
175 unsigned int flag; /* unwritten or not */ 175 unsigned int flag; /* unwritten or not */
176 struct page *page; /* page struct for buffer write */ 176 struct page *page; /* page struct for buffer write */
177 loff_t offset; /* offset in the file */ 177 loff_t offset; /* offset in the file */
178 ssize_t size; /* size of the extent */ 178 ssize_t size; /* size of the extent */
179 struct work_struct work; /* data work queue */ 179 struct work_struct work; /* data work queue */
180 struct kiocb *iocb; /* iocb struct for AIO */
181 int result; /* error value for AIO */
180} ext4_io_end_t; 182} ext4_io_end_t;
181 183
182/* 184/*
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 609159e990de..46d2079373c9 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -3668,6 +3668,8 @@ static int ext4_end_io_nolock(ext4_io_end_t *io)
3668 return ret; 3668 return ret;
3669 } 3669 }
3670 3670
3671 if (io->iocb)
3672 aio_complete(io->iocb, io->result, 0);
3671 /* clear the DIO AIO unwritten flag */ 3673 /* clear the DIO AIO unwritten flag */
3672 io->flag = 0; 3674 io->flag = 0;
3673 return ret; 3675 return ret;
@@ -3767,6 +3769,8 @@ static ext4_io_end_t *ext4_init_io_end (struct inode *inode, gfp_t flags)
3767 io->offset = 0; 3769 io->offset = 0;
3768 io->size = 0; 3770 io->size = 0;
3769 io->page = NULL; 3771 io->page = NULL;
3772 io->iocb = NULL;
3773 io->result = 0;
3770 INIT_WORK(&io->work, ext4_end_io_work); 3774 INIT_WORK(&io->work, ext4_end_io_work);
3771 INIT_LIST_HEAD(&io->list); 3775 INIT_LIST_HEAD(&io->list);
3772 } 3776 }
@@ -3796,12 +3800,18 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
3796 if (io_end->flag != EXT4_IO_UNWRITTEN){ 3800 if (io_end->flag != EXT4_IO_UNWRITTEN){
3797 ext4_free_io_end(io_end); 3801 ext4_free_io_end(io_end);
3798 iocb->private = NULL; 3802 iocb->private = NULL;
3799 goto out; 3803out:
3804 if (is_async)
3805 aio_complete(iocb, ret, 0);
3806 return;
3800 } 3807 }
3801 3808
3802 io_end->offset = offset; 3809 io_end->offset = offset;
3803 io_end->size = size; 3810 io_end->size = size;
3804 io_end->flag = EXT4_IO_UNWRITTEN; 3811 if (is_async) {
3812 io_end->iocb = iocb;
3813 io_end->result = ret;
3814 }
3805 wq = EXT4_SB(io_end->inode->i_sb)->dio_unwritten_wq; 3815 wq = EXT4_SB(io_end->inode->i_sb)->dio_unwritten_wq;
3806 3816
3807 /* queue the work to convert unwritten extents to written */ 3817 /* queue the work to convert unwritten extents to written */
@@ -3813,9 +3823,6 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
3813 list_add_tail(&io_end->list, &ei->i_completed_io_list); 3823 list_add_tail(&io_end->list, &ei->i_completed_io_list);
3814 spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); 3824 spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
3815 iocb->private = NULL; 3825 iocb->private = NULL;
3816out:
3817 if (is_async)
3818 aio_complete(iocb, ret, 0);
3819} 3826}
3820 3827
3821static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate) 3828static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate)