Re: [PATCH] sd: Fix REQ_OP_ZONE_REPORT completion handling

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

 



On 2020/01/27 14:07, Masato Suzuki wrote:
> ZBC/ZAC report zones command may return less bytes than requested if the
> number of matching zones for the report request is small. However, unlike
> read or write commands, the remainder of incomplete report zones commands
> cannot be automatically requested by the block layer: the start sector of
> the next report cannot be known, and the report reply may not be 512B
> aligned for SAS drives (a report zone reply size is always a multiple of
> 64B). The regular request completion code executing bio_advance() and
> restart of the command remainder part currently causes invalid zone
> descriptor data to be reported to the caller if the report zone size is
> smaller than 512B (a case that can happen easily for a report of the last
> zones of a SAS drive for example).
> 
> Since blkdev_report_zones() handles report zone command processing in a
> loop until completion (no more zones are being reported), we can safely
> avoid that the block layer performs an incorrect bio_advance() call and
> restart of the remainder of incomplete report zone BIOs. To do so, always
> indicate a full completion of REQ_OP_ZONE_REPORT by setting good_bytes to
> the request buffer size and by setting the command resid to 0. This does
> not affect the post processing of the report zone reply done by
> sd_zbc_complete() since the reply header indicates the number of zones
> reported.
> 
> Fixes: 89d947561077 ("sd: Implement support for ZBC devices")
> Cc: <stable@xxxxxxxxxxxxxxx> # 4.19
> Cc: <stable@xxxxxxxxxxxxxxx> # 4.14
> Signed-off-by: Masato Suzuki <masato.suzuki@xxxxxxx>

This bug exists since the beginning of SMR support in 4.10, until report
zones was changed to a device file method in kernel 4.20. It fell through
the cracks the entire time and was caught only recently with improvements
to our test suite.

Reviewed-by: Damien Le Moal <damien.lemoal@xxxxxxx>

> ---
>  drivers/scsi/sd.c | 8 ++++++--
>  1 file changed, 6 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
> index 2955b856e9ec..e8c2afbb82e9 100644
> --- a/drivers/scsi/sd.c
> +++ b/drivers/scsi/sd.c
> @@ -1981,9 +1981,13 @@ static int sd_done(struct scsi_cmnd *SCpnt)
>  		}
>  		break;
>  	case REQ_OP_ZONE_REPORT:
> +		/* To avoid that the block layer performs an incorrect
> +		 * bio_advance() call and restart of the remainder of
> +		 * incomplete report zone BIOs, always indicate a full
> +		 * completion of REQ_OP_ZONE_REPORT.
> +		 */
>  		if (!result) {
> -			good_bytes = scsi_bufflen(SCpnt)
> -				- scsi_get_resid(SCpnt);
> +			good_bytes = scsi_bufflen(SCpnt);
>  			scsi_set_resid(SCpnt, 0);
>  		} else {
>  			good_bytes = 0;
> 


-- 
Damien Le Moal
Western Digital Research




[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux