===================================================================
@@ -569,35 +569,37 @@ static struct io_entity *lookup_next_io_
return entity;
}
-static void requeue_io_entity(struct io_entity *entity)
+static void requeue_io_entity(struct io_entity *entity, int add_front)
{
struct io_service_tree *st = entity->st;
struct io_entity *next_entity;
- next_entity = __lookup_next_io_entity(st);
+ if (add_front) {
+ next_entity = __lookup_next_io_entity(st);
- /*
- * This is to emulate cfq like functionality where preemption can
- * happen with-in same class, like sync queue preempting async queue
- * May be this is not a very good idea from fairness point of view
- * as preempting queue gains share. Keeping it for now.
- *
- * This feature is also used by cfq close cooperator functionlity
- * where cfq selects a queue out of order to run next based on
- * close cooperator.
- */
+ /*
+ * This is to emulate cfq like functionality where preemption
+ * can happen with-in same class, like sync queue preempting
+ * async queue.
+ *
+ * This feature is also used by cfq close cooperator
+ * functionlity where cfq selects a queue out of order to run
+ * next based on close cooperator.
+ */
- if (next_entity && next_entity != entity) {
- __dequeue_io_entity(st, entity);
- place_entity(st, entity, 1);
- __enqueue_io_entity(st, entity, 1);
+ if (next_entity && next_entity == entity)
+ return;
}
+
+ __dequeue_io_entity(st, entity);
+ place_entity(st, entity, add_front);
+ __enqueue_io_entity(st, entity, add_front);
}
-/* Requeue and ioq (already on the tree) to the front of service tree */
-static void requeue_ioq(struct io_queue *ioq)
+/* Requeue and ioq which is already on the tree */
+static void requeue_ioq(struct io_queue *ioq, int add_front)
{
- requeue_io_entity(&ioq->entity);
+ requeue_io_entity(&ioq->entity, add_front);
}
static void put_prev_io_entity(struct io_entity *entity)
@@ -2394,7 +2396,7 @@ io_queue *elv_set_active_ioq(struct requ
int coop = 0;
if (ioq) {
- requeue_ioq(ioq);
+ requeue_ioq(ioq, 1);
/*
* io scheduler selected the next queue for us. Pass this
* this info back to io scheudler. cfq currently uses it
@@ -2557,8 +2559,16 @@ done:
ioq->nr_sectors = 0;
put_prev_ioq(ioq);
+
if (!ioq->nr_queued)
elv_del_ioq_busy(q->elevator, ioq);
+ else if (!elv_ioq_sync(ioq)) {
+ /*
+ * Requeue async ioq so that these will be again placed at
+ * the end of service tree giving a chance to sync queues.
+ */
+ requeue_ioq(ioq, 0);
+ }
}
EXPORT_SYMBOL(elv_ioq_slice_expired);
@@ -2652,7 +2662,7 @@ static void elv_preempt_queue(struct req
* so we know that it will be selected next.
*/
- requeue_ioq(ioq);
+ requeue_ioq(ioq, 1);
ioq->slice_start = ioq->slice_end = 0;
elv_mark_ioq_slice_new(ioq);
}