2008-01-29 16:53:40 +03: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 22:13:11 +04:00
* @ error : end I / O status of the request
2008-01-29 16:53:40 +03:00
*/
2008-07-15 23:21:45 +04:00
static void blk_end_sync_rq ( struct request * rq , int error )
2008-01-29 16:53:40 +03: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 22:13:11 +04:00
* Insert a fully prepared request at the back of the I / O scheduler queue
2008-01-29 16:53:40 +03: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 - > cmd_flags | = REQ_NOMERGE ;
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 23:21:43 +04: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 16:53:40 +03: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 22:13:11 +04:00
* Insert a fully prepared request at the back of the I / O scheduler queue
2008-01-29 16:53:40 +03: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 ) ;