[PATCH] Add blk_start_queueing() helper

CFQ implements this on its own now, but it's really block layer
knowledge. Tells a device queue to start dispatching requests to
the driver, taking care to unplug if needed. Also fixes the issue
where as/cfq will invoke a stopped queue, which we really don't
want.

Signed-off-by: Jens Axboe <axboe@suse.de>
This commit is contained in:
Jens Axboe 2006-07-20 14:54:05 +02:00 committed by Jens Axboe
parent 981a79730d
commit dc72ef4ae3
4 changed files with 26 additions and 25 deletions

View File

@ -1280,8 +1280,7 @@ static void as_work_handler(void *data)
unsigned long flags;
spin_lock_irqsave(q->queue_lock, flags);
if (!as_queue_empty(q))
q->request_fn(q);
blk_start_queueing(q);
spin_unlock_irqrestore(q->queue_lock, flags);
}

View File

@ -1552,19 +1552,6 @@ static void cfq_preempt_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq)
__cfq_set_active_queue(cfqd, cfqq);
}
/*
* should really be a ll_rw_blk.c helper
*/
static void cfq_start_queueing(struct cfq_data *cfqd, struct cfq_queue *cfqq)
{
request_queue_t *q = cfqd->queue;
if (!blk_queue_plugged(q))
q->request_fn(q);
else
__generic_unplug_device(q);
}
/*
* Called when a new fs request (rq) is added (to cfqq). Check if there's
* something we should do about it
@ -1593,7 +1580,7 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
if (cic == cfqd->active_cic &&
del_timer(&cfqd->idle_slice_timer)) {
cfq_slice_expired(cfqd, 0);
cfq_start_queueing(cfqd, cfqq);
blk_start_queueing(cfqd->queue);
}
return;
}
@ -1614,7 +1601,7 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
if (cfq_cfqq_wait_request(cfqq)) {
cfq_mark_cfqq_must_dispatch(cfqq);
del_timer(&cfqd->idle_slice_timer);
cfq_start_queueing(cfqd, cfqq);
blk_start_queueing(cfqd->queue);
}
} else if (cfq_should_preempt(cfqd, cfqq, rq)) {
/*
@ -1624,7 +1611,7 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
*/
cfq_preempt_queue(cfqd, cfqq);
cfq_mark_cfqq_must_dispatch(cfqq);
cfq_start_queueing(cfqd, cfqq);
blk_start_queueing(cfqd->queue);
}
}
@ -1832,8 +1819,7 @@ static void cfq_kick_queue(void *data)
unsigned long flags;
spin_lock_irqsave(q->queue_lock, flags);
blk_remove_plug(q);
q->request_fn(q);
blk_start_queueing(q);
spin_unlock_irqrestore(q->queue_lock, flags);
}

View File

@ -2266,6 +2266,25 @@ struct request *blk_get_request(request_queue_t *q, int rw, gfp_t gfp_mask)
}
EXPORT_SYMBOL(blk_get_request);
/**
* blk_start_queueing - initiate dispatch of requests to device
* @q: request queue to kick into gear
*
* This is basically a helper to remove the need to know whether a queue
* is plugged or not if someone just wants to initiate dispatch of requests
* for this queue.
*
* The queue lock must be held with interrupts disabled.
*/
void blk_start_queueing(request_queue_t *q)
{
if (!blk_queue_plugged(q))
q->request_fn(q);
else
__generic_unplug_device(q);
}
EXPORT_SYMBOL(blk_start_queueing);
/**
* blk_requeue_request - put a request back on queue
* @q: request queue where request should be inserted
@ -2333,11 +2352,7 @@ void blk_insert_request(request_queue_t *q, struct request *rq,
drive_stat_acct(rq, rq->nr_sectors, 1);
__elv_add_request(q, rq, where, 0);
if (blk_queue_plugged(q))
__generic_unplug_device(q);
else
q->request_fn(q);
blk_start_queueing(q);
spin_unlock_irqrestore(q->queue_lock, flags);
}

View File

@ -635,6 +635,7 @@ extern void blk_stop_queue(request_queue_t *q);
extern void blk_sync_queue(struct request_queue *q);
extern void __blk_stop_queue(request_queue_t *q);
extern void blk_run_queue(request_queue_t *);
extern void blk_start_queueing(request_queue_t *);
extern void blk_queue_activity_fn(request_queue_t *, activity_fn *, void *);
extern int blk_rq_map_user(request_queue_t *, struct request *, void __user *, unsigned int);
extern int blk_rq_unmap_user(struct bio *, unsigned int);