@ -109,28 +109,6 @@ void dm_stop_queue(struct request_queue *q)
dm_mq_stop_queue ( q ) ;
}
static struct dm_rq_target_io * alloc_old_rq_tio ( struct mapped_device * md ,
gfp_t gfp_mask )
{
return mempool_alloc ( md - > io_pool , gfp_mask ) ;
}
static void free_old_rq_tio ( struct dm_rq_target_io * tio )
{
mempool_free ( tio , tio - > md - > io_pool ) ;
}
static struct request * alloc_old_clone_request ( struct mapped_device * md ,
gfp_t gfp_mask )
{
return mempool_alloc ( md - > rq_pool , gfp_mask ) ;
}
static void free_old_clone_request ( struct mapped_device * md , struct request * rq )
{
mempool_free ( rq , md - > rq_pool ) ;
}
/*
* Partial completion handling for request - based dm
*/
@ -185,7 +163,7 @@ static void end_clone_bio(struct bio *clone)
static struct dm_rq_target_io * tio_from_request ( struct request * rq )
{
return ( rq - > q - > mq_ops ? blk_mq_rq_to_pdu ( rq ) : rq - > special ) ;
return blk_mq_rq_to_pdu ( rq ) ;
}
static void rq_end_stats ( struct mapped_device * md , struct request * orig )
@ -233,31 +211,6 @@ static void rq_completed(struct mapped_device *md, int rw, bool run_queue)
dm_put ( md ) ;
}
static void free_rq_clone ( struct request * clone )
{
struct dm_rq_target_io * tio = clone - > end_io_data ;
struct mapped_device * md = tio - > md ;
blk_rq_unprep_clone ( clone ) ;
/*
* It is possible for a clone_old_rq ( ) allocated clone to
* get passed in - - it may not yet have a request_queue .
* This is known to occur if the error target replaces
* a multipath target that has a request_fn queue stacked
* on blk - mq queue ( s ) .
*/
if ( clone - > q & & clone - > q - > mq_ops )
/* stacked on blk-mq queue(s) */
tio - > ti - > type - > release_clone_rq ( clone ) ;
else if ( ! md - > queue - > mq_ops )
/* request_fn queue stacked on request_fn queue(s) */
free_old_clone_request ( md , clone ) ;
if ( ! md - > queue - > mq_ops )
free_old_rq_tio ( tio ) ;
}
/*
* Complete the clone and the original request .
* Must be called without clone ' s queue lock held ,
@ -270,7 +223,9 @@ static void dm_end_request(struct request *clone, int error)
struct mapped_device * md = tio - > md ;
struct request * rq = tio - > orig ;
free_rq_clone ( clone ) ;
blk_rq_unprep_clone ( clone ) ;
tio - > ti - > type - > release_clone_rq ( clone ) ;
rq_end_stats ( md , rq ) ;
if ( ! rq - > q - > mq_ops )
blk_end_request_all ( rq , error ) ;
@ -279,22 +234,6 @@ static void dm_end_request(struct request *clone, int error)
rq_completed ( md , rw , true ) ;
}
static void dm_unprep_request ( struct request * rq )
{
struct dm_rq_target_io * tio = tio_from_request ( rq ) ;
struct request * clone = tio - > clone ;
if ( ! rq - > q - > mq_ops ) {
rq - > special = NULL ;
rq - > rq_flags & = ~ RQF_DONTPREP ;
}
if ( clone )
free_rq_clone ( clone ) ;
else if ( ! tio - > md - > queue - > mq_ops )
free_old_rq_tio ( tio ) ;
}
/*
* Requeue the original request of a clone .
*/
@ -333,7 +272,10 @@ static void dm_requeue_original_request(struct dm_rq_target_io *tio, bool delay_
int rw = rq_data_dir ( rq ) ;
rq_end_stats ( md , rq ) ;
dm_unprep_request ( rq ) ;
if ( tio - > clone ) {
blk_rq_unprep_clone ( tio - > clone ) ;
tio - > ti - > type - > release_clone_rq ( tio - > clone ) ;
}
if ( ! rq - > q - > mq_ops )
dm_old_requeue_request ( rq ) ;
@ -388,14 +330,11 @@ static void dm_softirq_done(struct request *rq)
if ( ! clone ) {
rq_end_stats ( tio - > md , rq ) ;
rw = rq_data_dir ( rq ) ;
if ( ! rq - > q - > mq_ops ) {
if ( ! rq - > q - > mq_ops )
blk_end_request_all ( rq , tio - > error ) ;
rq_completed ( tio - > md , rw , false ) ;
free_old_rq_tio ( tio ) ;
} else {
else
blk_mq_end_request ( rq , tio - > error ) ;
rq_completed ( tio - > md , rw , false ) ;
}
rq_completed ( tio - > md , rw , false ) ;
return ;
}
@ -439,16 +378,6 @@ static void end_clone_request(struct request *clone, int error)
{
struct dm_rq_target_io * tio = clone - > end_io_data ;
if ( ! clone - > q - > mq_ops ) {
/*
* For just cleaning up the information of the queue in which
* the clone was dispatched .
* The clone is * NOT * freed actually here because it is alloced
* from dm own mempool ( RQF_ALLOCED isn ' t set ) .
*/
__blk_put_request ( clone - > q , clone ) ;
}
/*
* Actual request completion is done in a softirq context which doesn ' t
* hold the clone ' s queue lock . Otherwise , deadlock could occur because :
@ -506,28 +435,6 @@ static int setup_clone(struct request *clone, struct request *rq,
return 0 ;
}
static struct request * clone_old_rq ( struct request * rq , struct mapped_device * md ,
struct dm_rq_target_io * tio , gfp_t gfp_mask )
{
/*
* Create clone for use with . request_fn request_queue
*/
struct request * clone ;
clone = alloc_old_clone_request ( md , gfp_mask ) ;
if ( ! clone )
return NULL ;
blk_rq_init ( NULL , clone ) ;
if ( setup_clone ( clone , rq , tio , gfp_mask ) ) {
/* -ENOMEM */
free_old_clone_request ( md , clone ) ;
return NULL ;
}
return clone ;
}
static void map_tio_request ( struct kthread_work * work ) ;
static void init_tio ( struct dm_rq_target_io * tio , struct request * rq ,
@ -549,60 +456,6 @@ static void init_tio(struct dm_rq_target_io *tio, struct request *rq,
kthread_init_work ( & tio - > work , map_tio_request ) ;
}
static struct dm_rq_target_io * dm_old_prep_tio ( struct request * rq ,
struct mapped_device * md ,
gfp_t gfp_mask )
{
struct dm_rq_target_io * tio ;
int srcu_idx ;
struct dm_table * table ;
tio = alloc_old_rq_tio ( md , gfp_mask ) ;
if ( ! tio )
return NULL ;
init_tio ( tio , rq , md ) ;
table = dm_get_live_table ( md , & srcu_idx ) ;
/*
* Must clone a request if this . request_fn DM device
* is stacked on . request_fn device ( s ) .
*/
if ( ! dm_table_all_blk_mq_devices ( table ) ) {
if ( ! clone_old_rq ( rq , md , tio , gfp_mask ) ) {
dm_put_live_table ( md , srcu_idx ) ;
free_old_rq_tio ( tio ) ;
return NULL ;
}
}
dm_put_live_table ( md , srcu_idx ) ;
return tio ;
}
/*
* Called with the queue lock held .
*/
static int dm_old_prep_fn ( struct request_queue * q , struct request * rq )
{
struct mapped_device * md = q - > queuedata ;
struct dm_rq_target_io * tio ;
if ( unlikely ( rq - > special ) ) {
DMWARN ( " Already has something in rq->special. " ) ;
return BLKPREP_KILL ;
}
tio = dm_old_prep_tio ( rq , md , GFP_ATOMIC ) ;
if ( ! tio )
return BLKPREP_DEFER ;
rq - > special = tio ;
rq - > rq_flags | = RQF_DONTPREP ;
return BLKPREP_OK ;
}
/*
* Returns :
* DM_MAPIO_ * : the request has been processed as indicated
@ -617,31 +470,18 @@ static int map_request(struct dm_rq_target_io *tio)
struct request * rq = tio - > orig ;
struct request * clone = NULL ;
if ( tio - > clone ) {
clone = tio - > clone ;
r = ti - > type - > map_rq ( ti , clone , & tio - > info ) ;
if ( r = = DM_MAPIO_DELAY_REQUEUE )
return DM_MAPIO_REQUEUE ; /* .request_fn requeue is always immediate */
} else {
r = ti - > type - > clone_and_map_rq ( ti , rq , & tio - > info , & clone ) ;
if ( r < 0 ) {
/* The target wants to complete the I/O */
dm_kill_unmapped_request ( rq , r ) ;
return r ;
}
if ( r = = DM_MAPIO_REMAPPED & &
setup_clone ( clone , rq , tio , GFP_ATOMIC ) ) {
/* -ENOMEM */
ti - > type - > release_clone_rq ( clone ) ;
return DM_MAPIO_REQUEUE ;
}
}
r = ti - > type - > clone_and_map_rq ( ti , rq , & tio - > info , & clone ) ;
switch ( r ) {
case DM_MAPIO_SUBMITTED :
/* The target has taken the I/O to submit by itself later */
break ;
case DM_MAPIO_REMAPPED :
if ( setup_clone ( clone , rq , tio , GFP_ATOMIC ) ) {
/* -ENOMEM */
ti - > type - > release_clone_rq ( clone ) ;
return DM_MAPIO_REQUEUE ;
}
/* The target has remapped the I/O so dispatch it */
trace_block_rq_remap ( clone - > q , clone , disk_devt ( dm_disk ( md ) ) ,
blk_rq_pos ( rq ) ) ;
@ -700,6 +540,29 @@ static void dm_start_request(struct mapped_device *md, struct request *orig)
dm_get ( md ) ;
}
static int __dm_rq_init_rq ( struct mapped_device * md , struct request * rq )
{
struct dm_rq_target_io * tio = blk_mq_rq_to_pdu ( rq ) ;
/*
* Must initialize md member of tio , otherwise it won ' t
* be available in dm_mq_queue_rq .
*/
tio - > md = md ;
if ( md - > init_tio_pdu ) {
/* target-specific per-io data is immediately after the tio */
tio - > info . ptr = tio + 1 ;
}
return 0 ;
}
static int dm_rq_init_rq ( struct request_queue * q , struct request * rq , gfp_t gfp )
{
return __dm_rq_init_rq ( q - > rq_alloc_data , rq ) ;
}
static void map_tio_request ( struct kthread_work * work )
{
struct dm_rq_target_io * tio = container_of ( work , struct dm_rq_target_io , work ) ;
@ -794,6 +657,7 @@ static void dm_old_request_fn(struct request_queue *q)
dm_start_request ( md , rq ) ;
tio = tio_from_request ( rq ) ;
init_tio ( tio , rq , md ) ;
/* Establish tio->ti before queuing work (map_tio_request) */
tio - > ti = ti ;
kthread_queue_work ( & md - > kworker , & tio - > work ) ;
@ -804,10 +668,22 @@ static void dm_old_request_fn(struct request_queue *q)
/*
* Fully initialize a . request_fn request - based queue .
*/
int dm_old_init_request_queue ( struct mapped_device * md )
int dm_old_init_request_queue ( struct mapped_device * md , struct dm_table * t )
{
struct dm_target * immutable_tgt ;
/* Fully initialize the queue */
md - > queue - > cmd_size = sizeof ( struct dm_rq_target_io ) ;
md - > queue - > rq_alloc_data = md ;
md - > queue - > request_fn = dm_old_request_fn ;
md - > queue - > init_rq_fn = dm_rq_init_rq ;
immutable_tgt = dm_table_get_immutable_target ( t ) ;
if ( immutable_tgt & & immutable_tgt - > per_io_data_size ) {
/* any target-specific per-io data is immediately after the tio */
md - > queue - > cmd_size + = immutable_tgt - > per_io_data_size ;
md - > init_tio_pdu = true ;
}
if ( blk_init_allocated_queue ( md - > queue ) < 0 )
return - EINVAL ;
@ -816,7 +692,6 @@ int dm_old_init_request_queue(struct mapped_device *md)
dm_init_normal_md_queue ( md ) ;
blk_queue_softirq_done ( md - > queue , dm_softirq_done ) ;
blk_queue_prep_rq ( md - > queue , dm_old_prep_fn ) ;
/* Initialize the request-based DM worker thread */
kthread_init_worker ( & md - > kworker ) ;
@ -837,21 +712,7 @@ static int dm_mq_init_request(void *data, struct request *rq,
unsigned int hctx_idx , unsigned int request_idx ,
unsigned int numa_node )
{
struct mapped_device * md = data ;
struct dm_rq_target_io * tio = blk_mq_rq_to_pdu ( rq ) ;
/*
* Must initialize md member of tio , otherwise it won ' t
* be available in dm_mq_queue_rq .
*/
tio - > md = md ;
if ( md - > init_tio_pdu ) {
/* target-specific per-io data is immediately after the tio */
tio - > info . ptr = tio + 1 ;
}
return 0 ;
return __dm_rq_init_rq ( data , rq ) ;
}
static int dm_mq_queue_rq ( struct blk_mq_hw_ctx * hctx ,