Re: [RFC PATCH 3/5] streamline REQ_OP_READ-WRITE access

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

 



On 2018/08/06 13:51, Douglas Gilbert wrote:
> Make the two block layer operations most frequently used (REQ_OP_READ
> and REQ_OP_WRITE) bypass the switch statements in the submission and
> response paths. Assume these two enums are 0 and 1 which allows a
> single comparison to select both of them. Check that assumption
> at driver start-up.

What about simply moving the REQ_OP_READ and REQ_OP_WRITE cases at the top of
the switch case list ? Since that gets (usually) compiled as a jump, the effect
should be the same, no ?

> 
> Signed-off-by: Douglas Gilbert <dgilbert@xxxxxxxxxxxx>
> ---
>  drivers/scsi/sd.c | 82 +++++++++++++++++++++++++++++++----------------
>  1 file changed, 55 insertions(+), 27 deletions(-)
> 
> diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
> index 4b1402633c36..9f047fd3c92d 100644
> --- a/drivers/scsi/sd.c
> +++ b/drivers/scsi/sd.c
> @@ -1227,6 +1227,14 @@ static int sd_init_command(struct scsi_cmnd *cmd)
>  {
>  	struct request *rq = cmd->request;
>  
> +	/*
> +	 * Assumption that REQ_OP_READ and REQ_OP_WRITE are 0 and 1 is
> +	 * checked in init_sd(). The following "if" is done to dispatch
> +	 * REQ_OP_READ and REQ_OP_WRITE quickly.
> +	 */
> +	if (likely(req_op(rq) < 2))
> +		return sd_setup_read_write_cmnd(cmd);
> +
>  	switch (req_op(rq)) {
>  	case REQ_OP_DISCARD:
>  		switch (scsi_disk(rq->rq_disk)->provisioning_mode) {
> @@ -1247,9 +1255,6 @@ static int sd_init_command(struct scsi_cmnd *cmd)
>  		return sd_setup_write_same_cmnd(cmd);
>  	case REQ_OP_FLUSH:
>  		return sd_setup_flush_cmnd(cmd);
> -	case REQ_OP_READ:
> -	case REQ_OP_WRITE:
> -		return sd_setup_read_write_cmnd(cmd);
>  	case REQ_OP_ZONE_REPORT:
>  		return sd_zbc_setup_report_cmnd(cmd);
>  	case REQ_OP_ZONE_RESET:
> @@ -1973,30 +1978,12 @@ static int sd_done(struct scsi_cmnd *SCpnt)
>  	int sense_valid = 0;
>  	int sense_deferred = 0;
>  
> -	switch (req_op(req)) {
> -	case REQ_OP_DISCARD:
> -	case REQ_OP_WRITE_ZEROES:
> -	case REQ_OP_WRITE_SAME:
> -	case REQ_OP_ZONE_RESET:
> -		if (!result) {
> -			good_bytes = blk_rq_bytes(req);
> -			scsi_set_resid(SCpnt, 0);
> -		} else {
> -			good_bytes = 0;
> -			scsi_set_resid(SCpnt, blk_rq_bytes(req));
> -		}
> -		break;
> -	case REQ_OP_ZONE_REPORT:
> -		if (!result) {
> -			good_bytes = scsi_bufflen(SCpnt)
> -				- scsi_get_resid(SCpnt);
> -			scsi_set_resid(SCpnt, 0);
> -		} else {
> -			good_bytes = 0;
> -			scsi_set_resid(SCpnt, blk_rq_bytes(req));
> -		}
> -		break;
> -	default:
> +	/*
> +	 * Assumption that REQ_OP_READ and REQ_OP_WRITE are 0 and 1 is
> +	 * checked in init_sd(). The following "if" is done to expedite
> +	 * REQ_OP_READ and REQ_OP_WRITE.
> +	 */
> +	if (likely(req_op(req) < 2)) {
>  		/*
>  		 * In case of bogus fw or device, we could end up having
>  		 * an unaligned partial completion. Check this here and force
> @@ -2011,6 +1998,36 @@ static int sd_done(struct scsi_cmnd *SCpnt)
>  				    round_up(resid, sector_size));
>  			scsi_set_resid(SCpnt, resid);
>  		}
> +	} else {
> +		switch (req_op(req)) {
> +		case REQ_OP_DISCARD:
> +		case REQ_OP_WRITE_ZEROES:
> +		case REQ_OP_WRITE_SAME:
> +		case REQ_OP_ZONE_RESET:
> +			if (!result) {
> +				good_bytes = blk_rq_bytes(req);
> +				scsi_set_resid(SCpnt, 0);
> +			} else {
> +				good_bytes = 0;
> +				scsi_set_resid(SCpnt, blk_rq_bytes(req));
> +			}
> +			break;
> +		case REQ_OP_ZONE_REPORT:
> +			if (!result) {
> +				good_bytes = scsi_bufflen(SCpnt)
> +					- scsi_get_resid(SCpnt);
> +				scsi_set_resid(SCpnt, 0);
> +			} else {
> +				good_bytes = 0;
> +				scsi_set_resid(SCpnt, blk_rq_bytes(req));
> +			}
> +			break;
> +		default:
> +			sd_printk(KERN_NOTICE, sdkp, "unexpected REQ_OP=%u\n",
> +				  (unsigned int)req_op(req));
> +			WARN_ON_ONCE(true);
> +			break;
> +		}
>  	}
>  
>  	if (result) {
> @@ -3597,6 +3614,17 @@ static int __init init_sd(void)
>  	int majors = 0, i, err;
>  
>  	SCSI_LOG_HLQUEUE(3, printk("init_sd: sd driver entry point\n"));
> +	/*
> +	 * The sd_init_command() and sd_done() assume REQ_OP_READ and
> +	 * REQ_OP_WRITE are 0 and 1 and will fail if they are not. If they
> +	 * are not, would prefer a compile failure but the preprocessor can't
> +	 * use enum constants. Place check here because only need to check
> +	 * early and once.
> +	 */
> +	if (REQ_OP_READ + REQ_OP_WRITE > 1)
> +		pr_err("%s: REQ_OP_READ=%d REQ_OP_WRITE=%d %s.\n", __func__,
> +		       REQ_OP_READ, REQ_OP_WRITE,
> +		       "expected 0 and 1. Logic ERROR");
>  
>  	for (i = 0; i < SD_MAJORS; i++) {
>  		if (register_blkdev(sd_major(i), "sd") != 0)
> 


-- 
Damien Le Moal
Western Digital Research




[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