Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a9938006 authored by Jens Axboe's avatar Jens Axboe Committed by Linus Torvalds
Browse files

cfq-iosched: fix sequential write regression



We have a 10-15% performance regression for sequential writes on TCQ/NCQ
enabled drives in 2.6.21-rcX after the CFQ update went in.  It has been
reported by Valerie Clement <valerie.clement@bull.net> and the Intel
testing folks.  The regression is because of CFQ's now more aggressive
queue control, limiting the depth available to the device.

This patches fixes that regression by allowing a greater depth when only
one queue is busy.  It has been tested to not impact sync-vs-async
workloads too much - we still do a lot better than 2.6.20.

Signed-off-by: default avatarJens Axboe <jens.axboe@oracle.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 46fcc86d
Loading
Loading
Loading
Loading
+19 −15
Original line number Diff line number Diff line
@@ -986,9 +986,9 @@ __cfq_dispatch_requests(struct cfq_data *cfqd, struct cfq_queue *cfqq,
	 * expire an async queue immediately if it has used up its slice. idle
	 * queue always expire after 1 dispatch round.
	 */
	if ((!cfq_cfqq_sync(cfqq) &&
	if (cfqd->busy_queues > 1 && ((!cfq_cfqq_sync(cfqq) &&
	    cfqd->dispatch_slice >= cfq_prio_to_maxrq(cfqd, cfqq)) ||
	    cfq_class_idle(cfqq)) {
	    cfq_class_idle(cfqq))) {
		cfqq->slice_end = jiffies + 1;
		cfq_slice_expired(cfqd, 0, 0);
	}
@@ -1051,6 +1051,7 @@ cfq_dispatch_requests(request_queue_t *q, int force)
	while ((cfqq = cfq_select_queue(cfqd)) != NULL) {
		int max_dispatch;

		if (cfqd->busy_queues > 1) {
			/*
			 * Don't repeat dispatch from the previous queue.
			 */
@@ -1064,6 +1065,7 @@ cfq_dispatch_requests(request_queue_t *q, int force)
			 */
			if (cfqd->rq_in_driver && cfq_cfqq_idle_window(cfqq))
				break;
		}

		cfq_clear_cfqq_must_dispatch(cfqq);
		cfq_clear_cfqq_wait_request(cfqq);
@@ -1370,7 +1372,9 @@ cfq_get_queue(struct cfq_data *cfqd, unsigned int key, struct task_struct *tsk,
		atomic_set(&cfqq->ref, 0);
		cfqq->cfqd = cfqd;

		if (key != CFQ_KEY_ASYNC)
			cfq_mark_cfqq_idle_window(cfqq);

		cfq_mark_cfqq_prio_changed(cfqq);
		cfq_mark_cfqq_queue_new(cfqq);
		cfq_init_prio_data(cfqq);