Skip to content

Commit 53b0374

Browse files
Jens AxboeJens Axboe
authored andcommitted
[PATCH] cfq-iosched: Kill O(N) runtime of cfq_resort_rr_list()
Currently it scales with number of processes in that priority group, which is potentially not very nice as it's called quite often. Basically we always need to do tail inserts, except for the case of a new process. So just mark/detect a queue as such. Signed-off-by: Jens Axboe <[email protected]>
1 parent b5deef9 commit 53b0374

File tree

1 file changed

+22
-31
lines changed

1 file changed

+22
-31
lines changed

block/cfq-iosched.c

Lines changed: 22 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,6 @@ struct cfq_queue {
152152
unsigned long slice_start;
153153
unsigned long slice_end;
154154
unsigned long slice_left;
155-
unsigned long service_last;
156155

157156
/* number of requests that are on the dispatch list */
158157
int on_dispatch[2];
@@ -174,6 +173,7 @@ enum cfqq_state_flags {
174173
CFQ_CFQQ_FLAG_fifo_expire,
175174
CFQ_CFQQ_FLAG_idle_window,
176175
CFQ_CFQQ_FLAG_prio_changed,
176+
CFQ_CFQQ_FLAG_queue_new,
177177
};
178178

179179
#define CFQ_CFQQ_FNS(name) \
@@ -198,6 +198,7 @@ CFQ_CFQQ_FNS(must_dispatch);
198198
CFQ_CFQQ_FNS(fifo_expire);
199199
CFQ_CFQQ_FNS(idle_window);
200200
CFQ_CFQQ_FNS(prio_changed);
201+
CFQ_CFQQ_FNS(queue_new);
201202
#undef CFQ_CFQQ_FNS
202203

203204
static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned int, unsigned short);
@@ -350,7 +351,7 @@ cfq_find_next_rq(struct cfq_data *cfqd, struct cfq_queue *cfqq,
350351
static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted)
351352
{
352353
struct cfq_data *cfqd = cfqq->cfqd;
353-
struct list_head *list, *entry;
354+
struct list_head *list;
354355

355356
BUG_ON(!cfq_cfqq_on_rr(cfqq));
356357

@@ -375,31 +376,26 @@ static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted)
375376
}
376377

377378
/*
378-
* if queue was preempted, just add to front to be fair. busy_rr
379-
* isn't sorted, but insert at the back for fairness.
379+
* If this queue was preempted or is new (never been serviced), let
380+
* it be added first for fairness but beind other new queues.
381+
* Otherwise, just add to the back of the list.
380382
*/
381-
if (preempted || list == &cfqd->busy_rr) {
382-
if (preempted)
383-
list = list->prev;
383+
if (preempted || cfq_cfqq_queue_new(cfqq)) {
384+
struct list_head *n = list;
385+
struct cfq_queue *__cfqq;
384386

385-
list_add_tail(&cfqq->cfq_list, list);
386-
return;
387-
}
387+
while (n->next != list) {
388+
__cfqq = list_entry_cfqq(n->next);
389+
if (!cfq_cfqq_queue_new(__cfqq))
390+
break;
388391

389-
/*
390-
* sort by when queue was last serviced
391-
*/
392-
entry = list;
393-
while ((entry = entry->prev) != list) {
394-
struct cfq_queue *__cfqq = list_entry_cfqq(entry);
392+
n = n->next;
393+
}
395394

396-
if (!__cfqq->service_last)
397-
break;
398-
if (time_before(__cfqq->service_last, cfqq->service_last))
399-
break;
395+
list = n;
400396
}
401397

402-
list_add(&cfqq->cfq_list, entry);
398+
list_add_tail(&cfqq->cfq_list, list);
403399
}
404400

405401
/*
@@ -591,13 +587,12 @@ __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq,
591587
if (cfq_cfqq_wait_request(cfqq))
592588
del_timer(&cfqd->idle_slice_timer);
593589

594-
if (!preempted && !cfq_cfqq_dispatched(cfqq)) {
595-
cfqq->service_last = now;
590+
if (!preempted && !cfq_cfqq_dispatched(cfqq))
596591
cfq_schedule_dispatch(cfqd);
597-
}
598592

599593
cfq_clear_cfqq_must_dispatch(cfqq);
600594
cfq_clear_cfqq_wait_request(cfqq);
595+
cfq_clear_cfqq_queue_new(cfqq);
601596

602597
/*
603598
* store what was left of this slice, if the queue idled out
@@ -1297,13 +1292,13 @@ cfq_get_queue(struct cfq_data *cfqd, unsigned int key, struct task_struct *tsk,
12971292
hlist_add_head(&cfqq->cfq_hash, &cfqd->cfq_hash[hashval]);
12981293
atomic_set(&cfqq->ref, 0);
12991294
cfqq->cfqd = cfqd;
1300-
cfqq->service_last = 0;
13011295
/*
13021296
* set ->slice_left to allow preemption for a new process
13031297
*/
13041298
cfqq->slice_left = 2 * cfqd->cfq_slice_idle;
13051299
cfq_mark_cfqq_idle_window(cfqq);
13061300
cfq_mark_cfqq_prio_changed(cfqq);
1301+
cfq_mark_cfqq_queue_new(cfqq);
13071302
cfq_init_prio_data(cfqq);
13081303
}
13091304

@@ -1672,12 +1667,8 @@ static void cfq_completed_request(request_queue_t *q, struct request *rq)
16721667
if (!cfq_class_idle(cfqq))
16731668
cfqd->last_end_request = now;
16741669

1675-
if (!cfq_cfqq_dispatched(cfqq)) {
1676-
if (cfq_cfqq_on_rr(cfqq)) {
1677-
cfqq->service_last = now;
1678-
cfq_resort_rr_list(cfqq, 0);
1679-
}
1680-
}
1670+
if (!cfq_cfqq_dispatched(cfqq) && cfq_cfqq_on_rr(cfqq))
1671+
cfq_resort_rr_list(cfqq, 0);
16811672

16821673
if (sync)
16831674
RQ_CIC(rq)->last_end_request = now;

0 commit comments

Comments
 (0)