Skip to content

Commit

Permalink
[BLOCK] cfq-iosched: cfq forced dispatching fix
Browse files Browse the repository at this point in the history
cfq forced dispatching might not return all requests on the queue.
This bug can hang elevator switchinig and corrupt request ordering
during flush sequence.

Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jens Axboe <axboe@suse.de>
  • Loading branch information
Tejun Heo authored and Jens Axboe committed Nov 12, 2005
1 parent 407df2a commit 1b5ed5e
Showing 1 changed file with 45 additions and 9 deletions.
54 changes: 45 additions & 9 deletions block/cfq-iosched.c
Original file line number Diff line number Diff line change
Expand Up @@ -999,7 +999,7 @@ cfq_prio_to_maxrq(struct cfq_data *cfqd, struct cfq_queue *cfqq)
/*
* get next queue for service
*/
static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd, int force)
static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd)
{
unsigned long now = jiffies;
struct cfq_queue *cfqq;
Expand All @@ -1023,7 +1023,7 @@ static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd, int force)
*/
if (!RB_EMPTY(&cfqq->sort_list))
goto keep_queue;
else if (!force && cfq_cfqq_class_sync(cfqq) &&
else if (cfq_cfqq_class_sync(cfqq) &&
time_before(now, cfqq->slice_end)) {
if (cfq_arm_slice_timer(cfqd, cfqq))
return NULL;
Expand Down Expand Up @@ -1091,6 +1091,42 @@ __cfq_dispatch_requests(struct cfq_data *cfqd, struct cfq_queue *cfqq,
return dispatched;
}

static int
cfq_forced_dispatch_cfqqs(struct list_head *list)
{
int dispatched = 0;
struct cfq_queue *cfqq, *next;
struct cfq_rq *crq;

list_for_each_entry_safe(cfqq, next, list, cfq_list) {
while ((crq = cfqq->next_crq)) {
cfq_dispatch_insert(cfqq->cfqd->queue, crq);
dispatched++;
}
BUG_ON(!list_empty(&cfqq->fifo));
}
return dispatched;
}

static int
cfq_forced_dispatch(struct cfq_data *cfqd)
{
int i, dispatched = 0;

for (i = 0; i < CFQ_PRIO_LISTS; i++)
dispatched += cfq_forced_dispatch_cfqqs(&cfqd->rr_list[i]);

dispatched += cfq_forced_dispatch_cfqqs(&cfqd->busy_rr);
dispatched += cfq_forced_dispatch_cfqqs(&cfqd->cur_rr);
dispatched += cfq_forced_dispatch_cfqqs(&cfqd->idle_rr);

cfq_slice_expired(cfqd, 0);

BUG_ON(cfqd->busy_queues);

return dispatched;
}

static int
cfq_dispatch_requests(request_queue_t *q, int force)
{
Expand All @@ -1100,7 +1136,10 @@ cfq_dispatch_requests(request_queue_t *q, int force)
if (!cfqd->busy_queues)
return 0;

cfqq = cfq_select_queue(cfqd, force);
if (unlikely(force))
return cfq_forced_dispatch(cfqd);

cfqq = cfq_select_queue(cfqd);
if (cfqq) {
int max_dispatch;

Expand All @@ -1115,12 +1154,9 @@ cfq_dispatch_requests(request_queue_t *q, int force)
cfq_clear_cfqq_wait_request(cfqq);
del_timer(&cfqd->idle_slice_timer);

if (!force) {
max_dispatch = cfqd->cfq_quantum;
if (cfq_class_idle(cfqq))
max_dispatch = 1;
} else
max_dispatch = INT_MAX;
max_dispatch = cfqd->cfq_quantum;
if (cfq_class_idle(cfqq))
max_dispatch = 1;

return __cfq_dispatch_requests(cfqd, cfqq, max_dispatch);
}
Expand Down

0 comments on commit 1b5ed5e

Please sign in to comment.