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

Commit 99f9628a authored by Jens Axboe's avatar Jens Axboe Committed by Jens Axboe
Browse files

[PATCH] cfq-iosched: use last service point as the fairness criteria



Right now we use slice_start, which gives async queues an unfair
advantage. Chance that to service_last, and base the resorter
on that.

Signed-off-by: default avatarJens Axboe <jens.axboe@oracle.com>
parent b0b8d749
Loading
Loading
Loading
Loading
+34 −14
Original line number Original line Diff line number Diff line
@@ -146,9 +146,9 @@ struct cfq_queue {
	/* fifo list of requests in sort_list */
	/* fifo list of requests in sort_list */
	struct list_head fifo;
	struct list_head fifo;


	unsigned long slice_start;
	unsigned long slice_end;
	unsigned long slice_end;
	unsigned long slice_left;
	unsigned long slice_left;
	unsigned long service_last;


	/* number of requests that are on the dispatch list */
	/* number of requests that are on the dispatch list */
	int on_dispatch[2];
	int on_dispatch[2];
@@ -355,7 +355,8 @@ cfq_find_next_rq(struct cfq_data *cfqd, struct cfq_queue *cfqq,
static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted)
static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted)
{
{
	struct cfq_data *cfqd = cfqq->cfqd;
	struct cfq_data *cfqd = cfqq->cfqd;
	struct list_head *list;
	struct list_head *list, *n;
	struct cfq_queue *__cfqq;


	/*
	/*
	 * Resorting requires the cfqq to be on the RR list already.
	 * Resorting requires the cfqq to be on the RR list already.
@@ -383,15 +384,13 @@ static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted)
			list = &cfqd->rr_list[cfqq->ioprio];
			list = &cfqd->rr_list[cfqq->ioprio];
	}
	}


	if (preempted || cfq_cfqq_queue_new(cfqq)) {
		/*
		/*
	 * If this queue was preempted or is new (never been serviced), let
		 * If this queue was preempted or is new (never been serviced),
	 * it be added first for fairness but beind other new queues.
		 * let it be added first for fairness but beind other new
	 * Otherwise, just add to the back  of the list.
		 * queues.
		 */
		 */
	if (preempted || cfq_cfqq_queue_new(cfqq)) {
		n = list;
		struct list_head *n = list;
		struct cfq_queue *__cfqq;

		while (n->next != list) {
		while (n->next != list) {
			__cfqq = list_entry_cfqq(n->next);
			__cfqq = list_entry_cfqq(n->next);
			if (!cfq_cfqq_queue_new(__cfqq))
			if (!cfq_cfqq_queue_new(__cfqq))
@@ -399,11 +398,32 @@ static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted)


			n = n->next;
			n = n->next;
		}
		}
		list_add_tail(&cfqq->cfq_list, n);
	} else if (!cfq_cfqq_class_sync(cfqq)) {
		/*
		 * async queue always goes to the end. this wont be overly
		 * unfair to writes, as the sort of the sync queue wont be
		 * allowed to pass the async queue again.
		 */
		list_add_tail(&cfqq->cfq_list, list);
	} else {
		/*
		 * sort by last service, but don't cross a new or async
		 * queue. we don't cross a new queue because it hasn't been
		 * service before, and we don't cross an async queue because
		 * it gets added to the end on expire.
		 */
		n = list;
		while ((n = n->prev) != list) {
			struct cfq_queue *__cfqq = list_entry_cfqq(n);


		list = n;
			if (!cfq_cfqq_class_sync(cfqq) || !__cfqq->service_last)
				break;
			if (time_before(__cfqq->service_last, cfqq->service_last))
				break;
		}
		list_add(&cfqq->cfq_list, n);
	}
	}

	list_add_tail(&cfqq->cfq_list, list);
}
}


/*
/*
@@ -608,7 +628,6 @@ __cfq_set_active_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq)
		 */
		 */
		del_timer(&cfqd->idle_class_timer);
		del_timer(&cfqd->idle_class_timer);


		cfqq->slice_start = jiffies;
		cfqq->slice_end = 0;
		cfqq->slice_end = 0;
		cfqq->slice_left = 0;
		cfqq->slice_left = 0;
		cfq_clear_cfqq_must_alloc_slice(cfqq);
		cfq_clear_cfqq_must_alloc_slice(cfqq);
@@ -1688,6 +1707,7 @@ static void cfq_completed_request(request_queue_t *q, struct request *rq)
	WARN_ON(!cfqq->on_dispatch[sync]);
	WARN_ON(!cfqq->on_dispatch[sync]);
	cfqd->rq_in_driver--;
	cfqd->rq_in_driver--;
	cfqq->on_dispatch[sync]--;
	cfqq->on_dispatch[sync]--;
	cfqq->service_last = now;


	if (!cfq_class_idle(cfqq))
	if (!cfq_class_idle(cfqq))
		cfqd->last_end_request = now;
		cfqd->last_end_request = now;