Skip to content

Commit

Permalink
cfq-iosched: fix async queue behaviour
Browse files Browse the repository at this point in the history
With the cfq_queue hash removal, we inadvertently got rid of the
async queue sharing. This was not intentional, in fact CFQ purposely
shares the async queue per priority level to get good merging for
async writes.

So put some logic in cfq_get_queue() to track the shared queues.

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
  • Loading branch information
Jens Axboe committed Jul 10, 2007
1 parent 72d3a38 commit 15c31be
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 5 deletions.
39 changes: 36 additions & 3 deletions block/cfq-iosched.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ struct cfq_data {
struct cfq_queue *active_queue;
struct cfq_io_context *active_cic;

struct cfq_queue *async_cfqq[IOPRIO_BE_NR];

struct timer_list idle_class_timer;

sector_t last_position;
Expand Down Expand Up @@ -1351,8 +1353,8 @@ static void cfq_ioc_set_ioprio(struct io_context *ioc)
}

static struct cfq_queue *
cfq_get_queue(struct cfq_data *cfqd, int is_sync, struct task_struct *tsk,
gfp_t gfp_mask)
cfq_find_alloc_queue(struct cfq_data *cfqd, int is_sync,
struct task_struct *tsk, gfp_t gfp_mask)
{
struct cfq_queue *cfqq, *new_cfqq = NULL;
struct cfq_io_context *cic;
Expand Down Expand Up @@ -1405,12 +1407,35 @@ cfq_get_queue(struct cfq_data *cfqd, int is_sync, struct task_struct *tsk,
if (new_cfqq)
kmem_cache_free(cfq_pool, new_cfqq);

atomic_inc(&cfqq->ref);
out:
WARN_ON((gfp_mask & __GFP_WAIT) && !cfqq);
return cfqq;
}

static struct cfq_queue *
cfq_get_queue(struct cfq_data *cfqd, int is_sync, struct task_struct *tsk,
gfp_t gfp_mask)
{
const int ioprio = task_ioprio(tsk);
struct cfq_queue *cfqq = NULL;

if (!is_sync)
cfqq = cfqd->async_cfqq[ioprio];
if (!cfqq)
cfqq = cfq_find_alloc_queue(cfqd, is_sync, tsk, gfp_mask);

/*
* pin the queue now that it's allocated, scheduler exit will prune it
*/
if (!is_sync && !cfqd->async_cfqq[ioprio]) {
atomic_inc(&cfqq->ref);
cfqd->async_cfqq[ioprio] = cfqq;
}

atomic_inc(&cfqq->ref);
return cfqq;
}

/*
* We drop cfq io contexts lazily, so we may find a dead one.
*/
Expand Down Expand Up @@ -2019,6 +2044,7 @@ static void cfq_exit_queue(elevator_t *e)
{
struct cfq_data *cfqd = e->elevator_data;
request_queue_t *q = cfqd->queue;
int i;

cfq_shutdown_timer_wq(cfqd);

Expand All @@ -2035,6 +2061,13 @@ static void cfq_exit_queue(elevator_t *e)
__cfq_exit_single_io_context(cfqd, cic);
}

/*
* Put the async queues
*/
for (i = 0; i < IOPRIO_BE_NR; i++)
if (cfqd->async_cfqq[i])
cfq_put_queue(cfqd->async_cfqq[i]);

spin_unlock_irq(q->queue_lock);

cfq_shutdown_timer_wq(cfqd);
Expand Down
6 changes: 4 additions & 2 deletions include/linux/ioprio.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,10 @@ enum {
#define IOPRIO_NORM (4)
static inline int task_ioprio(struct task_struct *task)
{
WARN_ON(!ioprio_valid(task->ioprio));
return IOPRIO_PRIO_DATA(task->ioprio);
if (ioprio_valid(task->ioprio))
return IOPRIO_PRIO_DATA(task->ioprio);

return IOPRIO_NORM;
}

static inline int task_nice_ioprio(struct task_struct *task)
Expand Down

0 comments on commit 15c31be

Please sign in to comment.