aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2010-07-18 17:17:09 -0400
committerAlex Elder <aelder@sgi.com>2010-07-26 17:09:02 -0400
commit40e2e97316af6e62affab7a392e792494b8d9dde (patch)
tree981ce3b464467893683d47f52ae5d35fdd32d46a /fs
parent696123fca877905696591829c97a2cef11c8d048 (diff)
direct-io: move aio_complete into ->end_io
Filesystems with unwritten extent support must not complete an AIO request until the transaction to convert the extent has been commited. That means the aio_complete calls needs to be moved into the ->end_io callback so that the filesystem can control when to call it exactly. This makes a bit of a mess out of dio_complete and the ->end_io callback prototype even more complicated. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Jan Kara <jack@suse.cz> Signed-off-by: Alex Elder <aelder@sgi.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/direct-io.c26
-rw-r--r--fs/ext4/inode.c10
-rw-r--r--fs/ocfs2/aops.c7
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c7
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.h2
5 files changed, 35 insertions, 17 deletions
diff --git a/fs/direct-io.c b/fs/direct-io.c
index 7600aacf531d..a10cb91cadea 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -218,7 +218,7 @@ static struct page *dio_get_page(struct dio *dio)
218 * filesystems can use it to hold additional state between get_block calls and 218 * filesystems can use it to hold additional state between get_block calls and
219 * dio_complete. 219 * dio_complete.
220 */ 220 */
221static int dio_complete(struct dio *dio, loff_t offset, int ret) 221static int dio_complete(struct dio *dio, loff_t offset, int ret, bool is_async)
222{ 222{
223 ssize_t transferred = 0; 223 ssize_t transferred = 0;
224 224
@@ -239,14 +239,6 @@ static int dio_complete(struct dio *dio, loff_t offset, int ret)
239 transferred = dio->i_size - offset; 239 transferred = dio->i_size - offset;
240 } 240 }
241 241
242 if (dio->end_io && dio->result)
243 dio->end_io(dio->iocb, offset, transferred,
244 dio->map_bh.b_private);
245
246 if (dio->flags & DIO_LOCKING)
247 /* lockdep: non-owner release */
248 up_read_non_owner(&dio->inode->i_alloc_sem);
249
250 if (ret == 0) 242 if (ret == 0)
251 ret = dio->page_errors; 243 ret = dio->page_errors;
252 if (ret == 0) 244 if (ret == 0)
@@ -254,6 +246,17 @@ static int dio_complete(struct dio *dio, loff_t offset, int ret)
254 if (ret == 0) 246 if (ret == 0)
255 ret = transferred; 247 ret = transferred;
256 248
249 if (dio->end_io && dio->result) {
250 dio->end_io(dio->iocb, offset, transferred,
251 dio->map_bh.b_private, ret, is_async);
252 } else if (is_async) {
253 aio_complete(dio->iocb, ret, 0);
254 }
255
256 if (dio->flags & DIO_LOCKING)
257 /* lockdep: non-owner release */
258 up_read_non_owner(&dio->inode->i_alloc_sem);
259
257 return ret; 260 return ret;
258} 261}
259 262
@@ -277,8 +280,7 @@ static void dio_bio_end_aio(struct bio *bio, int error)
277 spin_unlock_irqrestore(&dio->bio_lock, flags); 280 spin_unlock_irqrestore(&dio->bio_lock, flags);
278 281
279 if (remaining == 0) { 282 if (remaining == 0) {
280 int ret = dio_complete(dio, dio->iocb->ki_pos, 0); 283 dio_complete(dio, dio->iocb->ki_pos, 0, true);
281 aio_complete(dio->iocb, ret, 0);
282 kfree(dio); 284 kfree(dio);
283 } 285 }
284} 286}
@@ -1126,7 +1128,7 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode,
1126 spin_unlock_irqrestore(&dio->bio_lock, flags); 1128 spin_unlock_irqrestore(&dio->bio_lock, flags);
1127 1129
1128 if (ret2 == 0) { 1130 if (ret2 == 0) {
1129 ret = dio_complete(dio, offset, ret); 1131 ret = dio_complete(dio, offset, ret, false);
1130 kfree(dio); 1132 kfree(dio);
1131 } else 1133 } else
1132 BUG_ON(ret != -EIOCBQUEUED); 1134 BUG_ON(ret != -EIOCBQUEUED);
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 42272d67955a..0afc8c1d8cf3 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -3775,7 +3775,8 @@ static ext4_io_end_t *ext4_init_io_end (struct inode *inode, gfp_t flags)
3775} 3775}
3776 3776
3777static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset, 3777static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
3778 ssize_t size, void *private) 3778 ssize_t size, void *private, int ret,
3779 bool is_async)
3779{ 3780{
3780 ext4_io_end_t *io_end = iocb->private; 3781 ext4_io_end_t *io_end = iocb->private;
3781 struct workqueue_struct *wq; 3782 struct workqueue_struct *wq;
@@ -3784,7 +3785,7 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
3784 3785
3785 /* if not async direct IO or dio with 0 bytes write, just return */ 3786 /* if not async direct IO or dio with 0 bytes write, just return */
3786 if (!io_end || !size) 3787 if (!io_end || !size)
3787 return; 3788 goto out;
3788 3789
3789 ext_debug("ext4_end_io_dio(): io_end 0x%p" 3790 ext_debug("ext4_end_io_dio(): io_end 0x%p"
3790 "for inode %lu, iocb 0x%p, offset %llu, size %llu\n", 3791 "for inode %lu, iocb 0x%p, offset %llu, size %llu\n",
@@ -3795,7 +3796,7 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
3795 if (io_end->flag != EXT4_IO_UNWRITTEN){ 3796 if (io_end->flag != EXT4_IO_UNWRITTEN){
3796 ext4_free_io_end(io_end); 3797 ext4_free_io_end(io_end);
3797 iocb->private = NULL; 3798 iocb->private = NULL;
3798 return; 3799 goto out;
3799 } 3800 }
3800 3801
3801 io_end->offset = offset; 3802 io_end->offset = offset;
@@ -3812,6 +3813,9 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
3812 list_add_tail(&io_end->list, &ei->i_completed_io_list); 3813 list_add_tail(&io_end->list, &ei->i_completed_io_list);
3813 spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); 3814 spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
3814 iocb->private = NULL; 3815 iocb->private = NULL;
3816out:
3817 if (is_async)
3818 aio_complete(iocb, ret, 0);
3815} 3819}
3816 3820
3817static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate) 3821static 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 356e976772bf..96337a4fbbdf 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -578,7 +578,9 @@ bail:
578static void ocfs2_dio_end_io(struct kiocb *iocb, 578static void ocfs2_dio_end_io(struct kiocb *iocb,
579 loff_t offset, 579 loff_t offset,
580 ssize_t bytes, 580 ssize_t bytes,
581 void *private) 581 void *private,
582 int ret,
583 bool is_async)
582{ 584{
583 struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode; 585 struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode;
584 int level; 586 int level;
@@ -592,6 +594,9 @@ static void ocfs2_dio_end_io(struct kiocb *iocb,
592 if (!level) 594 if (!level)
593 up_read(&inode->i_alloc_sem); 595 up_read(&inode->i_alloc_sem);
594 ocfs2_rw_unlock(inode, level); 596 ocfs2_rw_unlock(inode, level);
597
598 if (is_async)
599 aio_complete(iocb, ret, 0);
595} 600}
596 601
597/* 602/*
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 8abbf0532ea1..95d1e2695c3a 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -1406,7 +1406,9 @@ xfs_end_io_direct(
1406 struct kiocb *iocb, 1406 struct kiocb *iocb,
1407 loff_t offset, 1407 loff_t offset,
1408 ssize_t size, 1408 ssize_t size,
1409 void *private) 1409 void *private,
1410 int ret,
1411 bool is_async)
1410{ 1412{
1411 xfs_ioend_t *ioend = iocb->private; 1413 xfs_ioend_t *ioend = iocb->private;
1412 1414
@@ -1452,6 +1454,9 @@ xfs_end_io_direct(
1452 * against double-freeing. 1454 * against double-freeing.
1453 */ 1455 */
1454 iocb->private = NULL; 1456 iocb->private = NULL;
1457
1458 if (is_async)
1459 aio_complete(iocb, ret, 0);
1455} 1460}
1456 1461
1457STATIC ssize_t 1462STATIC ssize_t
diff --git a/fs/xfs/linux-2.6/xfs_aops.h b/fs/xfs/linux-2.6/xfs_aops.h
index 319da173cc1a..c5057fb6237a 100644
--- a/fs/xfs/linux-2.6/xfs_aops.h
+++ b/fs/xfs/linux-2.6/xfs_aops.h
@@ -37,6 +37,8 @@ typedef struct xfs_ioend {
37 size_t io_size; /* size of the extent */ 37 size_t io_size; /* size of the extent */
38 xfs_off_t io_offset; /* offset in the file */ 38 xfs_off_t io_offset; /* offset in the file */
39 struct work_struct io_work; /* xfsdatad work queue */ 39 struct work_struct io_work; /* xfsdatad work queue */
40 struct kiocb *io_iocb;
41 int io_result;
40} xfs_ioend_t; 42} xfs_ioend_t;
41 43
42extern const struct address_space_operations xfs_address_space_operations; 44extern const struct address_space_operations xfs_address_space_operations;