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 <dgilb...@interlog.com>
> ---
>  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
h...@suse.de                                   +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)

Reply via email to