From: Jens Axboe In several places cfq checks cfqd->busy_queues to see if we have pending work, but that doesn't detect requests going directly to the dispatch list since they don't end up in a queue and thus get ->busy_queues incremented. Abstract the check into cfq_pending_work() and use that throughout the code. Signed-off-by: Jens Axboe Signed-off-by: Andrew Morton --- 25-akpm/drivers/block/cfq-iosched.c | 11 ++++++++--- 1 files changed, 8 insertions(+), 3 deletions(-) diff -puN drivers/block/cfq-iosched.c~cfq-ioschedc-fix-soft-hang-with-non-fs-requests drivers/block/cfq-iosched.c --- 25/drivers/block/cfq-iosched.c~cfq-ioschedc-fix-soft-hang-with-non-fs-requests 2005-03-17 01:21:16.000000000 -0800 +++ 25-akpm/drivers/block/cfq-iosched.c 2005-03-17 01:21:16.000000000 -0800 @@ -1724,11 +1724,16 @@ cfq_insert_request(request_queue_t *q, s } } +static inline int cfq_pending_requests(struct cfq_data *cfqd) +{ + return !list_empty(&cfqd->queue->queue_head) || cfqd->busy_queues; +} + static int cfq_queue_empty(request_queue_t *q) { struct cfq_data *cfqd = q->elevator->elevator_data; - return list_empty(&q->queue_head) && !cfqd->busy_queues; + return !cfq_pending_requests(cfqd); } static void cfq_completed_request(request_queue_t *q, struct request *rq) @@ -2049,7 +2054,7 @@ static void cfq_idle_slice_timer(unsigne * only expire and reinvoke request handler, if there are * other queues with pending requests */ - if (!cfqd->busy_queues) { + if (!cfq_pending_requests(cfqd)) { cfqd->idle_slice_timer.expires = min(now + cfqd->cfq_slice_idle, cfqq->slice_end); add_timer(&cfqd->idle_slice_timer); goto out_cont; @@ -2066,7 +2071,7 @@ static void cfq_idle_slice_timer(unsigne expire: cfq_slice_expired(cfqd, 0); out_kick: - if (cfqd->busy_queues) + if (cfq_pending_requests(cfqd)) kblockd_schedule_work(&cfqd->unplug_work); out_cont: spin_unlock_irqrestore(cfqd->queue->queue_lock, flags); _