Commit 1cfcda6a authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] elevator insertion fixes

From: Nick Piggin <piggin@cyberone.com.au>

This fixes a bug in deadline and AS that causes insert_here to be ignored on
blk_fs_requests. This has been causing problems with SCSI requeueing code.
It makes elevator insertion more correct as advertised wrt insert_here and
REQ_SOFTBARRIER.

It also fixes a buglet in the as_requeue code where the request wasn't being
put into the front of the list (in rare cases).
parent c12f96f2
...@@ -910,12 +910,7 @@ static void as_completed_request(request_queue_t *q, struct request *rq) ...@@ -910,12 +910,7 @@ static void as_completed_request(request_queue_t *q, struct request *rq)
struct as_rq *arq = RQ_DATA(rq); struct as_rq *arq = RQ_DATA(rq);
struct as_io_context *aic; struct as_io_context *aic;
if (unlikely(!blk_fs_request(rq))) if (unlikely(arq->state != AS_RQ_DISPATCHED))
return;
WARN_ON(blk_fs_request(rq) && arq->state == AS_RQ_NEW);
if (arq->state != AS_RQ_DISPATCHED)
return; return;
if (ad->changed_batch && ad->nr_dispatched == 1) { if (ad->changed_batch && ad->nr_dispatched == 1) {
...@@ -1035,7 +1030,7 @@ static void as_remove_request(request_queue_t *q, struct request *rq) ...@@ -1035,7 +1030,7 @@ static void as_remove_request(request_queue_t *q, struct request *rq)
{ {
struct as_rq *arq = RQ_DATA(rq); struct as_rq *arq = RQ_DATA(rq);
if (unlikely(!blk_fs_request(rq))) if (unlikely(arq->state == AS_RQ_NEW))
return; return;
if (!arq) { if (!arq) {
...@@ -1341,9 +1336,9 @@ static void as_requeue_request(request_queue_t *q, struct request *rq) ...@@ -1341,9 +1336,9 @@ static void as_requeue_request(request_queue_t *q, struct request *rq)
atomic_inc(&arq->io_context->aic->nr_dispatched); atomic_inc(&arq->io_context->aic->nr_dispatched);
} else } else
WARN_ON(blk_fs_request(rq) WARN_ON(blk_fs_request(rq)
&& (!(rq->flags & REQ_HARDBARRIER)) ); && (!(rq->flags & (REQ_HARDBARRIER|REQ_SOFTBARRIER))) );
list_add_tail(&rq->queuelist, ad->dispatch); list_add(&rq->queuelist, ad->dispatch);
/* Stop anticipating - let this request get through */ /* Stop anticipating - let this request get through */
as_antic_stop(ad); as_antic_stop(ad);
...@@ -1358,9 +1353,10 @@ as_insert_request(request_queue_t *q, struct request *rq, ...@@ -1358,9 +1353,10 @@ as_insert_request(request_queue_t *q, struct request *rq,
struct as_data *ad = q->elevator.elevator_data; struct as_data *ad = q->elevator.elevator_data;
struct as_rq *arq = RQ_DATA(rq); struct as_rq *arq = RQ_DATA(rq);
if (unlikely(rq->flags & REQ_HARDBARRIER)) { if (unlikely(rq->flags & (REQ_HARDBARRIER|REQ_SOFTBARRIER))) {
q->last_merge = NULL; q->last_merge = NULL;
if (insert_here != ad->dispatch) {
while (ad->next_arq[REQ_SYNC]) while (ad->next_arq[REQ_SYNC])
as_move_to_dispatch(ad, ad->next_arq[REQ_SYNC]); as_move_to_dispatch(ad, ad->next_arq[REQ_SYNC]);
...@@ -1368,16 +1364,20 @@ as_insert_request(request_queue_t *q, struct request *rq, ...@@ -1368,16 +1364,20 @@ as_insert_request(request_queue_t *q, struct request *rq,
as_move_to_dispatch(ad, ad->next_arq[REQ_ASYNC]); as_move_to_dispatch(ad, ad->next_arq[REQ_ASYNC]);
} }
if (unlikely(!blk_fs_request(rq))) {
if (!insert_here) if (!insert_here)
insert_here = ad->dispatch->prev; insert_here = ad->dispatch->prev;
}
if (unlikely(!blk_fs_request(rq))) {
if (!insert_here)
insert_here = ad->dispatch;
}
if (insert_here) {
list_add(&rq->queuelist, insert_here); list_add(&rq->queuelist, insert_here);
/* Stop anticipating - let this request get through */ /* Stop anticipating - let this request get through */
if (!list_empty(ad->dispatch) if (list_empty(ad->dispatch))
&& (ad->antic_status == ANTIC_WAIT_REQ
|| ad->antic_status == ANTIC_WAIT_NEXT))
as_antic_stop(ad); as_antic_stop(ad);
return; return;
......
...@@ -627,21 +627,25 @@ deadline_insert_request(request_queue_t *q, struct request *rq, ...@@ -627,21 +627,25 @@ deadline_insert_request(request_queue_t *q, struct request *rq,
struct deadline_data *dd = q->elevator.elevator_data; struct deadline_data *dd = q->elevator.elevator_data;
struct deadline_rq *drq = RQ_DATA(rq); struct deadline_rq *drq = RQ_DATA(rq);
if (unlikely(rq->flags & REQ_HARDBARRIER)) { if (unlikely(rq->flags & (REQ_HARDBARRIER|REQ_SOFTBARRIER))) {
DL_INVALIDATE_HASH(dd); DL_INVALIDATE_HASH(dd);
q->last_merge = NULL; q->last_merge = NULL;
if (insert_here != dd->dispatch) {
while (deadline_dispatch_requests(dd)) while (deadline_dispatch_requests(dd))
; ;
}
list_add_tail(&rq->queuelist, dd->dispatch); if (!insert_here)
return; insert_here = dd->dispatch->prev;
} }
if (unlikely(!blk_fs_request(rq))) { if (unlikely(!blk_fs_request(rq))) {
if (!insert_here) if (!insert_here)
insert_here = dd->dispatch->prev; insert_here = dd->dispatch;
}
if (insert_here) {
list_add(&rq->queuelist, insert_here); list_add(&rq->queuelist, insert_here);
return; return;
} }
......
...@@ -162,10 +162,10 @@ void elv_requeue_request(request_queue_t *q, struct request *rq) ...@@ -162,10 +162,10 @@ void elv_requeue_request(request_queue_t *q, struct request *rq)
void __elv_add_request(request_queue_t *q, struct request *rq, int at_end, void __elv_add_request(request_queue_t *q, struct request *rq, int at_end,
int plug) int plug)
{ {
struct list_head *insert = &q->queue_head; struct list_head *insert = NULL;
if (at_end) if (!at_end)
insert = insert->prev; insert = &q->queue_head;
if (plug) if (plug)
blk_plug_device(q); blk_plug_device(q);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment