Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 172989
b: refs/heads/master
c: f04a642
h: refs/heads/master
i:
  172987: 75eb854
v: v3
  • Loading branch information
Vivek Goyal authored and Jens Axboe committed Dec 3, 2009
1 parent ab7f0ec commit ea94a44
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 22 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 615f0259e6940293359a189f4881bb28c2fea40b
refs/heads/master: f04a64246344ad50e4b4b4186174a0912d07f30b
70 changes: 49 additions & 21 deletions trunk/block/cfq-iosched.c
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ static int cfq_queue_empty(struct request_queue *q)
{
struct cfq_data *cfqd = q->elevator->elevator_data;

return !cfqd->busy_queues;
return !cfqd->rq_queued;
}

/*
Expand Down Expand Up @@ -842,16 +842,24 @@ static void cfq_del_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq)
static void cfq_del_rq_rb(struct request *rq)
{
struct cfq_queue *cfqq = RQ_CFQQ(rq);
struct cfq_data *cfqd = cfqq->cfqd;
const int sync = rq_is_sync(rq);

BUG_ON(!cfqq->queued[sync]);
cfqq->queued[sync]--;

elv_rb_del(&cfqq->sort_list, rq);

if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY_ROOT(&cfqq->sort_list))
cfq_del_cfqq_rr(cfqd, cfqq);
if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY_ROOT(&cfqq->sort_list)) {
/*
* Queue will be deleted from service tree when we actually
* expire it later. Right now just remove it from prio tree
* as it is empty.
*/
if (cfqq->p_root) {
rb_erase(&cfqq->p_node, cfqq->p_root);
cfqq->p_root = NULL;
}
}
}

static void cfq_add_rq_rb(struct request *rq)
Expand Down Expand Up @@ -1065,6 +1073,9 @@ __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq,
cfq_log_cfqq(cfqd, cfqq, "resid=%ld", cfqq->slice_resid);
}

if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY_ROOT(&cfqq->sort_list))
cfq_del_cfqq_rr(cfqd, cfqq);

cfq_resort_rr_list(cfqd, cfqq);

if (cfqq == cfqd->active_queue)
Expand Down Expand Up @@ -1094,11 +1105,30 @@ static struct cfq_queue *cfq_get_next_queue(struct cfq_data *cfqd)
service_tree_for(cfqd->serving_group, cfqd->serving_prio,
cfqd->serving_type, cfqd);

if (!cfqd->rq_queued)
return NULL;

if (RB_EMPTY_ROOT(&service_tree->rb))
return NULL;
return cfq_rb_first(service_tree);
}

static struct cfq_queue *cfq_get_next_queue_forced(struct cfq_data *cfqd)
{
struct cfq_group *cfqg = &cfqd->root_group;
struct cfq_queue *cfqq;
int i, j;
struct cfq_rb_root *st;

if (!cfqd->rq_queued)
return NULL;

for_each_cfqg_st(cfqg, i, j, st)
if ((cfqq = cfq_rb_first(st)) != NULL)
return cfqq;
return NULL;
}

/*
* Get and set a new active queue for service.
*/
Expand Down Expand Up @@ -1231,6 +1261,9 @@ static bool cfq_should_idle(struct cfq_data *cfqd, struct cfq_queue *cfqq)
enum wl_prio_t prio = cfqq_prio(cfqq);
struct cfq_rb_root *service_tree = cfqq->service_tree;

BUG_ON(!service_tree);
BUG_ON(!service_tree->count);

/* We never do for idle class queues. */
if (prio == IDLE_WORKLOAD)
return false;
Expand All @@ -1243,14 +1276,7 @@ static bool cfq_should_idle(struct cfq_data *cfqd, struct cfq_queue *cfqq)
* Otherwise, we do only if they are the last ones
* in their service tree.
*/
if (!service_tree)
service_tree = service_tree_for(cfqq->cfqg, prio,
cfqq_type(cfqq), cfqd);

if (service_tree->count == 0)
return true;

return (service_tree->count == 1 && cfq_rb_first(service_tree) == cfqq);
return service_tree->count == 1;
}

static void cfq_arm_slice_timer(struct cfq_data *cfqd)
Expand Down Expand Up @@ -1527,6 +1553,8 @@ static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd)
if (!cfqq)
goto new_queue;

if (!cfqd->rq_queued)
return NULL;
/*
* The active queue has run out of time, expire it and select new.
*/
Expand Down Expand Up @@ -1589,6 +1617,9 @@ static int __cfq_forced_dispatch_cfqq(struct cfq_queue *cfqq)
}

BUG_ON(!list_empty(&cfqq->fifo));

/* By default cfqq is not expired if it is empty. Do it explicitly */
__cfq_slice_expired(cfqq->cfqd, cfqq, 0);
return dispatched;
}

Expand All @@ -1600,14 +1631,9 @@ static int cfq_forced_dispatch(struct cfq_data *cfqd)
{
struct cfq_queue *cfqq;
int dispatched = 0;
int i, j;
struct cfq_group *cfqg = &cfqd->root_group;
struct cfq_rb_root *st;

for_each_cfqg_st(cfqg, i, j, st) {
while ((cfqq = cfq_rb_first(st)) != NULL)
dispatched += __cfq_forced_dispatch_cfqq(cfqq);
}
while ((cfqq = cfq_get_next_queue_forced(cfqd)) != NULL)
dispatched += __cfq_forced_dispatch_cfqq(cfqq);

cfq_slice_expired(cfqd, 0);
BUG_ON(cfqd->busy_queues);
Expand Down Expand Up @@ -1776,13 +1802,13 @@ static void cfq_put_queue(struct cfq_queue *cfqq)
cfq_log_cfqq(cfqd, cfqq, "put_queue");
BUG_ON(rb_first(&cfqq->sort_list));
BUG_ON(cfqq->allocated[READ] + cfqq->allocated[WRITE]);
BUG_ON(cfq_cfqq_on_rr(cfqq));

if (unlikely(cfqd->active_queue == cfqq)) {
__cfq_slice_expired(cfqd, cfqq, 0);
cfq_schedule_dispatch(cfqd);
}

BUG_ON(cfq_cfqq_on_rr(cfqq));
kmem_cache_free(cfq_pool, cfqq);
}

Expand Down Expand Up @@ -2444,9 +2470,11 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq,
if (cfq_class_idle(cfqq))
return true;

/* Allow preemption only if we are idling on sync-noidle tree */
if (cfqd->serving_type == SYNC_NOIDLE_WORKLOAD &&
cfqq_type(new_cfqq) == SYNC_NOIDLE_WORKLOAD &&
new_cfqq->service_tree->count == 1)
new_cfqq->service_tree->count == 2 &&
RB_EMPTY_ROOT(&cfqq->sort_list))
return true;

/*
Expand Down

0 comments on commit ea94a44

Please sign in to comment.