summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Axboe <axboe@suse.de>2003-07-17 02:01:19 -0400
committerJens Axboe <axboe@suse.de>2003-07-17 02:01:19 -0400
commitae625582ba438fdd84a3faaf225bb9aa2f2d7bb1 (patch)
tree76bd850f0da0a5471d1cc7e39d74e7e83eac103b
parenta75b0e155680dcc0804f26928b8cb9c5dee36145 (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.c13
-rw-r--r--drivers/block/ll_rw_blk.c18
-rw-r--r--drivers/scsi/scsi_lib.c20
-rw-r--r--include/linux/blkdev.h1
-rw-r--r--include/linux/elevator.h3
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 *);