summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMasato Suzuki <masato.suzuki@wdc.com>2020-01-27 14:07:46 +0900
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-01-29 15:02:38 +0100
commit3e0151deb2872230e2a05c11d56f3a80cd5698f7 (patch)
tree859ceb483351b20cd57cbc91c57374a938ae19b6
parent778de9db9ec2036f0bd82572bbb7b35ec402089c (diff)
downloadlinux-stable-3e0151deb2872230e2a05c11d56f3a80cd5698f7.tar.gz
linux-stable-3e0151deb2872230e2a05c11d56f3a80cd5698f7.tar.bz2
linux-stable-3e0151deb2872230e2a05c11d56f3a80cd5698f7.zip
sd: Fix REQ_OP_ZONE_REPORT completion handling
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@vger.kernel.org> # 4.19 Cc: <stable@vger.kernel.org> # 4.14 Signed-off-by: Masato Suzuki <masato.suzuki@wdc.com> Reviewed-by: Damien Le Moal <damien.lemoal@wdc.com> Acked-by: Martin K. Petersen <martin.petersen@oracle.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/scsi/sd.c8
1 files 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;