Re: [PATCH v2.1] sd: Micro-optimize READ / WRITE CDB encoding

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

 



On 10/25/2017 05:52 AM, Douglas Gilbert wrote:
> The sd_setup_read_write_cmnd() function is on the "fast path" for
> block system access to SCSI devices (logical units). Rewrite this
> function to improve speed and readability:
>  - use put_unaligned_be family of functions to save lots of shifts
>  - improve the scaling code when sector_size > 512 bytes
>  - use variable names containing "sect" for block system quantities
>    which have implicit 512 byte sector size. Use "lba" and
>    "num_blks" after optional scaling to match the logical block
>    address and number of logical blocks of the SCSI device being
>    accessed
>  - use local variables to hold values that were previously calculated
>    more than once
> 
> Signed-off-by: Douglas Gilbert <dgilbert@xxxxxxxxxxxx>
> ---
>  drivers/scsi/sd.c | 216 ++++++++++++++++++++++++------------------------------
>  1 file changed, 94 insertions(+), 122 deletions(-)
> 
> diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
> index d175c5c5ccf8..618cb5d0f75a 100644
> --- a/drivers/scsi/sd.c
> +++ b/drivers/scsi/sd.c
> @@ -1004,11 +1004,18 @@ static int sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt)
>  	struct scsi_device *sdp = SCpnt->device;
>  	struct gendisk *disk = rq->rq_disk;
>  	struct scsi_disk *sdkp = scsi_disk(disk);
> -	sector_t block = blk_rq_pos(rq);
> -	sector_t threshold;
> -	unsigned int this_count = blk_rq_sectors(rq);
> +	unsigned int num_sects = blk_rq_sectors(rq);
> +	unsigned int num_blks;
>  	unsigned int dif, dix;
> -	bool zoned_write = sd_is_zoned(sdkp) && rq_data_dir(rq) == WRITE;
> +	unsigned int sect_sz;
> +	sector_t sect_addr = blk_rq_pos(rq);
> +	sector_t sect_after = sect_addr + num_sects;
> +	sector_t total_sects = get_capacity(disk);
> +	sector_t threshold_sect;
> +	sector_t lba;
> +	bool is_write = (rq_data_dir(rq) == WRITE);
> +	bool have_fua = !!(rq->cmd_flags & REQ_FUA);
> +	bool zoned_write = sd_is_zoned(sdkp) && is_write;
>  	int ret;
>  	unsigned char protect;
>  
> @@ -1029,20 +1036,23 @@ static int sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt)
>  
>  	SCSI_LOG_HLQUEUE(1,
>  		scmd_printk(KERN_INFO, SCpnt,
> -			"%s: block=%llu, count=%d\n",
> -			__func__, (unsigned long long)block, this_count));
> +			"%s: sector=%llu, num_sects=%d\n",
> +			__func__, (unsigned long long)sect_addr, num_sects));
>  
> -	if (!sdp || !scsi_device_online(sdp) ||
> -	    block + blk_rq_sectors(rq) > get_capacity(disk)) {
> +	if (likely(sdp && scsi_device_online(sdp) &&
> +		   (sect_after <= total_sects)))
> +		; /* ok: have device, its online and access fits on medium */
> +	else {
>  		SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt,
>  						"Finishing %u sectors\n",
> -						blk_rq_sectors(rq)));
> +						num_sects));
>  		SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt,
>  						"Retry with 0x%p\n", SCpnt));
>  		goto out;
>  	}
> +	sect_sz = sdp->sector_size;
>  
> -	if (sdp->changed) {
> +	if (unlikely(sdp->changed)) {
>  		/*
>  		 * quietly refuse to do anything to a changed disc until 
>  		 * the changed bit has been reset
Please invert the 'if' condition to avoid the empty branch.

> @@ -1055,21 +1065,22 @@ static int sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt)
>  	 * Some SD card readers can't handle multi-sector accesses which touch
>  	 * the last one or two hardware sectors.  Split accesses as needed.
>  	 */
> -	threshold = get_capacity(disk) - SD_LAST_BUGGY_SECTORS *
> -		(sdp->sector_size / 512);
> -
> -	if (unlikely(sdp->last_sector_bug && block + this_count > threshold)) {
> -		if (block < threshold) {
> -			/* Access up to the threshold but not beyond */
> -			this_count = threshold - block;
> -		} else {
> -			/* Access only a single hardware sector */
> -			this_count = sdp->sector_size / 512;
> -		}
> +	if (unlikely(sdp->last_sector_bug)) {
> +		threshold_sect = total_sects -
> +			    (SD_LAST_BUGGY_SECTORS * (sect_sz / 512));
> +
> +		if (unlikely(sect_after > threshold_sect))
> +			num_sects = (sect_addr < threshold_sect) ?
> +						(threshold_sect - sect_addr) :
> +						(sect_sz / 512);
> +			/* If LBA less than threshold then access up to the
> +			 * threshold but not beyond; otherwise access only
> +			 * a single hardware sector.
> +			 */
>  	}
>  
> -	SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, "block=%llu\n",
> -					(unsigned long long)block));
> +	SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, "num_sects=%llu\n",
> +					(unsigned long long)num_sects));
>  
>  	/*
>  	 * If we have a 1K hardware sectorsize, prevent access to single
Why did you change the log message?
I'd rather keep it as it were...

Cheers,

Hannes
-- 
-- 
Dr. Hannes Reinecke		   Teamlead Storage & Networking
hare@xxxxxxx			               +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: F. Imendörffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton
HRB 21284 (AG Nürnberg)



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]

  Powered by Linux