diff options
| -rw-r--r-- | fs/direct-io.c | 26 | ||||
| -rw-r--r-- | fs/ext4/inode.c | 10 | ||||
| -rw-r--r-- | fs/ocfs2/aops.c | 7 | ||||
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_aops.c | 7 | ||||
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_aops.h | 2 | ||||
| -rw-r--r-- | include/linux/fs.h | 3 |
6 files changed, 37 insertions, 18 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 | */ |
| 221 | static int dio_complete(struct dio *dio, loff_t offset, int ret) | 221 | static 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 | ||
| 3777 | static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset, | 3777 | static 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; |
| 3816 | out: | ||
| 3817 | if (is_async) | ||
| 3818 | aio_complete(iocb, ret, 0); | ||
| 3815 | } | 3819 | } |
| 3816 | 3820 | ||
| 3817 | static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate) | 3821 | static 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: | |||
| 578 | static void ocfs2_dio_end_io(struct kiocb *iocb, | 578 | static 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 | ||
| 1457 | STATIC ssize_t | 1462 | STATIC 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 | ||
| 42 | extern const struct address_space_operations xfs_address_space_operations; | 44 | extern const struct address_space_operations xfs_address_space_operations; |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 68ca1b0491af..f91affb7d530 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -415,7 +415,8 @@ struct buffer_head; | |||
| 415 | typedef int (get_block_t)(struct inode *inode, sector_t iblock, | 415 | typedef int (get_block_t)(struct inode *inode, sector_t iblock, |
| 416 | struct buffer_head *bh_result, int create); | 416 | struct buffer_head *bh_result, int create); |
| 417 | typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset, | 417 | typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset, |
| 418 | ssize_t bytes, void *private); | 418 | ssize_t bytes, void *private, int ret, |
| 419 | bool is_async); | ||
| 419 | 420 | ||
| 420 | /* | 421 | /* |
| 421 | * Attribute flags. These should be or-ed together to figure out what | 422 | * Attribute flags. These should be or-ed together to figure out what |
