diff options
| author | Jens Axboe <axboe@suse.de> | 2003-07-17 02:01:19 -0400 |
|---|---|---|
| committer | Jens Axboe <axboe@suse.de> | 2003-07-17 02:01:19 -0400 |
| commit | ae625582ba438fdd84a3faaf225bb9aa2f2d7bb1 (patch) | |
| tree | 76bd850f0da0a5471d1cc7e39d74e7e83eac103b | |
| parent | a75b0e155680dcc0804f26928b8cb9c5dee36145 (diff) | |
[PATCH] Consolidate SCSI requeueing and add blk elevator hook
This patch removes the scsi mid layer dependency on __elv_add_request
and introduces a new blk_requeue_request() function so the block
layer specificially knows a requeue is in progress.
It also adds an elevator hook for elevators like AS which need to
hook into the requeue for correct adjustment of internal counters.
| -rw-r--r-- | drivers/block/elevator.c | 13 | ||||
| -rw-r--r-- | drivers/block/ll_rw_blk.c | 18 | ||||
| -rw-r--r-- | drivers/scsi/scsi_lib.c | 20 | ||||
| -rw-r--r-- | include/linux/blkdev.h | 1 | ||||
| -rw-r--r-- | include/linux/elevator.h | 3 |
5 files changed, 37 insertions, 18 deletions
diff --git a/drivers/block/elevator.c b/drivers/block/elevator.c index 00b56d022b0e..272bcb34195b 100644 --- a/drivers/block/elevator.c +++ b/drivers/block/elevator.c @@ -214,6 +214,18 @@ void elv_merge_requests(request_queue_t *q, struct request *rq, e->elevator_merge_req_fn(q, rq, next); } +void elv_requeue_request(request_queue_t *q, struct request *rq) +{ + /* + * if iosched has an explicit requeue hook, then use that. otherwise + * just put the request at the front of the queue + */ + if (q->elevator.elevator_requeue_req_fn) + q->elevator.elevator_requeue_req_fn(q, rq); + else + __elv_add_request(q, rq, 0, 0); +} + void __elv_add_request(request_queue_t *q, struct request *rq, int at_end, int plug) { @@ -405,6 +417,7 @@ EXPORT_SYMBOL(elevator_noop); EXPORT_SYMBOL(elv_add_request); EXPORT_SYMBOL(__elv_add_request); +EXPORT_SYMBOL(elv_requeue_request); EXPORT_SYMBOL(elv_next_request); EXPORT_SYMBOL(elv_remove_request); EXPORT_SYMBOL(elv_queue_empty); diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 0f11567e5277..db399409909d 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -1355,6 +1355,23 @@ struct request *blk_get_request(request_queue_t *q, int rw, int gfp_mask) return rq; } +/** + * blk_requeue_request - put a request back on queue + * @q: request queue where request should be inserted + * @rq: request to be inserted + * + * Description: + * Drivers often keep queueing requests until the hardware cannot accept + * more, when that condition happens we need to put the request back + * on the queue. Must be called with queue lock held. + */ +void blk_requeue_request(request_queue_t *q, struct request *rq) +{ + if (blk_rq_tagged(rq)) + blk_queue_end_tag(q, rq); + + elv_requeue_request(q, rq); +} /** * blk_insert_request - insert a special request in to a request queue @@ -2339,6 +2356,7 @@ EXPORT_SYMBOL(blk_hw_contig_segment); EXPORT_SYMBOL(blk_get_request); EXPORT_SYMBOL(blk_put_request); EXPORT_SYMBOL(blk_insert_request); +EXPORT_SYMBOL(blk_requeue_request); EXPORT_SYMBOL(blk_queue_prep_rq); EXPORT_SYMBOL(blk_queue_merge_bvec); diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 4abb228037bd..b462b20c5b3d 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -444,22 +444,8 @@ static void scsi_run_queue(struct request_queue *q) */ static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd) { - unsigned long flags; - - spin_lock_irqsave(q->queue_lock, flags); - cmd->request->special = cmd; - if (blk_rq_tagged(cmd->request)) - blk_queue_end_tag(q, cmd->request); - - /* - * set REQ_SPECIAL - we have a command - * clear REQ_DONTPREP - we assume the sg table has been - * nuked so we need to set it up again. - */ - cmd->request->flags |= REQ_SPECIAL; cmd->request->flags &= ~REQ_DONTPREP; - __elv_add_request(q, cmd->request, 0, 0); - spin_unlock_irqrestore(q->queue_lock, flags); + blk_insert_request(q, cmd->request, 1, cmd); scsi_run_queue(q); } @@ -1213,9 +1199,7 @@ static void scsi_request_fn(struct request_queue *q) * later time. */ spin_lock_irq(q->queue_lock); - if (blk_rq_tagged(req)) - blk_queue_end_tag(q, req); - __elv_add_request(q, req, 0, 0); + blk_requeue_request(q, req); sdev->device_busy--; if(sdev->device_busy == 0) blk_plug_device(q); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 786ea3563752..b164fa5b40c6 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -405,6 +405,7 @@ extern void __blk_attempt_remerge(request_queue_t *, struct request *); extern struct request *blk_get_request(request_queue_t *, int, int); extern void blk_put_request(struct request *); extern void blk_insert_request(request_queue_t *, struct request *, int, void *); +extern void blk_requeue_request(request_queue_t *, struct request *); extern void blk_plug_device(request_queue_t *); extern int blk_remove_plug(request_queue_t *); extern void blk_recount_segments(request_queue_t *, struct bio *); diff --git a/include/linux/elevator.h b/include/linux/elevator.h index 522e51609ef3..e1c7bafa4fbc 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h @@ -13,6 +13,7 @@ typedef struct request *(elevator_next_req_fn) (request_queue_t *); typedef void (elevator_add_req_fn) (request_queue_t *, struct request *, struct list_head *); typedef int (elevator_queue_empty_fn) (request_queue_t *); typedef void (elevator_remove_req_fn) (request_queue_t *, struct request *); +typedef void (elevator_requeue_req_fn) (request_queue_t *, struct request *); typedef struct request *(elevator_request_list_fn) (request_queue_t *, struct request *); typedef struct list_head *(elevator_get_sort_head_fn) (request_queue_t *, struct request *); typedef int (elevator_set_req_fn) (request_queue_t *, struct request *, int); @@ -30,6 +31,7 @@ struct elevator_s elevator_next_req_fn *elevator_next_req_fn; elevator_add_req_fn *elevator_add_req_fn; elevator_remove_req_fn *elevator_remove_req_fn; + elevator_requeue_req_fn *elevator_requeue_req_fn; elevator_queue_empty_fn *elevator_queue_empty_fn; @@ -58,6 +60,7 @@ extern void elv_merge_requests(request_queue_t *, struct request *, struct request *); extern void elv_merged_request(request_queue_t *, struct request *); extern void elv_remove_request(request_queue_t *, struct request *); +extern void elv_requeue_request(request_queue_t *, struct request *); extern int elv_queue_empty(request_queue_t *); extern struct request *elv_next_request(struct request_queue *q); extern struct request *elv_former_request(request_queue_t *, struct request *); |
