Newer
Older
int dispatched = 0;
BUG_ON(RB_EMPTY_ROOT(&cfqq->sort_list));
* follow expired path, else get first next available
if ((rq = cfq_check_fifo(cfqq)) == NULL)
rq = cfqq->next_rq;
/*
* finally, insert request into driver dispatch list
*/
if (!cfqd->active_cic) {
atomic_inc(&RQ_CIC(rq)->ioc->refcount);
cfqd->active_cic = RQ_CIC(rq);
if (RB_EMPTY_ROOT(&cfqq->sort_list))
break;
} while (dispatched < max_dispatch);
/*
* expire an async queue immediately if it has used up its slice. idle
* queue always expire after 1 dispatch round.
*/
if (cfqd->busy_queues > 1 && ((!cfq_cfqq_sync(cfqq) &&
dispatched >= cfq_prio_to_maxrq(cfqd, cfqq)) ||
cfqq->slice_end = jiffies + 1;
cfq_slice_expired(cfqd, 0);
return dispatched;
}
static inline int __cfq_forced_dispatch_cfqq(struct cfq_queue *cfqq)
{
int dispatched = 0;
while (cfqq->next_rq) {
cfq_dispatch_insert(cfqq->cfqd->queue, cfqq->next_rq);
dispatched++;
}
BUG_ON(!list_empty(&cfqq->fifo));
return dispatched;
}
/*
* Drain our current requests. Used for barriers and when switching
* io schedulers on-the-fly.
*/
static int cfq_forced_dispatch(struct cfq_data *cfqd)
int dispatched = 0;
while ((cfqq = cfq_rb_first(&cfqd->service_tree)) != NULL)
dispatched += __cfq_forced_dispatch_cfqq(cfqq);
cfq_slice_expired(cfqd, 0);
BUG_ON(cfqd->busy_queues);
return dispatched;
}
static int cfq_dispatch_requests(struct request_queue *q, int force)
{
struct cfq_data *cfqd = q->elevator->elevator_data;
if (!cfqd->busy_queues)
return 0;
if (unlikely(force))
return cfq_forced_dispatch(cfqd);
dispatched = 0;
while ((cfqq = cfq_select_queue(cfqd)) != NULL) {
int max_dispatch;
max_dispatch = cfqd->cfq_quantum;
if (cfq_class_idle(cfqq))
max_dispatch = 1;
if (cfqq->dispatched >= max_dispatch) {
if (cfqd->busy_queues > 1)
if (cfqq->dispatched >= 4 * max_dispatch)
if (cfqd->sync_flight && !cfq_cfqq_sync(cfqq))
break;
cfq_clear_cfqq_must_dispatch(cfqq);
cfq_clear_cfqq_wait_request(cfqq);
del_timer(&cfqd->idle_slice_timer);
dispatched += __cfq_dispatch_requests(cfqd, cfqq, max_dispatch);
* task holds one reference to the queue, dropped when task exits. each rq
* in-flight on this queue also holds a reference, dropped when rq is freed.
*
* queue lock must be held here.
*/
static void cfq_put_queue(struct cfq_queue *cfqq)
{
struct cfq_data *cfqd = cfqq->cfqd;
BUG_ON(atomic_read(&cfqq->ref) <= 0);
if (!atomic_dec_and_test(&cfqq->ref))
return;
BUG_ON(rb_first(&cfqq->sort_list));
BUG_ON(cfqq->allocated[READ] + cfqq->allocated[WRITE]);
if (unlikely(cfqd->active_queue == cfqq)) {
__cfq_slice_expired(cfqd, cfqq, 0);
cfq_schedule_dispatch(cfqd);
}
/*
* Call func for each cic attached to this ioc. Returns number of cic's seen.
*/
#define CIC_GANG_NR 16
static unsigned int
call_for_each_cic(struct io_context *ioc,
void (*func)(struct io_context *, struct cfq_io_context *))
struct cfq_io_context *cics[CIC_GANG_NR];
unsigned long index = 0;
unsigned int called = 0;
int nr;
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
/*
* Perhaps there's a better way - this just gang lookups from
* 0 to the end, restarting after each CIC_GANG_NR from the
* last key + 1.
*/
nr = radix_tree_gang_lookup(&ioc->radix_root, (void **) cics,
index, CIC_GANG_NR);
if (!nr)
break;
called += nr;
index = 1 + (unsigned long) cics[nr - 1]->key;
for (i = 0; i < nr; i++)
func(ioc, cics[i]);
} while (nr == CIC_GANG_NR);
rcu_read_unlock();
return called;
}
static void cic_free_func(struct io_context *ioc, struct cfq_io_context *cic)
{
unsigned long flags;
BUG_ON(!cic->dead_key);
spin_lock_irqsave(&ioc->lock, flags);
radix_tree_delete(&ioc->radix_root, cic->dead_key);
spin_unlock_irqrestore(&ioc->lock, flags);
kmem_cache_free(cfq_ioc_pool, cic);
}
static void cfq_free_io_context(struct io_context *ioc)
{
int freed;
/*
* ioc->refcount is zero here, so no more cic's are allowed to be
* linked into this ioc. So it should be ok to iterate over the known
* list, we will see all cic's since no new ones are added.
*/
freed = call_for_each_cic(ioc, cic_free_func);
elv_ioc_count_mod(ioc_count, -freed);
if (ioc_gone && !elv_ioc_count_read(ioc_count))
static void cfq_exit_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq)
if (unlikely(cfqq == cfqd->active_queue)) {
__cfq_slice_expired(cfqd, cfqq, 0);
cfq_schedule_dispatch(cfqd);
}
cfq_put_queue(cfqq);
}
static void __cfq_exit_single_io_context(struct cfq_data *cfqd,
struct cfq_io_context *cic)
{
/*
* Make sure key == NULL is seen for dead queues
*/
cic->dead_key = (unsigned long) cic->key;
cfq_exit_cfqq(cfqd, cic->cfqq[ASYNC]);
cic->cfqq[ASYNC] = NULL;
}
if (cic->cfqq[SYNC]) {
cfq_exit_cfqq(cfqd, cic->cfqq[SYNC]);
cic->cfqq[SYNC] = NULL;
}
static void cfq_exit_single_io_context(struct io_context *ioc,
struct cfq_io_context *cic)
{
struct cfq_data *cfqd = cic->key;
if (cfqd) {
struct request_queue *q = cfqd->queue;
spin_lock_irqsave(q->queue_lock, flags);
__cfq_exit_single_io_context(cfqd, cic);
spin_unlock_irqrestore(q->queue_lock, flags);
/*
* The process that ioc belongs to has exited, we need to clean up
* and put the internal structures we have that belongs to that process.
*/
static void cfq_exit_io_context(struct io_context *ioc)
rcu_assign_pointer(ioc->ioc_data, NULL);
call_for_each_cic(ioc, cfq_exit_single_io_context);
static struct cfq_io_context *
cfq_alloc_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
struct cfq_io_context *cic;
cic = kmem_cache_alloc_node(cfq_ioc_pool, gfp_mask | __GFP_ZERO,
cfqd->queue->node);
cic->last_end_request = jiffies;
INIT_LIST_HEAD(&cic->queue_list);
cic->dtor = cfq_free_io_context;
cic->exit = cfq_exit_io_context;
elv_ioc_count_inc(ioc_count);
static void cfq_init_prio_data(struct cfq_queue *cfqq, struct io_context *ioc)
{
struct task_struct *tsk = current;
int ioprio_class;
ioprio_class = IOPRIO_PRIO_CLASS(ioc->ioprio);
switch (ioprio_class) {
default:
printk(KERN_ERR "cfq: bad prio %x\n", ioprio_class);
case IOPRIO_CLASS_NONE:
/*
* no prio set, place us in the middle of the BE classes
*/
cfqq->ioprio = task_nice_ioprio(tsk);
cfqq->ioprio_class = IOPRIO_CLASS_BE;
break;
case IOPRIO_CLASS_RT:
cfqq->ioprio = task_ioprio(ioc);
cfqq->ioprio_class = IOPRIO_CLASS_RT;
break;
case IOPRIO_CLASS_BE:
cfqq->ioprio = task_ioprio(ioc);
cfqq->ioprio_class = IOPRIO_CLASS_BE;
break;
case IOPRIO_CLASS_IDLE:
cfqq->ioprio_class = IOPRIO_CLASS_IDLE;
cfqq->ioprio = 7;
break;
}
/*
* keep track of original prio settings in case we have to temporarily
* elevate the priority of this queue
*/
cfqq->org_ioprio = cfqq->ioprio;
cfqq->org_ioprio_class = cfqq->ioprio_class;
static inline void changed_ioprio(struct io_context *ioc,
struct cfq_io_context *cic)
struct cfq_data *cfqd = cic->key;
struct cfq_queue *cfqq;
if (unlikely(!cfqd))
return;
spin_lock_irqsave(cfqd->queue->queue_lock, flags);
cfqq = cic->cfqq[ASYNC];
if (cfqq) {
struct cfq_queue *new_cfqq;
new_cfqq = cfq_get_queue(cfqd, ASYNC, cic->ioc, GFP_ATOMIC);
if (new_cfqq) {
cic->cfqq[ASYNC] = new_cfqq;
cfq_put_queue(cfqq);
}
cfqq = cic->cfqq[SYNC];
if (cfqq)
cfq_mark_cfqq_prio_changed(cfqq);
spin_unlock_irqrestore(cfqd->queue->queue_lock, flags);
static void cfq_ioc_set_ioprio(struct io_context *ioc)
call_for_each_cic(ioc, changed_ioprio);
}
static struct cfq_queue *
cfq_find_alloc_queue(struct cfq_data *cfqd, int is_sync,
struct io_context *ioc, gfp_t gfp_mask)
{
struct cfq_queue *cfqq, *new_cfqq = NULL;
cic = cfq_cic_lookup(cfqd, ioc);
/* cic always exists here */
cfqq = cic_to_cfqq(cic, is_sync);
if (!cfqq) {
if (new_cfqq) {
cfqq = new_cfqq;
new_cfqq = NULL;
} else if (gfp_mask & __GFP_WAIT) {
/*
* Inform the allocator of the fact that we will
* just repeat this allocation if it fails, to allow
* the allocator to do whatever it needs to attempt to
* free memory.
*/
spin_unlock_irq(cfqd->queue->queue_lock);
new_cfqq = kmem_cache_alloc_node(cfq_pool,
gfp_mask | __GFP_NOFAIL | __GFP_ZERO,
cfqd->queue->node);
spin_lock_irq(cfqd->queue->queue_lock);
goto retry;
} else {
cfqq = kmem_cache_alloc_node(cfq_pool,
gfp_mask | __GFP_ZERO,
cfqd->queue->node);
if (!cfqq)
goto out;
}
RB_CLEAR_NODE(&cfqq->rb_node);
INIT_LIST_HEAD(&cfqq->fifo);
atomic_set(&cfqq->ref, 0);
cfqq->cfqd = cfqd;
cfq_mark_cfqq_queue_new(cfqq);
cfq_init_prio_data(cfqq, ioc);
if (is_sync) {
if (!cfq_class_idle(cfqq))
cfq_mark_cfqq_idle_window(cfqq);
cfq_mark_cfqq_sync(cfqq);
}
}
if (new_cfqq)
kmem_cache_free(cfq_pool, new_cfqq);
out:
WARN_ON((gfp_mask & __GFP_WAIT) && !cfqq);
return cfqq;
}
static struct cfq_queue **
cfq_async_queue_prio(struct cfq_data *cfqd, int ioprio_class, int ioprio)
{
switch(ioprio_class) {
case IOPRIO_CLASS_RT:
return &cfqd->async_cfqq[0][ioprio];
case IOPRIO_CLASS_BE:
return &cfqd->async_cfqq[1][ioprio];
case IOPRIO_CLASS_IDLE:
return &cfqd->async_idle_cfqq;
default:
BUG();
}
}
cfq_get_queue(struct cfq_data *cfqd, int is_sync, struct io_context *ioc,
const int ioprio = task_ioprio(ioc);
const int ioprio_class = task_ioprio_class(ioc);
struct cfq_queue **async_cfqq = NULL;
struct cfq_queue *cfqq = NULL;
if (!is_sync) {
async_cfqq = cfq_async_queue_prio(cfqd, ioprio_class, ioprio);
cfqq = *async_cfqq;
}
cfqq = cfq_find_alloc_queue(cfqd, is_sync, ioc, gfp_mask);
if (!cfqq)
return NULL;
}
/*
* pin the queue now that it's allocated, scheduler exit will prune it
*/
if (!is_sync && !(*async_cfqq)) {
}
atomic_inc(&cfqq->ref);
return cfqq;
}
static void cfq_cic_free(struct cfq_io_context *cic)
{
kmem_cache_free(cfq_ioc_pool, cic);
elv_ioc_count_dec(ioc_count);
if (ioc_gone && !elv_ioc_count_read(ioc_count))
complete(ioc_gone);
}
/*
* We drop cfq io contexts lazily, so we may find a dead one.
*/
cfq_drop_dead_cic(struct cfq_data *cfqd, struct io_context *ioc,
struct cfq_io_context *cic)
unsigned long flags;
WARN_ON(!list_empty(&cic->queue_list));
spin_lock_irqsave(&ioc->lock, flags);
rcu_assign_pointer(ioc->ioc_data, NULL);
radix_tree_delete(&ioc->radix_root, (unsigned long) cfqd);
spin_unlock_irqrestore(&ioc->lock, flags);
cfq_cic_free(cic);
static struct cfq_io_context *
cfq_cic_lookup(struct cfq_data *cfqd, struct io_context *ioc)
{
struct cfq_io_context *cic;
if (unlikely(!ioc))
return NULL;
/*
* we maintain a last-hit cache, to avoid browsing over the tree
*/
cic = rcu_dereference(ioc->ioc_data);
if (cic && cic->key == cfqd)
return cic;
do {
rcu_read_lock();
cic = radix_tree_lookup(&ioc->radix_root, (unsigned long) cfqd);
rcu_read_unlock();
if (!cic)
break;
/* ->key must be copied to avoid race with cfq_exit_queue() */
k = cic->key;
if (unlikely(!k)) {
cfq_drop_dead_cic(cfqd, ioc, cic);
continue;
rcu_assign_pointer(ioc->ioc_data, cic);
break;
} while (1);
}
/*
* Add cic into ioc, using cfqd as the search key. This enables us to lookup
* the process specific cfq io context when entered from the block layer.
* Also adds the cic to a per-cfqd list, used when this queue is removed.
*/
static inline int
cfq_cic_link(struct cfq_data *cfqd, struct io_context *ioc,
struct cfq_io_context *cic, gfp_t gfp_mask)
{
ret = radix_tree_preload(gfp_mask);
if (!ret) {
cic->ioc = ioc;
cic->key = cfqd;
spin_lock_irqsave(&ioc->lock, flags);
ret = radix_tree_insert(&ioc->radix_root,
(unsigned long) cfqd, cic);
spin_unlock_irqrestore(&ioc->lock, flags);
radix_tree_preload_end();
if (!ret) {
spin_lock_irqsave(cfqd->queue->queue_lock, flags);
list_add(&cic->queue_list, &cfqd->cic_list);
spin_unlock_irqrestore(cfqd->queue->queue_lock, flags);
}
}
if (ret)
printk(KERN_ERR "cfq: cic link failed!\n");
}
/*
* Setup general io context and cfq io context. There can be several cfq
* io contexts per general io context, if this process is doing io to more
* than one device managed by cfq.
cfq_get_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
struct io_context *ioc = NULL;
might_sleep_if(gfp_mask & __GFP_WAIT);
ioc = get_io_context(gfp_mask, cfqd->queue->node);
cic = cfq_cic_lookup(cfqd, ioc);
if (cic)
goto out;
cic = cfq_alloc_io_context(cfqd, gfp_mask);
if (cic == NULL)
goto err;
if (cfq_cic_link(cfqd, ioc, cic, gfp_mask))
goto err_free;
smp_read_barrier_depends();
if (unlikely(ioc->ioprio_changed))
cfq_ioc_set_ioprio(ioc);
err_free:
cfq_cic_free(cic);
err:
put_io_context(ioc);
return NULL;
}
static void
cfq_update_io_thinktime(struct cfq_data *cfqd, struct cfq_io_context *cic)
unsigned long elapsed = jiffies - cic->last_end_request;
unsigned long ttime = min(elapsed, 2UL * cfqd->cfq_slice_idle);
cic->ttime_samples = (7*cic->ttime_samples + 256) / 8;
cic->ttime_total = (7*cic->ttime_total + 256*ttime) / 8;
cic->ttime_mean = (cic->ttime_total + 128) / cic->ttime_samples;
}
cfq_update_io_seektime(struct cfq_data *cfqd, struct cfq_io_context *cic,
struct request *rq)
{
sector_t sdist;
u64 total;
if (cic->last_request_pos < rq->sector)
sdist = rq->sector - cic->last_request_pos;
/*
* Don't allow the seek distance to get too large from the
* odd fragment, pagein, etc
*/
if (cic->seek_samples <= 60) /* second&third seek */
sdist = min(sdist, (cic->seek_mean * 4) + 2*1024*1024);
else
sdist = min(sdist, (cic->seek_mean * 4) + 2*1024*64);
cic->seek_samples = (7*cic->seek_samples + 256) / 8;
cic->seek_total = (7*cic->seek_total + (u64)256*sdist) / 8;
total = cic->seek_total + (cic->seek_samples/2);
do_div(total, cic->seek_samples);
cic->seek_mean = (sector_t)total;
}
/*
* Disable idle window if the process thinks too long or seeks so much that
* it doesn't matter
*/
static void
cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq,
struct cfq_io_context *cic)
{
/*
* Don't idle for async or idle io prio class
*/
if (!cfq_cfqq_sync(cfqq) || cfq_class_idle(cfqq))
return;
enable_idle = cfq_cfqq_idle_window(cfqq);
if (!atomic_read(&cic->ioc->nr_tasks) || !cfqd->cfq_slice_idle ||
(cfqd->hw_tag && CIC_SEEKY(cic)))
enable_idle = 0;
else if (sample_valid(cic->ttime_samples)) {
if (cic->ttime_mean > cfqd->cfq_slice_idle)
enable_idle = 0;
else
enable_idle = 1;
if (enable_idle)
cfq_mark_cfqq_idle_window(cfqq);
else
cfq_clear_cfqq_idle_window(cfqq);
/*
* Check if new_cfqq should preempt the currently active queue. Return 0 for
* no or if we aren't sure, a 1 will cause a preempt.
*/
static int
cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq,
cfqq = cfqd->active_queue;
if (!cfqq)
if (cfq_slice_used(cfqq))
return 1;
if (cfq_class_idle(new_cfqq))
if (cfq_class_idle(cfqq))
return 1;
/*
* if the new request is sync, but the currently running queue is
* not, let the sync request have priority.
*/
/*
* So both queues are sync. Let the new request get disk time if
* it's a metadata request and the current queue is doing regular IO.
*/
if (rq_is_meta(rq) && !cfqq->meta_pending)
return 1;
if (!cfqd->active_cic || !cfq_cfqq_wait_request(cfqq))
return 0;
/*
* if this request is as-good as one we would expect from the
* current cfqq, let it preempt
*/
return 0;
}
/*
* cfqq preempts the active queue. if we allowed preempt with no slice left,
* let it have half of its nominal slice.
*/
static void cfq_preempt_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq)
{
cfq_slice_expired(cfqd, 1);
/*
* Put the new queue at the front of the of the current list,
* so we know that it will be selected next.
*/
BUG_ON(!cfq_cfqq_on_rr(cfqq));
cfq_service_tree_add(cfqd, cfqq, 1);
cfqq->slice_end = 0;
cfq_mark_cfqq_slice_new(cfqq);
* Called when a new fs request (rq) is added (to cfqq). Check if there's
* something we should do about it
*/
static void
cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
struct request *rq)
if (rq_is_meta(rq))
cfqq->meta_pending++;
cfq_update_idle_window(cfqd, cfqq, cic);
cic->last_request_pos = rq->sector + rq->nr_sectors;
if (cfqq == cfqd->active_queue) {
/*
* if we are waiting for a request for this queue, let it rip
* immediately and flag that we must not expire this queue
* just now
*/
if (cfq_cfqq_wait_request(cfqq)) {
cfq_mark_cfqq_must_dispatch(cfqq);
del_timer(&cfqd->idle_slice_timer);
} else if (cfq_should_preempt(cfqd, cfqq, rq)) {
/*
* not the active queue - expire current slice if it is
* idle and has expired it's mean thinktime or this new queue
* has some old slice time left and is of higher priority
*/
cfq_preempt_queue(cfqd, cfqq);
static void cfq_insert_request(struct request_queue *q, struct request *rq)
struct cfq_data *cfqd = q->elevator->elevator_data;
cfq_init_prio_data(cfqq, RQ_CIC(rq)->ioc);
list_add_tail(&rq->queuelist, &cfqq->fifo);
static void cfq_completed_request(struct request_queue *q, struct request *rq)
struct cfq_data *cfqd = cfqq->cfqd;
const int sync = rq_is_sync(rq);
unsigned long now;
now = jiffies;
WARN_ON(!cfqd->rq_in_driver);
cfqd->rq_in_driver--;
if (cfq_cfqq_sync(cfqq))
cfqd->sync_flight--;
if (!cfq_class_idle(cfqq))
cfqd->last_end_request = now;
/*
* If this is the active queue, check if it needs to be expired,
* or if we want to idle in case it has no pending requests.
*/
if (cfqd->active_queue == cfqq) {
if (cfq_cfqq_slice_new(cfqq)) {
cfq_set_prio_slice(cfqd, cfqq);
cfq_clear_cfqq_slice_new(cfqq);
}
if (cfq_slice_used(cfqq) || cfq_class_idle(cfqq))
cfq_slice_expired(cfqd, 1);
else if (sync && RB_EMPTY_ROOT(&cfqq->sort_list))
cfq_arm_slice_timer(cfqd);
if (!cfqd->rq_in_driver)
cfq_schedule_dispatch(cfqd);
/*
* we temporarily boost lower priority queues if they are holding fs exclusive
* resources. they are boosted to normal prio (CLASS_BE/4)
*/
static void cfq_prio_boost(struct cfq_queue *cfqq)
if (has_fs_excl()) {
/*
* boost idle prio on transactions that would lock out other
* users of the filesystem
*/
if (cfq_class_idle(cfqq))
cfqq->ioprio_class = IOPRIO_CLASS_BE;
if (cfqq->ioprio > IOPRIO_NORM)
cfqq->ioprio = IOPRIO_NORM;
} else {
/*
* check if we need to unboost the queue
*/
if (cfqq->ioprio_class != cfqq->org_ioprio_class)
cfqq->ioprio_class = cfqq->org_ioprio_class;
if (cfqq->ioprio != cfqq->org_ioprio)
cfqq->ioprio = cfqq->org_ioprio;
}
}
static inline int __cfq_may_queue(struct cfq_queue *cfqq)
if ((cfq_cfqq_wait_request(cfqq) || cfq_cfqq_must_alloc(cfqq)) &&
return ELV_MQUEUE_MUST;
return ELV_MQUEUE_MAY;
}
static int cfq_may_queue(struct request_queue *q, int rw)
{
struct cfq_data *cfqd = q->elevator->elevator_data;
struct task_struct *tsk = current;
struct cfq_queue *cfqq;
/*
* don't force setup of a queue from here, as a call to may_queue
* does not necessarily imply that a request actually will be queued.
* so just lookup a possibly existing queue, or return 'may queue'
* if that fails
*/
cic = cfq_cic_lookup(cfqd, tsk->io_context);
if (!cic)
return ELV_MQUEUE_MAY;
cfqq = cic_to_cfqq(cic, rw & REQ_RW_SYNC);
cfq_init_prio_data(cfqq, cic->ioc);
cfq_prio_boost(cfqq);
return __cfq_may_queue(cfqq);
}
return ELV_MQUEUE_MAY;
static void cfq_put_request(struct request *rq)
const int rw = rq_data_dir(rq);
BUG_ON(!cfqq->allocated[rw]);
cfqq->allocated[rw]--;
* Allocate cfq data structures associated with this request.
cfq_set_request(struct request_queue *q, struct request *rq, gfp_t gfp_mask)
{
struct cfq_data *cfqd = q->elevator->elevator_data;
struct cfq_io_context *cic;
const int rw = rq_data_dir(rq);
const int is_sync = rq_is_sync(rq);
struct cfq_queue *cfqq;
unsigned long flags;
might_sleep_if(gfp_mask & __GFP_WAIT);
cic = cfq_get_io_context(cfqd, gfp_mask);
if (!cic)
goto queue_fail;
cfqq = cic_to_cfqq(cic, is_sync);
if (!cfqq) {
cfqq = cfq_get_queue(cfqd, is_sync, cic->ioc, gfp_mask);
if (!cfqq)
goto queue_fail;
cic_set_cfqq(cic, cfqq, is_sync);
}
atomic_inc(&cfqq->ref);
spin_unlock_irqrestore(q->queue_lock, flags);
rq->elevator_private = cic;
rq->elevator_private2 = cfqq;
return 0;
queue_fail:
if (cic)
put_io_context(cic->ioc);
spin_unlock_irqrestore(q->queue_lock, flags);
return 1;
}