|
@@ -999,7 +999,7 @@ cfq_prio_to_maxrq(struct cfq_data *cfqd, struct cfq_queue *cfqq)
|
|
/*
|
|
/*
|
|
* get next queue for service
|
|
* 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;
|
|
unsigned long now = jiffies;
|
|
struct cfq_queue *cfqq;
|
|
struct cfq_queue *cfqq;
|
|
@@ -1023,7 +1023,7 @@ static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd, int force)
|
|
*/
|
|
*/
|
|
if (!RB_EMPTY(&cfqq->sort_list))
|
|
if (!RB_EMPTY(&cfqq->sort_list))
|
|
goto keep_queue;
|
|
goto keep_queue;
|
|
- else if (!force && cfq_cfqq_class_sync(cfqq) &&
|
|
|
|
|
|
+ else if (cfq_cfqq_class_sync(cfqq) &&
|
|
time_before(now, cfqq->slice_end)) {
|
|
time_before(now, cfqq->slice_end)) {
|
|
if (cfq_arm_slice_timer(cfqd, cfqq))
|
|
if (cfq_arm_slice_timer(cfqd, cfqq))
|
|
return NULL;
|
|
return NULL;
|
|
@@ -1091,6 +1091,42 @@ __cfq_dispatch_requests(struct cfq_data *cfqd, struct cfq_queue *cfqq,
|
|
return dispatched;
|
|
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
|
|
static int
|
|
cfq_dispatch_requests(request_queue_t *q, int force)
|
|
cfq_dispatch_requests(request_queue_t *q, int force)
|
|
{
|
|
{
|
|
@@ -1100,7 +1136,10 @@ cfq_dispatch_requests(request_queue_t *q, int force)
|
|
if (!cfqd->busy_queues)
|
|
if (!cfqd->busy_queues)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
- cfqq = cfq_select_queue(cfqd, force);
|
|
|
|
|
|
+ if (unlikely(force))
|
|
|
|
+ return cfq_forced_dispatch(cfqd);
|
|
|
|
+
|
|
|
|
+ cfqq = cfq_select_queue(cfqd);
|
|
if (cfqq) {
|
|
if (cfqq) {
|
|
int max_dispatch;
|
|
int max_dispatch;
|
|
|
|
|
|
@@ -1115,12 +1154,9 @@ cfq_dispatch_requests(request_queue_t *q, int force)
|
|
cfq_clear_cfqq_wait_request(cfqq);
|
|
cfq_clear_cfqq_wait_request(cfqq);
|
|
del_timer(&cfqd->idle_slice_timer);
|
|
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);
|
|
return __cfq_dispatch_requests(cfqd, cfqq, max_dispatch);
|
|
}
|
|
}
|