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 --- include/linux/blkdev.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include/linux/blkdev.h') 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 { #define blk_fua_rq(rq) ((rq)->cmd_flags & REQ_FUA) #define blk_bidi_rq(rq) ((rq)->next_rq != NULL) #define blk_empty_barrier(rq) (blk_barrier_rq(rq) && blk_fs_request(rq) && !(rq)->hard_nr_sectors) +/* rq->queuelist of dequeued request must be list_empty() */ +#define blk_queued_rq(rq) (!list_empty(&(rq)->queuelist)) #define list_entry_rq(ptr) list_entry((ptr), struct request, queuelist) @@ -724,6 +726,8 @@ static inline void blk_run_address_space(struct address_space *mapping) * for parts of the original function. This prevents * code duplication in drivers. */ +extern int blk_end_request(struct request *rq, int error, int nr_bytes); +extern int __blk_end_request(struct request *rq, int error, int nr_bytes); extern int end_that_request_first(struct request *, int, int); extern int end_that_request_chunk(struct request *, int, int); extern void end_that_request_last(struct request *, int); -- cgit v1.2.2 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 --- include/linux/blkdev.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'include/linux/blkdev.h') diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 3b212f02db8d..aa2341df7932 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -736,6 +736,14 @@ extern void end_queued_request(struct request *, int); extern void end_dequeued_request(struct request *, int); extern void blk_complete_request(struct request *); +/* + * blk_end_request() takes bytes instead of sectors as a complete size. + * blk_rq_bytes() returns bytes left to complete in the entire request. + * blk_rq_cur_bytes() returns bytes left to complete in the current segment. + */ +extern unsigned int blk_rq_bytes(struct request *rq); +extern unsigned int blk_rq_cur_bytes(struct request *rq); + /* * end_that_request_first/chunk() takes an uptodate argument. we account * any value <= as an io error. 0 means -EIO for compatability reasons, -- cgit v1.2.2 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 --- include/linux/blkdev.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux/blkdev.h') diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index aa2341df7932..63fe7542b3fa 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -734,6 +734,8 @@ extern void end_that_request_last(struct request *, int); extern void end_request(struct request *, int); extern void end_queued_request(struct request *, int); extern void end_dequeued_request(struct request *, int); +extern int blk_end_request_callback(struct request *rq, int error, int nr_bytes, + int (drv_callback)(struct request *)); extern void blk_complete_request(struct request *); /* -- cgit v1.2.2 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 --- include/linux/blkdev.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux/blkdev.h') diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 63fe7542b3fa..029b7097f9e5 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -728,6 +728,8 @@ static inline void blk_run_address_space(struct address_space *mapping) */ extern int blk_end_request(struct request *rq, int error, int nr_bytes); extern int __blk_end_request(struct request *rq, int error, int nr_bytes); +extern int blk_end_bidi_request(struct request *rq, int error, int nr_bytes, + int bidi_bytes); extern int end_that_request_first(struct request *, int, int); extern int end_that_request_chunk(struct request *, int, int); extern void end_that_request_last(struct request *, int); -- cgit v1.2.2 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 --- include/linux/blkdev.h | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'include/linux/blkdev.h') diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 029b7097f9e5..0c39ac75bed4 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -718,21 +718,18 @@ static inline void blk_run_address_space(struct address_space *mapping) } /* - * end_request() and friends. Must be called with the request queue spinlock - * acquired. All functions called within end_request() _must_be_ atomic. + * blk_end_request() and friends. + * __blk_end_request() and end_request() must be called with + * the request queue spinlock acquired. * * Several drivers define their own end_request and call - * end_that_request_first() and end_that_request_last() - * for parts of the original function. This prevents - * code duplication in drivers. + * blk_end_request() for parts of the original function. + * This prevents code duplication in drivers. */ extern int blk_end_request(struct request *rq, int error, int nr_bytes); extern int __blk_end_request(struct request *rq, int error, int nr_bytes); extern int blk_end_bidi_request(struct request *rq, int error, int nr_bytes, int bidi_bytes); -extern int end_that_request_first(struct request *, int, int); -extern int end_that_request_chunk(struct request *, int, int); -extern void end_that_request_last(struct request *, int); extern void end_request(struct request *, int); extern void end_queued_request(struct request *, int); extern void end_dequeued_request(struct request *, int); -- cgit v1.2.2 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 --- include/linux/blkdev.h | 8 -------- 1 file changed, 8 deletions(-) (limited to 'include/linux/blkdev.h') diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 0c39ac75bed4..0ea82d222046 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -745,14 +745,6 @@ extern void blk_complete_request(struct request *); extern unsigned int blk_rq_bytes(struct request *rq); extern unsigned int blk_rq_cur_bytes(struct request *rq); -/* - * end_that_request_first/chunk() takes an uptodate argument. we account - * any value <= as an io error. 0 means -EIO for compatability reasons, - * any other < 0 value is the direct error type. An uptodate value of - * 1 indicates successful io completion - */ -#define end_io_error(uptodate) (unlikely((uptodate) <= 0)) - static inline void blkdev_dequeue_request(struct request *req) { elv_dequeue_request(req->q, req); -- cgit v1.2.2