ACK: [SRU][Xenial][PATCH 1/1] block: fix bio_will_gap() for first bvec with offset

Sultan Alsawaf sultan.alsawaf at canonical.com
Thu Mar 26 20:13:20 UTC 2020


Looks good and doesn't have a subsequent 'Fixes' commit in upstream.

Acked-by: Sultan Alsawaf <sultan.alsawaf at canonical.com>

On Thu, Mar 26, 2020 at 03:27:36PM -0300, Heitor Alves de Siqueira wrote:
> From: Ming Lei <ming.lei at redhat.com>
> 
> BugLink: https://bugs.launchpad.net/bugs/1869229
> 
> Commit 729204ef49ec("block: relax check on sg gap") allows us to merge
> bios, if both are physically contiguous.  This change can merge a huge
> number of small bios, through mkfs for example, mkfs.ntfs running time
> can be decreased to ~1/10.
> 
> But if one rq starts with a non-aligned buffer (the 1st bvec's bv_offset
> is non-zero) and if we allow the merge, it is quite difficult to respect
> sg gap limit, especially the max segment size, or we risk having an
> unaligned virtual boundary.  This patch tries to avoid the issue by
> disallowing a merge, if the req starts with an unaligned buffer.
> 
> Also add comments to explain why the merged segment can't end in
> unaligned virt boundary.
> 
> Fixes: 729204ef49ec ("block: relax check on sg gap")
> Tested-by: Johannes Thumshirn <jthumshirn at suse.de>
> Reviewed-by: Johannes Thumshirn <jthumshirn at suse.de>
> Signed-off-by: Ming Lei <ming.lei at redhat.com>
> 
> Rewrote parts of the commit message and comments.
> 
> Signed-off-by: Jens Axboe <axboe at fb.com>
> (cherry picked from commit 5a8d75a1b8c99bdc926ba69b7b7dbe4fae81a5af)
> Signed-off-by: Matthew Ruffell <matthew.ruffell at canonical.com>
> Signed-off-by: Heitor Alves de Siqueira <halves at canonical.com>
> ---
>  include/linux/blkdev.h | 32 ++++++++++++++++++++++++++++----
>  1 file changed, 28 insertions(+), 4 deletions(-)
> 
> diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
> index 7548f332121a..01a696b0a4d3 100644
> --- a/include/linux/blkdev.h
> +++ b/include/linux/blkdev.h
> @@ -1672,12 +1672,36 @@ static inline bool bios_segs_mergeable(struct request_queue *q,
>  	return true;
>  }
>  
> -static inline bool bio_will_gap(struct request_queue *q, struct bio *prev,
> -			 struct bio *next)
> +static inline bool bio_will_gap(struct request_queue *q,
> +				struct request *prev_rq,
> +				struct bio *prev,
> +				struct bio *next)
>  {
>  	if (bio_has_data(prev) && queue_virt_boundary(q)) {
>  		struct bio_vec pb, nb;
>  
> +		/*
> +		 * don't merge if the 1st bio starts with non-zero
> +		 * offset, otherwise it is quite difficult to respect
> +		 * sg gap limit. We work hard to merge a huge number of small
> +		 * single bios in case of mkfs.
> +		 */
> +		if (prev_rq)
> +			bio_get_first_bvec(prev_rq->bio, &pb);
> +		else
> +			bio_get_first_bvec(prev, &pb);
> +		if (pb.bv_offset)
> +			return true;
> +
> +		/*
> +		 * We don't need to worry about the situation that the
> +		 * merged segment ends in unaligned virt boundary:
> +		 *
> +		 * - if 'pb' ends aligned, the merged segment ends aligned
> +		 * - if 'pb' ends unaligned, the next bio must include
> +		 *   one single bvec of 'nb', otherwise the 'nb' can't
> +		 *   merge with 'pb'
> +		 */
>  		bio_get_last_bvec(prev, &pb);
>  		bio_get_first_bvec(next, &nb);
>  
> @@ -1690,12 +1714,12 @@ static inline bool bio_will_gap(struct request_queue *q, struct bio *prev,
>  
>  static inline bool req_gap_back_merge(struct request *req, struct bio *bio)
>  {
> -	return bio_will_gap(req->q, req->biotail, bio);
> +	return bio_will_gap(req->q, req, req->biotail, bio);
>  }
>  
>  static inline bool req_gap_front_merge(struct request *req, struct bio *bio)
>  {
> -	return bio_will_gap(req->q, bio, req->bio);
> +	return bio_will_gap(req->q, NULL, bio, req->bio);
>  }
>  
>  int kblockd_schedule_work(struct work_struct *work);
> -- 
> 2.26.0
> 
> 
> -- 
> kernel-team mailing list
> kernel-team at lists.ubuntu.com
> https://lists.ubuntu.com/mailman/listinfo/kernel-team



More information about the kernel-team mailing list