2008-01-29 06:53:40 -07:00
|
|
|
/*
|
|
|
|
* Functions related to setting various queue properties from drivers
|
|
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/bio.h>
|
|
|
|
#include <linux/blkdev.h>
|
|
|
|
|
|
|
|
#include "blk.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
* for max sense size
|
|
|
|
*/
|
|
|
|
#include <scsi/scsi_cmnd.h>
|
|
|
|
|
|
|
|
/**
|
|
|
|
* blk_end_sync_rq - executes a completion event on a request
|
|
|
|
* @rq: request to complete
|
2008-08-19 12:13:11 -06:00
|
|
|
* @error: end I/O status of the request
|
2008-01-29 06:53:40 -07:00
|
|
|
*/
|
2008-07-15 13:21:45 -06:00
|
|
|
static void blk_end_sync_rq(struct request *rq, int error)
|
2008-01-29 06:53:40 -07:00
|
|
|
{
|
|
|
|
struct completion *waiting = rq->end_io_data;
|
|
|
|
|
|
|
|
rq->end_io_data = NULL;
|
|
|
|
__blk_put_request(rq->q, rq);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* complete last, if this is a stack request the process (and thus
|
|
|
|
* the rq pointer) could be invalid right after this complete()
|
|
|
|
*/
|
|
|
|
complete(waiting);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* blk_execute_rq_nowait - insert a request into queue for execution
|
|
|
|
* @q: queue to insert the request in
|
|
|
|
* @bd_disk: matching gendisk
|
|
|
|
* @rq: request to insert
|
|
|
|
* @at_head: insert request at head or tail of queue
|
|
|
|
* @done: I/O completion handler
|
|
|
|
*
|
|
|
|
* Description:
|
2008-08-19 12:13:11 -06:00
|
|
|
* Insert a fully prepared request at the back of the I/O scheduler queue
|
2008-01-29 06:53:40 -07:00
|
|
|
* for execution. Don't wait for completion.
|
|
|
|
*/
|
|
|
|
void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk,
|
|
|
|
struct request *rq, int at_head,
|
|
|
|
rq_end_io_fn *done)
|
|
|
|
{
|
|
|
|
int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK;
|
|
|
|
|
|
|
|
rq->rq_disk = bd_disk;
|
|
|
|
rq->end_io = done;
|
|
|
|
WARN_ON(irqs_disabled());
|
|
|
|
spin_lock_irq(q->queue_lock);
|
|
|
|
__elv_add_request(q, rq, where, 1);
|
|
|
|
__generic_unplug_device(q);
|
2008-07-15 13:21:43 -06:00
|
|
|
/* the queue is stopped so it won't be plugged+unplugged */
|
|
|
|
if (blk_pm_resume_request(rq))
|
|
|
|
q->request_fn(q);
|
2008-01-29 06:53:40 -07:00
|
|
|
spin_unlock_irq(q->queue_lock);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(blk_execute_rq_nowait);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* blk_execute_rq - insert a request into queue for execution
|
|
|
|
* @q: queue to insert the request in
|
|
|
|
* @bd_disk: matching gendisk
|
|
|
|
* @rq: request to insert
|
|
|
|
* @at_head: insert request at head or tail of queue
|
|
|
|
*
|
|
|
|
* Description:
|
2008-08-19 12:13:11 -06:00
|
|
|
* Insert a fully prepared request at the back of the I/O scheduler queue
|
2008-01-29 06:53:40 -07:00
|
|
|
* for execution and wait for completion.
|
|
|
|
*/
|
|
|
|
int blk_execute_rq(struct request_queue *q, struct gendisk *bd_disk,
|
|
|
|
struct request *rq, int at_head)
|
|
|
|
{
|
|
|
|
DECLARE_COMPLETION_ONSTACK(wait);
|
|
|
|
char sense[SCSI_SENSE_BUFFERSIZE];
|
|
|
|
int err = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* we need an extra reference to the request, so we can look at
|
|
|
|
* it after io completion
|
|
|
|
*/
|
|
|
|
rq->ref_count++;
|
|
|
|
|
|
|
|
if (!rq->sense) {
|
|
|
|
memset(sense, 0, sizeof(sense));
|
|
|
|
rq->sense = sense;
|
|
|
|
rq->sense_len = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
rq->end_io_data = &wait;
|
|
|
|
blk_execute_rq_nowait(q, bd_disk, rq, at_head, blk_end_sync_rq);
|
|
|
|
wait_for_completion(&wait);
|
|
|
|
|
|
|
|
if (rq->errors)
|
|
|
|
err = -EIO;
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(blk_execute_rq);
|