2008-01-29 16:04:06 +03:00
/*
* Functions related to segment and merge handling
*/
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/bio.h>
# include <linux/blkdev.h>
# include <linux/scatterlist.h>
# include "blk.h"
2009-02-23 11:03:10 +03:00
static unsigned int __blk_recalc_rq_segments ( struct request_queue * q ,
2009-03-06 10:55:24 +03:00
struct bio * bio )
2008-01-29 16:04:06 +03:00
{
2013-11-24 05:19:00 +04:00
struct bio_vec bv , bvprv = { NULL } ;
int cluster , high , highprv = 1 ;
2009-02-23 11:03:10 +03:00
unsigned int seg_size , nr_phys_segs ;
2009-03-06 10:55:24 +03:00
struct bio * fbio , * bbio ;
2013-11-24 05:19:00 +04:00
struct bvec_iter iter ;
2008-01-29 16:04:06 +03:00
2009-02-23 11:03:10 +03:00
if ( ! bio )
return 0 ;
2008-01-29 16:04:06 +03:00
2014-02-08 00:53:46 +04:00
/*
* This should probably be returning 0 , but blk_add_request_payload ( )
* ( Christoph ! ! ! ! )
*/
if ( bio - > bi_rw & REQ_DISCARD )
return 1 ;
if ( bio - > bi_rw & REQ_WRITE_SAME )
return 1 ;
2009-02-23 11:03:10 +03:00
fbio = bio ;
2010-12-01 21:41:49 +03:00
cluster = blk_queue_cluster ( q ) ;
2008-08-15 12:20:02 +04:00
seg_size = 0 ;
2010-06-21 13:02:47 +04:00
nr_phys_segs = 0 ;
2009-02-23 11:03:10 +03:00
for_each_bio ( bio ) {
2013-11-24 05:19:00 +04:00
bio_for_each_segment ( bv , bio , iter ) {
2009-02-23 11:03:10 +03:00
/*
* the trick here is making sure that a high page is
* never considered part of another segment , since that
* might change with the bounce page .
*/
2013-11-24 05:19:00 +04:00
high = page_to_pfn ( bv . bv_page ) > queue_bounce_pfn ( q ) ;
if ( ! high & & ! highprv & & cluster ) {
if ( seg_size + bv . bv_len
2009-05-23 01:17:50 +04:00
> queue_max_segment_size ( q ) )
2009-02-23 11:03:10 +03:00
goto new_segment ;
2013-11-24 05:19:00 +04:00
if ( ! BIOVEC_PHYS_MERGEABLE ( & bvprv , & bv ) )
2009-02-23 11:03:10 +03:00
goto new_segment ;
2013-11-24 05:19:00 +04:00
if ( ! BIOVEC_SEG_BOUNDARY ( q , & bvprv , & bv ) )
2009-02-23 11:03:10 +03:00
goto new_segment ;
2008-01-29 16:04:06 +03:00
2013-11-24 05:19:00 +04:00
seg_size + = bv . bv_len ;
2009-02-23 11:03:10 +03:00
bvprv = bv ;
continue ;
}
2008-01-29 16:04:06 +03:00
new_segment :
2009-02-23 11:03:10 +03:00
if ( nr_phys_segs = = 1 & & seg_size >
fbio - > bi_seg_front_size )
fbio - > bi_seg_front_size = seg_size ;
2008-10-13 16:19:05 +04:00
2009-02-23 11:03:10 +03:00
nr_phys_segs + + ;
bvprv = bv ;
2013-11-24 05:19:00 +04:00
seg_size = bv . bv_len ;
2009-02-23 11:03:10 +03:00
highprv = high ;
}
2009-03-06 10:55:24 +03:00
bbio = bio ;
2008-01-29 16:04:06 +03:00
}
2009-03-06 10:55:24 +03:00
if ( nr_phys_segs = = 1 & & seg_size > fbio - > bi_seg_front_size )
fbio - > bi_seg_front_size = seg_size ;
if ( seg_size > bbio - > bi_seg_back_size )
bbio - > bi_seg_back_size = seg_size ;
2009-02-23 11:03:10 +03:00
return nr_phys_segs ;
}
void blk_recalc_rq_segments ( struct request * rq )
{
2009-03-06 10:55:24 +03:00
rq - > nr_phys_segments = __blk_recalc_rq_segments ( rq - > q , rq - > bio ) ;
2008-01-29 16:04:06 +03:00
}
void blk_recount_segments ( struct request_queue * q , struct bio * bio )
{
struct bio * nxt = bio - > bi_next ;
2009-02-23 11:03:10 +03:00
2008-01-29 16:04:06 +03:00
bio - > bi_next = NULL ;
2009-03-06 10:55:24 +03:00
bio - > bi_phys_segments = __blk_recalc_rq_segments ( q , bio ) ;
2008-01-29 16:04:06 +03:00
bio - > bi_next = nxt ;
bio - > bi_flags | = ( 1 < < BIO_SEG_VALID ) ;
}
EXPORT_SYMBOL ( blk_recount_segments ) ;
static int blk_phys_contig_segment ( struct request_queue * q , struct bio * bio ,
struct bio * nxt )
{
2013-12-04 01:29:09 +04:00
struct bio_vec end_bv = { NULL } , nxt_bv ;
2013-08-08 01:30:33 +04:00
struct bvec_iter iter ;
2010-12-01 21:41:49 +03:00
if ( ! blk_queue_cluster ( q ) )
2008-01-29 16:04:06 +03:00
return 0 ;
2008-10-13 16:19:05 +04:00
if ( bio - > bi_seg_back_size + nxt - > bi_seg_front_size >
2009-05-23 01:17:50 +04:00
queue_max_segment_size ( q ) )
2008-01-29 16:04:06 +03:00
return 0 ;
2008-08-09 19:42:20 +04:00
if ( ! bio_has_data ( bio ) )
return 1 ;
2013-08-08 01:30:33 +04:00
bio_for_each_segment ( end_bv , bio , iter )
if ( end_bv . bv_len = = iter . bi_size )
break ;
nxt_bv = bio_iovec ( nxt ) ;
if ( ! BIOVEC_PHYS_MERGEABLE ( & end_bv , & nxt_bv ) )
2008-08-09 19:42:20 +04:00
return 0 ;
2008-01-29 16:04:06 +03:00
/*
2008-08-09 19:42:20 +04:00
* bio and nxt are contiguous in memory ; check if the queue allows
2008-01-29 16:04:06 +03:00
* these two to be merged into one
*/
2013-08-08 01:30:33 +04:00
if ( BIOVEC_SEG_BOUNDARY ( q , & end_bv , & nxt_bv ) )
2008-01-29 16:04:06 +03:00
return 1 ;
return 0 ;
}
2013-11-24 05:19:00 +04:00
static inline void
2012-08-03 01:42:03 +04:00
__blk_segment_map_sg ( struct request_queue * q , struct bio_vec * bvec ,
2013-11-24 05:19:00 +04:00
struct scatterlist * sglist , struct bio_vec * bvprv ,
2012-08-03 01:42:03 +04:00
struct scatterlist * * sg , int * nsegs , int * cluster )
{
int nbytes = bvec - > bv_len ;
2013-11-24 05:19:00 +04:00
if ( * sg & & * cluster ) {
2012-08-03 01:42:03 +04:00
if ( ( * sg ) - > length + nbytes > queue_max_segment_size ( q ) )
goto new_segment ;
2013-11-24 05:19:00 +04:00
if ( ! BIOVEC_PHYS_MERGEABLE ( bvprv , bvec ) )
2012-08-03 01:42:03 +04:00
goto new_segment ;
2013-11-24 05:19:00 +04:00
if ( ! BIOVEC_SEG_BOUNDARY ( q , bvprv , bvec ) )
2012-08-03 01:42:03 +04:00
goto new_segment ;
( * sg ) - > length + = nbytes ;
} else {
new_segment :
if ( ! * sg )
* sg = sglist ;
else {
/*
* If the driver previously mapped a shorter
* list , we could see a termination bit
* prematurely unless it fully inits the sg
* table on each mapping . We KNOW that there
* must be more entries here or the driver
* would be buggy , so force clear the
* termination bit to avoid doing a full
* sg_init_table ( ) in drivers for each command .
*/
2013-03-20 09:07:08 +04:00
sg_unmark_end ( * sg ) ;
2012-08-03 01:42:03 +04:00
* sg = sg_next ( * sg ) ;
}
sg_set_page ( * sg , bvec - > bv_page , nbytes , bvec - > bv_offset ) ;
( * nsegs ) + + ;
}
2013-11-24 05:19:00 +04:00
* bvprv = * bvec ;
2012-08-03 01:42:03 +04:00
}
2014-02-08 00:53:46 +04:00
static int __blk_bios_map_sg ( struct request_queue * q , struct bio * bio ,
struct scatterlist * sglist ,
struct scatterlist * * sg )
2008-01-29 16:04:06 +03:00
{
2013-12-04 01:29:09 +04:00
struct bio_vec bvec , bvprv = { NULL } ;
2014-02-08 00:53:46 +04:00
struct bvec_iter iter ;
2008-01-29 16:04:06 +03:00
int nsegs , cluster ;
nsegs = 0 ;
2010-12-01 21:41:49 +03:00
cluster = blk_queue_cluster ( q ) ;
2008-01-29 16:04:06 +03:00
2014-02-08 00:53:46 +04:00
if ( bio - > bi_rw & REQ_DISCARD ) {
/*
* This is a hack - drivers should be neither modifying the
* biovec , nor relying on bi_vcnt - but because of
* blk_add_request_payload ( ) , a discard bio may or may not have
* a payload we need to set up here ( thank you Christoph ) and
* bi_vcnt is really the only way of telling if we need to .
*/
if ( bio - > bi_vcnt )
goto single_segment ;
return 0 ;
}
if ( bio - > bi_rw & REQ_WRITE_SAME ) {
single_segment :
* sg = sglist ;
bvec = bio_iovec ( bio ) ;
sg_set_page ( * sg , bvec . bv_page , bvec . bv_len , bvec . bv_offset ) ;
return 1 ;
}
for_each_bio ( bio )
bio_for_each_segment ( bvec , bio , iter )
__blk_segment_map_sg ( q , & bvec , sglist , & bvprv , sg ,
& nsegs , & cluster ) ;
2008-01-29 16:04:06 +03:00
2014-02-08 00:53:46 +04:00
return nsegs ;
}
/*
* map a request to scatterlist , return number of sg entries setup . Caller
* must make sure sg can hold rq - > nr_phys_segments entries
*/
int blk_rq_map_sg ( struct request_queue * q , struct request * rq ,
struct scatterlist * sglist )
{
struct scatterlist * sg = NULL ;
int nsegs = 0 ;
if ( rq - > bio )
nsegs = __blk_bios_map_sg ( q , rq - > bio , sglist , & sg ) ;
2008-04-11 14:56:52 +04:00
if ( unlikely ( rq - > cmd_flags & REQ_COPY_USER ) & &
2009-05-07 17:24:41 +04:00
( blk_rq_bytes ( rq ) & q - > dma_pad_mask ) ) {
unsigned int pad_len =
( q - > dma_pad_mask & ~ blk_rq_bytes ( rq ) ) + 1 ;
2008-04-11 14:56:52 +04:00
sg - > length + = pad_len ;
rq - > extra_len + = pad_len ;
}
2008-02-19 13:36:53 +03:00
if ( q - > dma_drain_size & & q - > dma_drain_needed ( rq ) ) {
2010-08-07 20:20:39 +04:00
if ( rq - > cmd_flags & REQ_WRITE )
2008-02-19 13:36:55 +03:00
memset ( q - > dma_drain_buffer , 0 , q - > dma_drain_size ) ;
2008-01-29 16:04:06 +03:00
sg - > page_link & = ~ 0x02 ;
sg = sg_next ( sg ) ;
sg_set_page ( sg , virt_to_page ( q - > dma_drain_buffer ) ,
q - > dma_drain_size ,
( ( unsigned long ) q - > dma_drain_buffer ) &
( PAGE_SIZE - 1 ) ) ;
nsegs + + ;
2008-03-04 13:17:11 +03:00
rq - > extra_len + = q - > dma_drain_size ;
2008-01-29 16:04:06 +03:00
}
if ( sg )
sg_mark_end ( sg ) ;
return nsegs ;
}
EXPORT_SYMBOL ( blk_rq_map_sg ) ;
2012-08-03 01:42:04 +04:00
/**
* blk_bio_map_sg - map a bio to a scatterlist
* @ q : request_queue in question
* @ bio : bio being mapped
* @ sglist : scatterlist being mapped
*
* Note :
* Caller must make sure sg can hold bio - > bi_phys_segments entries
*
* Will return the number of sg entries setup
*/
int blk_bio_map_sg ( struct request_queue * q , struct bio * bio ,
struct scatterlist * sglist )
{
2014-02-08 00:53:46 +04:00
struct scatterlist * sg = NULL ;
int nsegs ;
struct bio * next = bio - > bi_next ;
bio - > bi_next = NULL ;
2012-08-03 01:42:04 +04:00
2014-02-08 00:53:46 +04:00
nsegs = __blk_bios_map_sg ( q , bio , sglist , & sg ) ;
bio - > bi_next = next ;
2012-08-03 01:42:04 +04:00
if ( sg )
sg_mark_end ( sg ) ;
BUG_ON ( bio - > bi_phys_segments & & nsegs > bio - > bi_phys_segments ) ;
return nsegs ;
}
EXPORT_SYMBOL ( blk_bio_map_sg ) ;
2008-01-29 16:04:06 +03:00
static inline int ll_new_hw_segment ( struct request_queue * q ,
struct request * req ,
struct bio * bio )
{
int nr_phys_segs = bio_phys_segments ( q , bio ) ;
2010-09-10 22:50:10 +04:00
if ( req - > nr_phys_segments + nr_phys_segs > queue_max_segments ( q ) )
goto no_merge ;
if ( bio_integrity ( bio ) & & blk_integrity_merge_bio ( q , req , bio ) )
goto no_merge ;
2008-01-29 16:04:06 +03:00
/*
* This will form the start of a new hw segment . Bump both
* counters .
*/
req - > nr_phys_segments + = nr_phys_segs ;
return 1 ;
2010-09-10 22:50:10 +04:00
no_merge :
req - > cmd_flags | = REQ_NOMERGE ;
if ( req = = q - > last_merge )
q - > last_merge = NULL ;
return 0 ;
2008-01-29 16:04:06 +03:00
}
int ll_back_merge_fn ( struct request_queue * q , struct request * req ,
struct bio * bio )
{
2012-09-18 20:19:26 +04:00
if ( blk_rq_sectors ( req ) + bio_sectors ( bio ) >
blk_rq_get_max_sectors ( req ) ) {
2008-01-29 16:04:06 +03:00
req - > cmd_flags | = REQ_NOMERGE ;
if ( req = = q - > last_merge )
q - > last_merge = NULL ;
return 0 ;
}
2008-05-07 11:33:55 +04:00
if ( ! bio_flagged ( req - > biotail , BIO_SEG_VALID ) )
2008-01-29 16:04:06 +03:00
blk_recount_segments ( q , req - > biotail ) ;
2008-05-07 11:33:55 +04:00
if ( ! bio_flagged ( bio , BIO_SEG_VALID ) )
2008-01-29 16:04:06 +03:00
blk_recount_segments ( q , bio ) ;
return ll_new_hw_segment ( q , req , bio ) ;
}
2008-01-31 15:03:55 +03:00
int ll_front_merge_fn ( struct request_queue * q , struct request * req ,
2008-01-29 16:04:06 +03:00
struct bio * bio )
{
2012-09-18 20:19:26 +04:00
if ( blk_rq_sectors ( req ) + bio_sectors ( bio ) >
blk_rq_get_max_sectors ( req ) ) {
2008-01-29 16:04:06 +03:00
req - > cmd_flags | = REQ_NOMERGE ;
if ( req = = q - > last_merge )
q - > last_merge = NULL ;
return 0 ;
}
2008-05-07 11:33:55 +04:00
if ( ! bio_flagged ( bio , BIO_SEG_VALID ) )
2008-01-29 16:04:06 +03:00
blk_recount_segments ( q , bio ) ;
2008-05-07 11:33:55 +04:00
if ( ! bio_flagged ( req - > bio , BIO_SEG_VALID ) )
2008-01-29 16:04:06 +03:00
blk_recount_segments ( q , req - > bio ) ;
return ll_new_hw_segment ( q , req , bio ) ;
}
2013-10-29 22:11:47 +04:00
/*
* blk - mq uses req - > special to carry normal driver per - request payload , it
* does not indicate a prepared command that we cannot merge with .
*/
static bool req_no_special_merge ( struct request * req )
{
struct request_queue * q = req - > q ;
return ! q - > mq_ops & & req - > special ;
}
2008-01-29 16:04:06 +03:00
static int ll_merge_requests_fn ( struct request_queue * q , struct request * req ,
struct request * next )
{
int total_phys_segments ;
2008-10-13 16:19:05 +04:00
unsigned int seg_size =
req - > biotail - > bi_seg_back_size + next - > bio - > bi_seg_front_size ;
2008-01-29 16:04:06 +03:00
/*
* First check if the either of the requests are re - queued
* requests . Can ' t merge them if they are .
*/
2013-10-29 22:11:47 +04:00
if ( req_no_special_merge ( req ) | | req_no_special_merge ( next ) )
2008-01-29 16:04:06 +03:00
return 0 ;
/*
* Will it become too large ?
*/
2012-09-18 20:19:26 +04:00
if ( ( blk_rq_sectors ( req ) + blk_rq_sectors ( next ) ) >
blk_rq_get_max_sectors ( req ) )
2008-01-29 16:04:06 +03:00
return 0 ;
total_phys_segments = req - > nr_phys_segments + next - > nr_phys_segments ;
2008-10-13 16:19:05 +04:00
if ( blk_phys_contig_segment ( q , req - > biotail , next - > bio ) ) {
if ( req - > nr_phys_segments = = 1 )
req - > bio - > bi_seg_front_size = seg_size ;
if ( next - > nr_phys_segments = = 1 )
next - > biotail - > bi_seg_back_size = seg_size ;
2008-01-29 16:04:06 +03:00
total_phys_segments - - ;
2008-10-13 16:19:05 +04:00
}
2008-01-29 16:04:06 +03:00
2010-02-26 08:20:39 +03:00
if ( total_phys_segments > queue_max_segments ( q ) )
2008-01-29 16:04:06 +03:00
return 0 ;
2010-09-10 22:50:10 +04:00
if ( blk_integrity_rq ( req ) & & blk_integrity_merge_rq ( q , req , next ) )
return 0 ;
2008-01-29 16:04:06 +03:00
/* Merge is OK... */
req - > nr_phys_segments = total_phys_segments ;
return 1 ;
}
2009-07-03 12:48:17 +04:00
/**
* blk_rq_set_mixed_merge - mark a request as mixed merge
* @ rq : request to mark as mixed merge
*
* Description :
* @ rq is about to be mixed merged . Make sure the attributes
* which can be mixed are set in each bio and mark @ rq as mixed
* merged .
*/
void blk_rq_set_mixed_merge ( struct request * rq )
{
unsigned int ff = rq - > cmd_flags & REQ_FAILFAST_MASK ;
struct bio * bio ;
if ( rq - > cmd_flags & REQ_MIXED_MERGE )
return ;
/*
* @ rq will no longer represent mixable attributes for all the
* contained bios . It will just track those of the first one .
* Distributes the attributs to each bio .
*/
for ( bio = rq - > bio ; bio ; bio = bio - > bi_next ) {
WARN_ON_ONCE ( ( bio - > bi_rw & REQ_FAILFAST_MASK ) & &
( bio - > bi_rw & REQ_FAILFAST_MASK ) ! = ff ) ;
bio - > bi_rw | = ff ;
}
rq - > cmd_flags | = REQ_MIXED_MERGE ;
}
2009-03-27 12:31:51 +03:00
static void blk_account_io_merge ( struct request * req )
{
if ( blk_do_io_stat ( req ) ) {
struct hd_struct * part ;
int cpu ;
cpu = part_stat_lock ( ) ;
2011-01-05 18:57:38 +03:00
part = req - > part ;
2009-03-27 12:31:51 +03:00
part_round_stats ( cpu , part ) ;
block: Seperate read and write statistics of in_flight requests v2
Commit a9327cac440be4d8333bba975cbbf76045096275 added seperate read
and write statistics of in_flight requests. And exported the number
of read and write requests in progress seperately through sysfs.
But Corrado Zoccolo <czoccolo@gmail.com> reported getting strange
output from "iostat -kx 2". Global values for service time and
utilization were garbage. For interval values, utilization was always
100%, and service time is higher than normal.
So this was reverted by commit 0f78ab9899e9d6acb09d5465def618704255963b
The problem was in part_round_stats_single(), I missed the following:
if (now == part->stamp)
return;
- if (part->in_flight) {
+ if (part_in_flight(part)) {
__part_stat_add(cpu, part, time_in_queue,
part_in_flight(part) * (now - part->stamp));
__part_stat_add(cpu, part, io_ticks, (now - part->stamp));
With this chunk included, the reported regression gets fixed.
Signed-off-by: Nikanth Karthikesan <knikanth@suse.de>
--
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
2009-10-06 22:16:55 +04:00
part_dec_in_flight ( part , rq_data_dir ( req ) ) ;
2009-03-27 12:31:51 +03:00
2011-01-07 10:43:37 +03:00
hd_struct_put ( part ) ;
2009-03-27 12:31:51 +03:00
part_stat_unlock ( ) ;
}
}
2008-01-29 16:04:06 +03:00
/*
* Has to be called with the request spinlock acquired
*/
static int attempt_merge ( struct request_queue * q , struct request * req ,
struct request * next )
{
if ( ! rq_mergeable ( req ) | | ! rq_mergeable ( next ) )
return 0 ;
2012-09-18 20:19:26 +04:00
if ( ! blk_check_merge_flags ( req - > cmd_flags , next - > cmd_flags ) )
return 0 ;
2008-01-29 16:04:06 +03:00
/*
* not contiguous
*/
2009-05-07 17:24:39 +04:00
if ( blk_rq_pos ( req ) + blk_rq_sectors ( req ) ! = blk_rq_pos ( next ) )
2008-01-29 16:04:06 +03:00
return 0 ;
if ( rq_data_dir ( req ) ! = rq_data_dir ( next )
| | req - > rq_disk ! = next - > rq_disk
2013-10-29 22:11:47 +04:00
| | req_no_special_merge ( next ) )
2008-01-29 16:04:06 +03:00
return 0 ;
2012-09-18 20:19:27 +04:00
if ( req - > cmd_flags & REQ_WRITE_SAME & &
! blk_write_same_mergeable ( req - > bio , next - > bio ) )
return 0 ;
2008-01-29 16:04:06 +03:00
/*
* If we are allowed to merge , then append bio list
* from next to rq and release next . merge_requests_fn
* will have updated segment counts , update sector
* counts here .
*/
if ( ! ll_merge_requests_fn ( q , req , next ) )
return 0 ;
2009-07-03 12:48:17 +04:00
/*
* If failfast settings disagree or any of the two is already
* a mixed merge , mark both as mixed before proceeding . This
* makes sure that all involved bios have mixable attributes
* set properly .
*/
if ( ( req - > cmd_flags | next - > cmd_flags ) & REQ_MIXED_MERGE | |
( req - > cmd_flags & REQ_FAILFAST_MASK ) ! =
( next - > cmd_flags & REQ_FAILFAST_MASK ) ) {
blk_rq_set_mixed_merge ( req ) ;
blk_rq_set_mixed_merge ( next ) ;
}
2008-01-29 16:04:06 +03:00
/*
* At this point we have either done a back merge
* or front merge . We need the smaller start_time of
* the merged requests to be the current request
* for accounting purposes .
*/
if ( time_after ( req - > start_time , next - > start_time ) )
req - > start_time = next - > start_time ;
req - > biotail - > bi_next = next - > bio ;
req - > biotail = next - > biotail ;
2009-05-07 17:24:44 +04:00
req - > __data_len + = blk_rq_bytes ( next ) ;
2008-01-29 16:04:06 +03:00
elv_merge_requests ( q , req , next ) ;
2009-04-22 16:01:49 +04:00
/*
* ' next ' is going away , so update stats accordingly
*/
blk_account_io_merge ( next ) ;
2008-01-29 16:04:06 +03:00
req - > ioprio = ioprio_best ( req - > ioprio , next - > ioprio ) ;
2008-08-26 12:25:02 +04:00
if ( blk_rq_cpu_valid ( next ) )
req - > cpu = next - > cpu ;
2008-01-29 16:04:06 +03:00
2009-03-24 14:35:07 +03:00
/* owner-ship of bio passed from next to req */
next - > bio = NULL ;
2008-01-29 16:04:06 +03:00
__blk_put_request ( q , next ) ;
return 1 ;
}
int attempt_back_merge ( struct request_queue * q , struct request * rq )
{
struct request * next = elv_latter_request ( q , rq ) ;
if ( next )
return attempt_merge ( q , rq , next ) ;
return 0 ;
}
int attempt_front_merge ( struct request_queue * q , struct request * rq )
{
struct request * prev = elv_former_request ( q , rq ) ;
if ( prev )
return attempt_merge ( q , prev , rq ) ;
return 0 ;
}
2011-03-21 12:14:27 +03:00
int blk_attempt_req_merge ( struct request_queue * q , struct request * rq ,
struct request * next )
{
return attempt_merge ( q , rq , next ) ;
}
2012-02-08 12:19:38 +04:00
bool blk_rq_merge_ok ( struct request * rq , struct bio * bio )
{
2012-09-18 20:19:25 +04:00
if ( ! rq_mergeable ( rq ) | | ! bio_mergeable ( bio ) )
2012-02-08 12:19:38 +04:00
return false ;
2012-09-18 20:19:26 +04:00
if ( ! blk_check_merge_flags ( rq - > cmd_flags , bio - > bi_rw ) )
return false ;
2012-02-08 12:19:38 +04:00
/* different data direction or already started, don't merge */
if ( bio_data_dir ( bio ) ! = rq_data_dir ( rq ) )
return false ;
/* must be same device and not a special request */
2013-10-29 22:11:47 +04:00
if ( rq - > rq_disk ! = bio - > bi_bdev - > bd_disk | | req_no_special_merge ( rq ) )
2012-02-08 12:19:38 +04:00
return false ;
/* only merge integrity protected bio into ditto rq */
if ( bio_integrity ( bio ) ! = blk_integrity_rq ( rq ) )
return false ;
2012-09-18 20:19:27 +04:00
/* must be using the same buffer */
if ( rq - > cmd_flags & REQ_WRITE_SAME & &
! blk_write_same_mergeable ( rq - > bio , bio ) )
return false ;
2012-02-08 12:19:38 +04:00
return true ;
}
int blk_try_merge ( struct request * rq , struct bio * bio )
{
2013-10-12 02:44:27 +04:00
if ( blk_rq_pos ( rq ) + blk_rq_sectors ( rq ) = = bio - > bi_iter . bi_sector )
2012-02-08 12:19:38 +04:00
return ELEVATOR_BACK_MERGE ;
2013-10-12 02:44:27 +04:00
else if ( blk_rq_pos ( rq ) - bio_sectors ( bio ) = = bio - > bi_iter . bi_sector )
2012-02-08 12:19:38 +04:00
return ELEVATOR_FRONT_MERGE ;
return ELEVATOR_NO_MERGE ;
}