From 336cdb4003200a90f4fc52a4e9ccc2baa570fffb Mon Sep 17 00:00:00 2001 From: Kiyoshi Ueda Date: Tue, 11 Dec 2007 17:40:30 -0500 Subject: 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 Signed-off-by: Jun'ichi Nomura Signed-off-by: Jens Axboe --- block/ll_rw_blk.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) (limited to 'block') 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) } EXPORT_SYMBOL(end_request); +static void complete_request(struct request *rq, int error) +{ + /* + * REMOVEME: This conversion is transitional and will be removed + * when old end_that_request_* are unexported. + */ + int uptodate = 1; + if (error) + uptodate = (error == -EIO) ? 0 : error; + + if (blk_rq_tagged(rq)) + blk_queue_end_tag(rq->q, rq); + + if (blk_queued_rq(rq)) + blkdev_dequeue_request(rq); + + end_that_request_last(rq, uptodate); +} + +/** + * blk_end_request - Helper function for drivers to complete the request. + * @rq: the request being processed + * @error: 0 for success, < 0 for error + * @nr_bytes: number of bytes to complete + * + * Description: + * Ends I/O on a number of bytes attached to @rq. + * If @rq has leftover, sets it up for the next range of segments. + * + * Return: + * 0 - we are done with this request + * 1 - still buffers pending for this request + **/ +int blk_end_request(struct request *rq, int error, int nr_bytes) +{ + struct request_queue *q = rq->q; + unsigned long flags = 0UL; + /* + * REMOVEME: This conversion is transitional and will be removed + * when old end_that_request_* are unexported. + */ + int uptodate = 1; + if (error) + uptodate = (error == -EIO) ? 0 : error; + + if (blk_fs_request(rq) || blk_pc_request(rq)) { + if (__end_that_request_first(rq, uptodate, nr_bytes)) + return 1; + } + + add_disk_randomness(rq->rq_disk); + + spin_lock_irqsave(q->queue_lock, flags); + complete_request(rq, error); + spin_unlock_irqrestore(q->queue_lock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(blk_end_request); + +/** + * __blk_end_request - Helper function for drivers to complete the request. + * @rq: the request being processed + * @error: 0 for success, < 0 for error + * @nr_bytes: number of bytes to complete + * + * Description: + * Must be called with queue lock held unlike blk_end_request(). + * + * Return: + * 0 - we are done with this request + * 1 - still buffers pending for this request + **/ +int __blk_end_request(struct request *rq, int error, int nr_bytes) +{ + /* + * REMOVEME: This conversion is transitional and will be removed + * when old end_that_request_* are unexported. + */ + int uptodate = 1; + if (error) + uptodate = (error == -EIO) ? 0 : error; + + if (blk_fs_request(rq) || blk_pc_request(rq)) { + if (__end_that_request_first(rq, uptodate, nr_bytes)) + return 1; + } + + add_disk_randomness(rq->rq_disk); + + complete_request(rq, error); + + return 0; +} +EXPORT_SYMBOL_GPL(__blk_end_request); + static void blk_rq_bio_prep(struct request_queue *q, struct request *rq, struct bio *bio) { -- cgit v1.2.3 From 3b11313a6c2a42425bf06e92528bda6affd58dec Mon Sep 17 00:00:00 2001 From: Kiyoshi Ueda Date: Tue, 11 Dec 2007 17:41:17 -0500 Subject: blk_end_request: add/export functions to get request size (take 4) This patch adds/exports functions to get the size of request in bytes. They are useful because blk_end_request interfaces take bytes as a completed I/O size instead of sectors. Signed-off-by: Kiyoshi Ueda Signed-off-by: Jun'ichi Nomura Signed-off-by: Jens Axboe --- block/ll_rw_blk.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) (limited to 'block') diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 5c01911af47c..8b2b2509f60e 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -3723,13 +3723,32 @@ static inline void __end_request(struct request *rq, int uptodate, } } -static unsigned int rq_byte_size(struct request *rq) +/** + * blk_rq_bytes - Returns bytes left to complete in the entire request + **/ +unsigned int blk_rq_bytes(struct request *rq) { if (blk_fs_request(rq)) return rq->hard_nr_sectors << 9; return rq->data_len; } +EXPORT_SYMBOL_GPL(blk_rq_bytes); + +/** + * blk_rq_cur_bytes - Returns bytes left to complete in the current segment + **/ +unsigned int blk_rq_cur_bytes(struct request *rq) +{ + if (blk_fs_request(rq)) + return rq->current_nr_sectors << 9; + + if (rq->bio) + return rq->bio->bi_size; + + return rq->data_len; +} +EXPORT_SYMBOL_GPL(blk_rq_cur_bytes); /** * end_queued_request - end all I/O on a queued request @@ -3744,7 +3763,7 @@ static unsigned int rq_byte_size(struct request *rq) **/ void end_queued_request(struct request *rq, int uptodate) { - __end_request(rq, uptodate, rq_byte_size(rq), 1); + __end_request(rq, uptodate, blk_rq_bytes(rq), 1); } EXPORT_SYMBOL(end_queued_request); @@ -3761,7 +3780,7 @@ EXPORT_SYMBOL(end_queued_request); **/ void end_dequeued_request(struct request *rq, int uptodate) { - __end_request(rq, uptodate, rq_byte_size(rq), 0); + __end_request(rq, uptodate, blk_rq_bytes(rq), 0); } EXPORT_SYMBOL(end_dequeued_request); -- cgit v1.2.3 From 9e6e39f2c478fff2e9d3430cdfe6730877942ed6 Mon Sep 17 00:00:00 2001 From: Kiyoshi Ueda Date: Tue, 11 Dec 2007 17:41:54 -0500 Subject: blk_end_request: changing block layer core (take 4) This patch converts core parts of block layer to use blk_end_request interfaces. Related 'uptodate' arguments are converted to 'error'. 'dequeue' argument was originally introduced for end_dequeued_request(), where no attempt should be made to dequeue the request as it's already dequeued. However, it's not necessary as it can be checked with list_empty(&rq->queuelist). (Dequeued request has empty list and queued request doesn't.) And it has been done in blk_end_request interfaces. As a result of this patch, end_queued_request() and end_dequeued_request() become identical. A future patch will merge and rename them and change users of those functions. Signed-off-by: Kiyoshi Ueda Signed-off-by: Jun'ichi Nomura Signed-off-by: Jens Axboe --- block/ll_rw_blk.c | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) (limited to 'block') diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 8b2b2509f60e..fb951198c70e 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -347,7 +347,6 @@ unsigned blk_ordered_req_seq(struct request *rq) void blk_ordered_complete_seq(struct request_queue *q, unsigned seq, int error) { struct request *rq; - int uptodate; if (error && !q->orderr) q->orderr = error; @@ -361,15 +360,11 @@ void blk_ordered_complete_seq(struct request_queue *q, unsigned seq, int error) /* * Okay, sequence complete. */ - uptodate = 1; - if (q->orderr) - uptodate = q->orderr; - q->ordseq = 0; rq = q->orig_bar_rq; - end_that_request_first(rq, uptodate, rq->hard_nr_sectors); - end_that_request_last(rq, uptodate); + if (__blk_end_request(rq, q->orderr, blk_rq_bytes(rq))) + BUG(); } static void pre_flush_end_io(struct request *rq, int error) @@ -486,9 +481,9 @@ int blk_do_ordered(struct request_queue *q, struct request **rqp) * ORDERED_NONE while this request is on it. */ blkdev_dequeue_request(rq); - end_that_request_first(rq, -EOPNOTSUPP, - rq->hard_nr_sectors); - end_that_request_last(rq, -EOPNOTSUPP); + if (__blk_end_request(rq, -EOPNOTSUPP, + blk_rq_bytes(rq))) + BUG(); *rqp = NULL; return 0; } @@ -3713,14 +3708,14 @@ void end_that_request_last(struct request *req, int uptodate) EXPORT_SYMBOL(end_that_request_last); static inline void __end_request(struct request *rq, int uptodate, - unsigned int nr_bytes, int dequeue) + unsigned int nr_bytes) { - if (!end_that_request_chunk(rq, uptodate, nr_bytes)) { - if (dequeue) - blkdev_dequeue_request(rq); - add_disk_randomness(rq->rq_disk); - end_that_request_last(rq, uptodate); - } + int error = 0; + + if (uptodate <= 0) + error = uptodate ? uptodate : -EIO; + + __blk_end_request(rq, error, nr_bytes); } /** @@ -3763,7 +3758,7 @@ EXPORT_SYMBOL_GPL(blk_rq_cur_bytes); **/ void end_queued_request(struct request *rq, int uptodate) { - __end_request(rq, uptodate, blk_rq_bytes(rq), 1); + __end_request(rq, uptodate, blk_rq_bytes(rq)); } EXPORT_SYMBOL(end_queued_request); @@ -3780,7 +3775,7 @@ EXPORT_SYMBOL(end_queued_request); **/ void end_dequeued_request(struct request *rq, int uptodate) { - __end_request(rq, uptodate, blk_rq_bytes(rq), 0); + __end_request(rq, uptodate, blk_rq_bytes(rq)); } EXPORT_SYMBOL(end_dequeued_request); @@ -3806,7 +3801,7 @@ EXPORT_SYMBOL(end_dequeued_request); **/ void end_request(struct request *req, int uptodate) { - __end_request(req, uptodate, req->hard_cur_sectors << 9, 1); + __end_request(req, uptodate, req->hard_cur_sectors << 9); } EXPORT_SYMBOL(end_request); -- cgit v1.2.3 From e19a3ab058fe91c8c54d43dc56dccf7eb386478e Mon Sep 17 00:00:00 2001 From: Kiyoshi Ueda Date: Tue, 11 Dec 2007 17:51:02 -0500 Subject: blk_end_request: add callback feature (take 4) This patch adds a variant of the interface, blk_end_request_callback(), which has driver callback feature. Drivers may need to do special works between end_that_request_first() and end_that_request_last(). For such drivers, blk_end_request_callback() allows it to pass a callback function which is called between end_that_request_first() and end_that_request_last(). This interface is only for fallback of other blk_end_request interfaces. Drivers should avoid their tricky behaviors and use other interfaces as much as possible. Currently, only one driver, ide-cd, needs this interface. So this interface should/will be removed, after the driver removes such tricky behaviors. o ide-cd (cdrom_newpc_intr()) In PIO mode, cdrom_newpc_intr() needs to defer end_that_request_last() until the device clears DRQ_STAT and raises an interrupt after end_that_request_first(). So end_that_request_first() and end_that_request_last() are called separately in cdrom_newpc_intr(). This means blk_end_request_callback() has to return without completing request even if no leftover in the request. To satisfy the requirement, callback function has return value so that drivers can tell blk_end_request_callback() to return without completing request. Signed-off-by: Kiyoshi Ueda Signed-off-by: Jun'ichi Nomura Signed-off-by: Jens Axboe --- block/ll_rw_blk.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 6 deletions(-) (limited to 'block') diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index fb951198c70e..919e4baf478b 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -3825,10 +3825,14 @@ static void complete_request(struct request *rq, int error) } /** - * blk_end_request - Helper function for drivers to complete the request. - * @rq: the request being processed - * @error: 0 for success, < 0 for error - * @nr_bytes: number of bytes to complete + * blk_end_io - Generic end_io function to complete a request. + * @rq: the request being processed + * @error: 0 for success, < 0 for error + * @nr_bytes: number of bytes to complete + * @drv_callback: function called between completion of bios in the request + * and completion of the request. + * If the callback returns non 0, this helper returns without + * completion of the request. * * Description: * Ends I/O on a number of bytes attached to @rq. @@ -3836,9 +3840,10 @@ static void complete_request(struct request *rq, int error) * * Return: * 0 - we are done with this request - * 1 - still buffers pending for this request + * 1 - this request is not freed yet, it still has pending buffers. **/ -int blk_end_request(struct request *rq, int error, int nr_bytes) +static int blk_end_io(struct request *rq, int error, int nr_bytes, + int (drv_callback)(struct request *)) { struct request_queue *q = rq->q; unsigned long flags = 0UL; @@ -3855,6 +3860,10 @@ int blk_end_request(struct request *rq, int error, int nr_bytes) return 1; } + /* Special feature for tricky drivers */ + if (drv_callback && drv_callback(rq)) + return 1; + add_disk_randomness(rq->rq_disk); spin_lock_irqsave(q->queue_lock, flags); @@ -3863,6 +3872,25 @@ int blk_end_request(struct request *rq, int error, int nr_bytes) return 0; } + +/** + * blk_end_request - Helper function for drivers to complete the request. + * @rq: the request being processed + * @error: 0 for success, < 0 for error + * @nr_bytes: number of bytes to complete + * + * Description: + * Ends I/O on a number of bytes attached to @rq. + * If @rq has leftover, sets it up for the next range of segments. + * + * Return: + * 0 - we are done with this request + * 1 - still buffers pending for this request + **/ +int blk_end_request(struct request *rq, int error, int nr_bytes) +{ + return blk_end_io(rq, error, nr_bytes, NULL); +} EXPORT_SYMBOL_GPL(blk_end_request); /** @@ -3901,6 +3929,38 @@ int __blk_end_request(struct request *rq, int error, int nr_bytes) } EXPORT_SYMBOL_GPL(__blk_end_request); +/** + * blk_end_request_callback - Special helper function for tricky drivers + * @rq: the request being processed + * @error: 0 for success, < 0 for error + * @nr_bytes: number of bytes to complete + * @drv_callback: function called between completion of bios in the request + * and completion of the request. + * If the callback returns non 0, this helper returns without + * completion of the request. + * + * Description: + * Ends I/O on a number of bytes attached to @rq. + * If @rq has leftover, sets it up for the next range of segments. + * + * This special helper function is used only for existing tricky drivers. + * (e.g. cdrom_newpc_intr() of ide-cd) + * This interface will be removed when such drivers are rewritten. + * Don't use this interface in other places anymore. + * + * Return: + * 0 - we are done with this request + * 1 - this request is not freed yet. + * this request still has pending buffers or + * the driver doesn't want to finish this request yet. + **/ +int blk_end_request_callback(struct request *rq, int error, int nr_bytes, + int (drv_callback)(struct request *)) +{ + return blk_end_io(rq, error, nr_bytes, drv_callback); +} +EXPORT_SYMBOL_GPL(blk_end_request_callback); + static void blk_rq_bio_prep(struct request_queue *q, struct request *rq, struct bio *bio) { -- cgit v1.2.3 From e3a04fe34a3ec81ddeddb6c73fb7299716cffbb0 Mon Sep 17 00:00:00 2001 From: Kiyoshi Ueda Date: Tue, 11 Dec 2007 17:51:46 -0500 Subject: blk_end_request: add bidi completion interface (take 4) This patch adds a variant of the interface, blk_end_bidi_request(), which completes a bidi request. Bidi request must be completed as a whole, both rq and rq->next_rq at once. So the interface has 2 arguments for completion size. As for ->end_io, only rq->end_io is called (rq->next_rq->end_io is not called). So if special completion handling is needed, the handler must be set to rq->end_io. And the handler must take care of freeing next_rq too, since the interface doesn't care of it if rq->end_io is not NULL. Cc: Boaz Harrosh Signed-off-by: Kiyoshi Ueda Signed-off-by: Jun'ichi Nomura Signed-off-by: Jens Axboe --- block/ll_rw_blk.c | 40 +++++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) (limited to 'block') diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 919e4baf478b..4889f7a8c2b7 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -3821,6 +3821,9 @@ static void complete_request(struct request *rq, int error) if (blk_queued_rq(rq)) blkdev_dequeue_request(rq); + if (blk_bidi_rq(rq) && !rq->end_io) + __blk_put_request(rq->next_rq->q, rq->next_rq); + end_that_request_last(rq, uptodate); } @@ -3828,14 +3831,15 @@ static void complete_request(struct request *rq, int error) * blk_end_io - Generic end_io function to complete a request. * @rq: the request being processed * @error: 0 for success, < 0 for error - * @nr_bytes: number of bytes to complete + * @nr_bytes: number of bytes to complete @rq + * @bidi_bytes: number of bytes to complete @rq->next_rq * @drv_callback: function called between completion of bios in the request * and completion of the request. * If the callback returns non 0, this helper returns without * completion of the request. * * Description: - * Ends I/O on a number of bytes attached to @rq. + * Ends I/O on a number of bytes attached to @rq and @rq->next_rq. * If @rq has leftover, sets it up for the next range of segments. * * Return: @@ -3843,7 +3847,7 @@ static void complete_request(struct request *rq, int error) * 1 - this request is not freed yet, it still has pending buffers. **/ static int blk_end_io(struct request *rq, int error, int nr_bytes, - int (drv_callback)(struct request *)) + int bidi_bytes, int (drv_callback)(struct request *)) { struct request_queue *q = rq->q; unsigned long flags = 0UL; @@ -3858,6 +3862,11 @@ static int blk_end_io(struct request *rq, int error, int nr_bytes, if (blk_fs_request(rq) || blk_pc_request(rq)) { if (__end_that_request_first(rq, uptodate, nr_bytes)) return 1; + + /* Bidi request must be completed as a whole */ + if (blk_bidi_rq(rq) && + __end_that_request_first(rq->next_rq, uptodate, bidi_bytes)) + return 1; } /* Special feature for tricky drivers */ @@ -3889,7 +3898,7 @@ static int blk_end_io(struct request *rq, int error, int nr_bytes, **/ int blk_end_request(struct request *rq, int error, int nr_bytes) { - return blk_end_io(rq, error, nr_bytes, NULL); + return blk_end_io(rq, error, nr_bytes, 0, NULL); } EXPORT_SYMBOL_GPL(blk_end_request); @@ -3929,6 +3938,27 @@ int __blk_end_request(struct request *rq, int error, int nr_bytes) } EXPORT_SYMBOL_GPL(__blk_end_request); +/** + * blk_end_bidi_request - Helper function for drivers to complete bidi request. + * @rq: the bidi request being processed + * @error: 0 for success, < 0 for error + * @nr_bytes: number of bytes to complete @rq + * @bidi_bytes: number of bytes to complete @rq->next_rq + * + * Description: + * Ends I/O on a number of bytes attached to @rq and @rq->next_rq. + * + * Return: + * 0 - we are done with this request + * 1 - still buffers pending for this request + **/ +int blk_end_bidi_request(struct request *rq, int error, int nr_bytes, + int bidi_bytes) +{ + return blk_end_io(rq, error, nr_bytes, bidi_bytes, NULL); +} +EXPORT_SYMBOL_GPL(blk_end_bidi_request); + /** * blk_end_request_callback - Special helper function for tricky drivers * @rq: the request being processed @@ -3957,7 +3987,7 @@ EXPORT_SYMBOL_GPL(__blk_end_request); int blk_end_request_callback(struct request *rq, int error, int nr_bytes, int (drv_callback)(struct request *)) { - return blk_end_io(rq, error, nr_bytes, drv_callback); + return blk_end_io(rq, error, nr_bytes, 0, drv_callback); } EXPORT_SYMBOL_GPL(blk_end_request_callback); -- cgit v1.2.3 From 3bcddeac1c4c7e6fb90531b80f236b1a05dfe514 Mon Sep 17 00:00:00 2001 From: Kiyoshi Ueda Date: Tue, 11 Dec 2007 17:52:28 -0500 Subject: blk_end_request: remove/unexport end_that_request_* (take 4) This patch removes the following functions: o end_that_request_first() o end_that_request_chunk() and stops exporting the functions below: o end_that_request_last() Cc: Boaz Harrosh Signed-off-by: Kiyoshi Ueda Signed-off-by: Jun'ichi Nomura Signed-off-by: Jens Axboe --- block/ll_rw_blk.c | 61 ++++++++++++++----------------------------------------- 1 file changed, 15 insertions(+), 46 deletions(-) (limited to 'block') diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 4889f7a8c2b7..4bd1803919ce 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -3432,6 +3432,20 @@ static void blk_recalc_rq_sectors(struct request *rq, int nsect) } } +/** + * __end_that_request_first - end I/O on a request + * @req: the request being processed + * @uptodate: 1 for success, 0 for I/O error, < 0 for specific error + * @nr_bytes: number of bytes to complete + * + * Description: + * Ends I/O on a number of bytes attached to @req, and sets it up + * for the next range of segments (if any) in the cluster. + * + * Return: + * 0 - we are done with this request, call end_that_request_last() + * 1 - still buffers pending for this request + **/ static int __end_that_request_first(struct request *req, int uptodate, int nr_bytes) { @@ -3548,49 +3562,6 @@ static int __end_that_request_first(struct request *req, int uptodate, return 1; } -/** - * end_that_request_first - end I/O on a request - * @req: the request being processed - * @uptodate: 1 for success, 0 for I/O error, < 0 for specific error - * @nr_sectors: number of sectors to end I/O on - * - * Description: - * Ends I/O on a number of sectors attached to @req, and sets it up - * for the next range of segments (if any) in the cluster. - * - * Return: - * 0 - we are done with this request, call end_that_request_last() - * 1 - still buffers pending for this request - **/ -int end_that_request_first(struct request *req, int uptodate, int nr_sectors) -{ - return __end_that_request_first(req, uptodate, nr_sectors << 9); -} - -EXPORT_SYMBOL(end_that_request_first); - -/** - * end_that_request_chunk - end I/O on a request - * @req: the request being processed - * @uptodate: 1 for success, 0 for I/O error, < 0 for specific error - * @nr_bytes: number of bytes to complete - * - * Description: - * Ends I/O on a number of bytes attached to @req, and sets it up - * for the next range of segments (if any). Like end_that_request_first(), - * but deals with bytes instead of sectors. - * - * Return: - * 0 - we are done with this request, call end_that_request_last() - * 1 - still buffers pending for this request - **/ -int end_that_request_chunk(struct request *req, int uptodate, int nr_bytes) -{ - return __end_that_request_first(req, uptodate, nr_bytes); -} - -EXPORT_SYMBOL(end_that_request_chunk); - /* * splice the completion data to a local structure and hand off to * process_completion_queue() to complete the requests @@ -3670,7 +3641,7 @@ EXPORT_SYMBOL(blk_complete_request); /* * queue lock must be held */ -void end_that_request_last(struct request *req, int uptodate) +static void end_that_request_last(struct request *req, int uptodate) { struct gendisk *disk = req->rq_disk; int error; @@ -3705,8 +3676,6 @@ void end_that_request_last(struct request *req, int uptodate) __blk_put_request(req->q, req); } -EXPORT_SYMBOL(end_that_request_last); - static inline void __end_request(struct request *rq, int uptodate, unsigned int nr_bytes) { -- cgit v1.2.3 From 5450d3e1d68f10be087f0855d8bad5458b50ecbe Mon Sep 17 00:00:00 2001 From: Kiyoshi Ueda Date: Tue, 11 Dec 2007 17:53:03 -0500 Subject: blk_end_request: cleanup 'uptodate' related code (take 4) This patch converts 'uptodate' arguments of no longer exported interfaces, end_that_request_first/last, to 'error', and removes internal conversions for it in blk_end_request interfaces. Also, this patch removes no longer needed end_io_error(). Cc: Boaz Harrosh Signed-off-by: Kiyoshi Ueda Signed-off-by: Jun'ichi Nomura Signed-off-by: Jens Axboe --- block/ll_rw_blk.c | 56 +++++++++---------------------------------------------- 1 file changed, 9 insertions(+), 47 deletions(-) (limited to 'block') diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 4bd1803919ce..f5e091bc027d 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -3435,7 +3435,7 @@ static void blk_recalc_rq_sectors(struct request *rq, int nsect) /** * __end_that_request_first - end I/O on a request * @req: the request being processed - * @uptodate: 1 for success, 0 for I/O error, < 0 for specific error + * @error: 0 for success, < 0 for error * @nr_bytes: number of bytes to complete * * Description: @@ -3446,21 +3446,14 @@ static void blk_recalc_rq_sectors(struct request *rq, int nsect) * 0 - we are done with this request, call end_that_request_last() * 1 - still buffers pending for this request **/ -static int __end_that_request_first(struct request *req, int uptodate, +static int __end_that_request_first(struct request *req, int error, int nr_bytes) { - int total_bytes, bio_nbytes, error, next_idx = 0; + int total_bytes, bio_nbytes, next_idx = 0; struct bio *bio; blk_add_trace_rq(req->q, req, BLK_TA_COMPLETE); - /* - * extend uptodate bool to allow < 0 value to be direct io error - */ - error = 0; - if (end_io_error(uptodate)) - error = !uptodate ? -EIO : uptodate; - /* * for a REQ_BLOCK_PC request, we want to carry any eventual * sense key with us all the way through @@ -3468,7 +3461,7 @@ static int __end_that_request_first(struct request *req, int uptodate, if (!blk_pc_request(req)) req->errors = 0; - if (!uptodate) { + if (error) { if (blk_fs_request(req) && !(req->cmd_flags & REQ_QUIET)) printk("end_request: I/O error, dev %s, sector %llu\n", req->rq_disk ? req->rq_disk->disk_name : "?", @@ -3641,17 +3634,9 @@ EXPORT_SYMBOL(blk_complete_request); /* * queue lock must be held */ -static void end_that_request_last(struct request *req, int uptodate) +static void end_that_request_last(struct request *req, int error) { struct gendisk *disk = req->rq_disk; - int error; - - /* - * extend uptodate bool to allow < 0 value to be direct io error - */ - error = 0; - if (end_io_error(uptodate)) - error = !uptodate ? -EIO : uptodate; if (unlikely(laptop_mode) && blk_fs_request(req)) laptop_io_completion(); @@ -3776,14 +3761,6 @@ EXPORT_SYMBOL(end_request); static void complete_request(struct request *rq, int error) { - /* - * REMOVEME: This conversion is transitional and will be removed - * when old end_that_request_* are unexported. - */ - int uptodate = 1; - if (error) - uptodate = (error == -EIO) ? 0 : error; - if (blk_rq_tagged(rq)) blk_queue_end_tag(rq->q, rq); @@ -3793,7 +3770,7 @@ static void complete_request(struct request *rq, int error) if (blk_bidi_rq(rq) && !rq->end_io) __blk_put_request(rq->next_rq->q, rq->next_rq); - end_that_request_last(rq, uptodate); + end_that_request_last(rq, error); } /** @@ -3820,21 +3797,14 @@ static int blk_end_io(struct request *rq, int error, int nr_bytes, { struct request_queue *q = rq->q; unsigned long flags = 0UL; - /* - * REMOVEME: This conversion is transitional and will be removed - * when old end_that_request_* are unexported. - */ - int uptodate = 1; - if (error) - uptodate = (error == -EIO) ? 0 : error; if (blk_fs_request(rq) || blk_pc_request(rq)) { - if (__end_that_request_first(rq, uptodate, nr_bytes)) + if (__end_that_request_first(rq, error, nr_bytes)) return 1; /* Bidi request must be completed as a whole */ if (blk_bidi_rq(rq) && - __end_that_request_first(rq->next_rq, uptodate, bidi_bytes)) + __end_that_request_first(rq->next_rq, error, bidi_bytes)) return 1; } @@ -3886,16 +3856,8 @@ EXPORT_SYMBOL_GPL(blk_end_request); **/ int __blk_end_request(struct request *rq, int error, int nr_bytes) { - /* - * REMOVEME: This conversion is transitional and will be removed - * when old end_that_request_* are unexported. - */ - int uptodate = 1; - if (error) - uptodate = (error == -EIO) ? 0 : error; - if (blk_fs_request(rq) || blk_pc_request(rq)) { - if (__end_that_request_first(rq, uptodate, nr_bytes)) + if (__end_that_request_first(rq, error, nr_bytes)) return 1; } -- cgit v1.2.3 From b8286239ddaf2632cec65c01e68a403ac4c3d079 Mon Sep 17 00:00:00 2001 From: Kiyoshi Ueda Date: Tue, 11 Dec 2007 17:53:24 -0500 Subject: blk_end_request: cleanup of request completion (take 4) This patch merges complete_request() into end_that_request_last() for cleanup. complete_request() was introduced by earlier part of this patch-set, not to break the existing users of end_that_request_last(). Since all users are converted to blk_end_request interfaces and end_that_request_last() is no longer exported, the code can be merged to end_that_request_last(). Cc: Boaz Harrosh Signed-off-by: Kiyoshi Ueda Signed-off-by: Jun'ichi Nomura Signed-off-by: Jens Axboe --- block/ll_rw_blk.c | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) (limited to 'block') diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index f5e091bc027d..4bf95b602f36 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -3638,6 +3638,12 @@ static void end_that_request_last(struct request *req, int error) { struct gendisk *disk = req->rq_disk; + if (blk_rq_tagged(req)) + blk_queue_end_tag(req->q, req); + + if (blk_queued_rq(req)) + blkdev_dequeue_request(req); + if (unlikely(laptop_mode) && blk_fs_request(req)) laptop_io_completion(); @@ -3655,10 +3661,15 @@ static void end_that_request_last(struct request *req, int error) disk_round_stats(disk); disk->in_flight--; } + if (req->end_io) req->end_io(req, error); - else + else { + if (blk_bidi_rq(req)) + __blk_put_request(req->next_rq->q, req->next_rq); + __blk_put_request(req->q, req); + } } static inline void __end_request(struct request *rq, int uptodate, @@ -3759,20 +3770,6 @@ void end_request(struct request *req, int uptodate) } EXPORT_SYMBOL(end_request); -static void complete_request(struct request *rq, int error) -{ - if (blk_rq_tagged(rq)) - blk_queue_end_tag(rq->q, rq); - - if (blk_queued_rq(rq)) - blkdev_dequeue_request(rq); - - if (blk_bidi_rq(rq) && !rq->end_io) - __blk_put_request(rq->next_rq->q, rq->next_rq); - - end_that_request_last(rq, error); -} - /** * blk_end_io - Generic end_io function to complete a request. * @rq: the request being processed @@ -3815,7 +3812,7 @@ static int blk_end_io(struct request *rq, int error, int nr_bytes, add_disk_randomness(rq->rq_disk); spin_lock_irqsave(q->queue_lock, flags); - complete_request(rq, error); + end_that_request_last(rq, error); spin_unlock_irqrestore(q->queue_lock, flags); return 0; @@ -3863,7 +3860,7 @@ int __blk_end_request(struct request *rq, int error, int nr_bytes) add_disk_randomness(rq->rq_disk); - complete_request(rq, error); + end_that_request_last(rq, error); return 0; } -- cgit v1.2.3