diff options
| author | Kiyoshi Ueda <k-ueda@ct.jp.nec.com> | 2007-12-11 17:40:30 -0500 |
|---|---|---|
| committer | Jens Axboe <jens.axboe@oracle.com> | 2008-01-28 04:35:53 -0500 |
| commit | 336cdb4003200a90f4fc52a4e9ccc2baa570fffb (patch) | |
| tree | dcb7f736738232c0e853a1ba796ca35d5b18c503 | |
| parent | 91525300baf162e83e923b09ca286f9205e21522 (diff) | |
blk_end_request: add new request completion interface (take 4)
This patch adds 2 new interfaces for request completion:
o blk_end_request() : called without queue lock
o __blk_end_request() : called with queue lock held
blk_end_request takes 'error' as an argument instead of 'uptodate',
which current end_that_request_* take.
The meanings of values are below and the value is used when bio is
completed.
0 : success
< 0 : error
Some device drivers call some generic functions below between
end_that_request_{first/chunk} and end_that_request_last().
o add_disk_randomness()
o blk_queue_end_tag()
o blkdev_dequeue_request()
These are called in the blk_end_request interfaces as a part of
generic request completion.
So all device drivers become to call above functions.
To decide whether to call blkdev_dequeue_request(), blk_end_request
uses list_empty(&rq->queuelist) (blk_queued_rq() macro is added for it).
So drivers must re-initialize it using list_init() or so before calling
blk_end_request if drivers use it for its specific purpose.
(Currently, there is no driver which completes request without
re-initializing the queuelist after used it. So rq->queuelist
can be used for the purpose above.)
"Normal" drivers can be converted to use blk_end_request()
in a standard way shown below.
a) end_that_request_{chunk/first}
spin_lock_irqsave()
(add_disk_randomness(), blk_queue_end_tag(), blkdev_dequeue_request())
end_that_request_last()
spin_unlock_irqrestore()
=> blk_end_request()
b) spin_lock_irqsave()
end_that_request_{chunk/first}
(add_disk_randomness(), blk_queue_end_tag(), blkdev_dequeue_request())
end_that_request_last()
spin_unlock_irqrestore()
=> spin_lock_irqsave()
__blk_end_request()
spin_unlock_irqsave()
c) spin_lock_irqsave()
(add_disk_randomness(), blk_queue_end_tag(), blkdev_dequeue_request())
end_that_request_last()
spin_unlock_irqrestore()
=> blk_end_request() or spin_lock_irqsave()
__blk_end_request()
spin_unlock_irqrestore()
Signed-off-by: Kiyoshi Ueda <k-ueda@ct.jp.nec.com>
Signed-off-by: Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
| -rw-r--r-- | block/ll_rw_blk.c | 96 | ||||
| -rw-r--r-- | include/linux/blkdev.h | 4 |
2 files changed, 100 insertions, 0 deletions
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 3d0422f48453..5c01911af47c 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c | |||
| @@ -3791,6 +3791,102 @@ void end_request(struct request *req, int uptodate) | |||
| 3791 | } | 3791 | } |
| 3792 | EXPORT_SYMBOL(end_request); | 3792 | EXPORT_SYMBOL(end_request); |
| 3793 | 3793 | ||
| 3794 | static void complete_request(struct request *rq, int error) | ||
| 3795 | { | ||
| 3796 | /* | ||
| 3797 | * REMOVEME: This conversion is transitional and will be removed | ||
| 3798 | * when old end_that_request_* are unexported. | ||
| 3799 | */ | ||
| 3800 | int uptodate = 1; | ||
| 3801 | if (error) | ||
| 3802 | uptodate = (error == -EIO) ? 0 : error; | ||
| 3803 | |||
| 3804 | if (blk_rq_tagged(rq)) | ||
| 3805 | blk_queue_end_tag(rq->q, rq); | ||
| 3806 | |||
| 3807 | if (blk_queued_rq(rq)) | ||
| 3808 | blkdev_dequeue_request(rq); | ||
| 3809 | |||
| 3810 | end_that_request_last(rq, uptodate); | ||
| 3811 | } | ||
| 3812 | |||
| 3813 | /** | ||
| 3814 | * blk_end_request - Helper function for drivers to complete the request. | ||
| 3815 | * @rq: the request being processed | ||
| 3816 | * @error: 0 for success, < 0 for error | ||
| 3817 | * @nr_bytes: number of bytes to complete | ||
| 3818 | * | ||
| 3819 | * Description: | ||
| 3820 | * Ends I/O on a number of bytes attached to @rq. | ||
| 3821 | * If @rq has leftover, sets it up for the next range of segments. | ||
| 3822 | * | ||
| 3823 | * Return: | ||
| 3824 | * 0 - we are done with this request | ||
| 3825 | * 1 - still buffers pending for this request | ||
| 3826 | **/ | ||
| 3827 | int blk_end_request(struct request *rq, int error, int nr_bytes) | ||
| 3828 | { | ||
| 3829 | struct request_queue *q = rq->q; | ||
| 3830 | unsigned long flags = 0UL; | ||
| 3831 | /* | ||
| 3832 | * REMOVEME: This conversion is transitional and will be removed | ||
| 3833 | * when old end_that_request_* are unexported. | ||
| 3834 | */ | ||
| 3835 | int uptodate = 1; | ||
| 3836 | if (error) | ||
| 3837 | uptodate = (error == -EIO) ? 0 : error; | ||
| 3838 | |||
| 3839 | if (blk_fs_request(rq) || blk_pc_request(rq)) { | ||
| 3840 | if (__end_that_request_first(rq, uptodate, nr_bytes)) | ||
| 3841 | return 1; | ||
| 3842 | } | ||
| 3843 | |||
| 3844 | add_disk_randomness(rq->rq_disk); | ||
| 3845 | |||
| 3846 | spin_lock_irqsave(q->queue_lock, flags); | ||
| 3847 | complete_request(rq, error); | ||
| 3848 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
| 3849 | |||
| 3850 | return 0; | ||
| 3851 | } | ||
| 3852 | EXPORT_SYMBOL_GPL(blk_end_request); | ||
| 3853 | |||
| 3854 | /** | ||
| 3855 | * __blk_end_request - Helper function for drivers to complete the request. | ||
| 3856 | * @rq: the request being processed | ||
| 3857 | * @error: 0 for success, < 0 for error | ||
| 3858 | * @nr_bytes: number of bytes to complete | ||
| 3859 | * | ||
| 3860 | * Description: | ||
| 3861 | * Must be called with queue lock held unlike blk_end_request(). | ||
| 3862 | * | ||
| 3863 | * Return: | ||
| 3864 | * 0 - we are done with this request | ||
| 3865 | * 1 - still buffers pending for this request | ||
| 3866 | **/ | ||
| 3867 | int __blk_end_request(struct request *rq, int error, int nr_bytes) | ||
| 3868 | { | ||
| 3869 | /* | ||
| 3870 | * REMOVEME: This conversion is transitional and will be removed | ||
| 3871 | * when old end_that_request_* are unexported. | ||
| 3872 | */ | ||
| 3873 | int uptodate = 1; | ||
| 3874 | if (error) | ||
| 3875 | uptodate = (error == -EIO) ? 0 : error; | ||
| 3876 | |||
| 3877 | if (blk_fs_request(rq) || blk_pc_request(rq)) { | ||
| 3878 | if (__end_that_request_first(rq, uptodate, nr_bytes)) | ||
| 3879 | return 1; | ||
| 3880 | } | ||
| 3881 | |||
| 3882 | add_disk_randomness(rq->rq_disk); | ||
| 3883 | |||
| 3884 | complete_request(rq, error); | ||
| 3885 | |||
| 3886 | return 0; | ||
| 3887 | } | ||
| 3888 | EXPORT_SYMBOL_GPL(__blk_end_request); | ||
| 3889 | |||
| 3794 | static void blk_rq_bio_prep(struct request_queue *q, struct request *rq, | 3890 | static void blk_rq_bio_prep(struct request_queue *q, struct request *rq, |
| 3795 | struct bio *bio) | 3891 | struct bio *bio) |
| 3796 | { | 3892 | { |
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 49b7a4c31a6d..3b212f02db8d 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h | |||
| @@ -537,6 +537,8 @@ enum { | |||
| 537 | #define blk_fua_rq(rq) ((rq)->cmd_flags & REQ_FUA) | 537 | #define blk_fua_rq(rq) ((rq)->cmd_flags & REQ_FUA) |
| 538 | #define blk_bidi_rq(rq) ((rq)->next_rq != NULL) | 538 | #define blk_bidi_rq(rq) ((rq)->next_rq != NULL) |
| 539 | #define blk_empty_barrier(rq) (blk_barrier_rq(rq) && blk_fs_request(rq) && !(rq)->hard_nr_sectors) | 539 | #define blk_empty_barrier(rq) (blk_barrier_rq(rq) && blk_fs_request(rq) && !(rq)->hard_nr_sectors) |
| 540 | /* rq->queuelist of dequeued request must be list_empty() */ | ||
| 541 | #define blk_queued_rq(rq) (!list_empty(&(rq)->queuelist)) | ||
| 540 | 542 | ||
| 541 | #define list_entry_rq(ptr) list_entry((ptr), struct request, queuelist) | 543 | #define list_entry_rq(ptr) list_entry((ptr), struct request, queuelist) |
| 542 | 544 | ||
| @@ -724,6 +726,8 @@ static inline void blk_run_address_space(struct address_space *mapping) | |||
| 724 | * for parts of the original function. This prevents | 726 | * for parts of the original function. This prevents |
| 725 | * code duplication in drivers. | 727 | * code duplication in drivers. |
| 726 | */ | 728 | */ |
| 729 | extern int blk_end_request(struct request *rq, int error, int nr_bytes); | ||
| 730 | extern int __blk_end_request(struct request *rq, int error, int nr_bytes); | ||
| 727 | extern int end_that_request_first(struct request *, int, int); | 731 | extern int end_that_request_first(struct request *, int, int); |
| 728 | extern int end_that_request_chunk(struct request *, int, int); | 732 | extern int end_that_request_chunk(struct request *, int, int); |
| 729 | extern void end_that_request_last(struct request *, int); | 733 | extern void end_that_request_last(struct request *, int); |
