Re: [PATCH 03/10] block: Micro-optimize get_max_segment_size()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Oct 19, 2022 at 03:23:17PM -0700, Bart Van Assche wrote:
> This patch removes a conditional jump from get_max_segment_size(). The
> x86-64 assembler code for this function without this patch is as follows:
> 
> 206             return min_not_zero(mask - offset + 1,
>    0x0000000000000118 <+72>:    not    %rax
>    0x000000000000011b <+75>:    and    0x8(%r10),%rax
>    0x000000000000011f <+79>:    add    $0x1,%rax
>    0x0000000000000123 <+83>:    je     0x138 <bvec_split_segs+104>
>    0x0000000000000125 <+85>:    cmp    %rdx,%rax
>    0x0000000000000128 <+88>:    mov    %rdx,%r12
>    0x000000000000012b <+91>:    cmovbe %rax,%r12
>    0x000000000000012f <+95>:    test   %rdx,%rdx
>    0x0000000000000132 <+98>:    mov    %eax,%edx
>    0x0000000000000134 <+100>:   cmovne %r12d,%edx
> 
> With this patch applied:
> 
> 206             return min(mask - offset, (unsigned long)lim->max_segment_size - 1) + 1;
>    0x000000000000003f <+63>:    mov    0x28(%rdi),%ebp
>    0x0000000000000042 <+66>:    not    %rax
>    0x0000000000000045 <+69>:    and    0x8(%rdi),%rax
>    0x0000000000000049 <+73>:    sub    $0x1,%rbp
>    0x000000000000004d <+77>:    cmp    %rbp,%rax
>    0x0000000000000050 <+80>:    cmova  %rbp,%rax
>    0x0000000000000054 <+84>:    add    $0x1,%eax
> 
> Cc: Ming Lei <ming.lei@xxxxxxxxxx>
> Cc: Christoph Hellwig <hch@xxxxxx>
> Cc: Keith Busch <kbusch@xxxxxxxxxx>
> Cc: Steven Rostedt <rostedt@xxxxxxxxxxx>
> Cc: Guenter Roeck <linux@xxxxxxxxxxxx>
> Signed-off-by: Bart Van Assche <bvanassche@xxxxxxx>
> ---
>  block/blk-merge.c | 15 +++++++++++----
>  1 file changed, 11 insertions(+), 4 deletions(-)
> 
> diff --git a/block/blk-merge.c b/block/blk-merge.c
> index 58fdc3f8905b..35a8f75cc45d 100644
> --- a/block/blk-merge.c
> +++ b/block/blk-merge.c
> @@ -186,6 +186,14 @@ static inline unsigned get_max_io_size(struct bio *bio,
>  	return max_sectors & ~(lbs - 1);
>  }
>  
> +/**
> + * get_max_segment_size() - maximum number of bytes to add as a single segment
> + * @lim: Request queue limits.
> + * @start_page: See below.
> + * @offset: Offset from @start_page where to add a segment.
> + *
> + * Returns the maximum number of bytes that can be added as a single segment.
> + */
>  static inline unsigned get_max_segment_size(const struct queue_limits *lim,
>  		struct page *start_page, unsigned long offset)
>  {
> @@ -194,11 +202,10 @@ static inline unsigned get_max_segment_size(const struct queue_limits *lim,
>  	offset = mask & (page_to_phys(start_page) + offset);
>  
>  	/*
> -	 * overflow may be triggered in case of zero page physical address
> -	 * on 32bit arch, use queue's max segment size when that happens.
> +	 * Prevent an overflow if mask = ULONG_MAX and offset = 0 by adding 1
> +	 * after having calculated the minimum.
>  	 */
> -	return min_not_zero(mask - offset + 1,
> -			(unsigned long)lim->max_segment_size);
> +	return min(mask - offset, (unsigned long)lim->max_segment_size - 1) + 1;
>  }

Looks fine,

Reviewed-by: Ming Lei <ming.lei@xxxxxxxxxx>


Thanks,
Ming




[Index of Archives]     [Linux RAID]     [Linux SCSI]     [Linux ATA RAID]     [IDE]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Device Mapper]

  Powered by Linux