From: Alexey Makhalov amakhalov@vmware.com
stable inclusion from stable-v5.10.90 commit 2a4f551dec1a897c10ccc1a525232ec41b26de80 bugzilla: 186168 https://gitee.com/openeuler/kernel/issues/I4SHY1
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=...
--------------------------------
commit 142c779d05d1fef75134c3cb63f52ccbc96d9e1f upstream.
The PVSCSI implementation in the VMware hypervisor under specific configuration ("SCSI Bus Sharing" set to "Physical") returns zero dataLen in the completion descriptor for READ CAPACITY(16). As a result, the kernel can not detect proper disk geometry. This can be recognized by the kernel message:
[ 0.776588] sd 1:0:0:0: [sdb] Sector size 0 reported, assuming 512.
The PVSCSI implementation in QEMU does not set dataLen at all, keeping it zeroed. This leads to a boot hang as was reported by Shmulik Ladkani.
It is likely that the controller returns the garbage at the end of the buffer. Residual length should be set by the driver in that case. The SCSI layer will erase corresponding data. See commit bdb2b8cab439 ("[SCSI] erase invalid data returned by device") for details.
Commit e662502b3a78 ("scsi: vmw_pvscsi: Set correct residual data length") introduced the issue by setting residual length unconditionally, causing the SCSI layer to erase the useful payload beyond dataLen when this value is returned as 0.
As a result, considering existing issues in implementations of PVSCSI controllers, we do not want to call scsi_set_resid() when dataLen == 0. Calling scsi_set_resid() has no effect if dataLen equals buffer length.
Link: https://lore.kernel.org/lkml/20210824120028.30d9c071@blondie/ Link: https://lore.kernel.org/r/20211220190514.55935-1-amakhalov@vmware.com Fixes: e662502b3a78 ("scsi: vmw_pvscsi: Set correct residual data length") Cc: Matt Wang wwentao@vmware.com Cc: Martin K. Petersen martin.petersen@oracle.com Cc: Vishal Bhakta vbhakta@vmware.com Cc: VMware PV-Drivers pv-drivers@vmware.com Cc: James E.J. Bottomley jejb@linux.ibm.com Cc: linux-scsi@vger.kernel.org Cc: stable@vger.kernel.org Reported-and-suggested-by: Shmulik Ladkani shmulik.ladkani@gmail.com Signed-off-by: Alexey Makhalov amakhalov@vmware.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Chen Jun chenjun102@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/scsi/vmw_pvscsi.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/vmw_pvscsi.c b/drivers/scsi/vmw_pvscsi.c index 1421b1394d81..7d51ff4672d7 100644 --- a/drivers/scsi/vmw_pvscsi.c +++ b/drivers/scsi/vmw_pvscsi.c @@ -591,9 +591,12 @@ static void pvscsi_complete_request(struct pvscsi_adapter *adapter, * Commands like INQUIRY may transfer less data than * requested by the initiator via bufflen. Set residual * count to make upper layer aware of the actual amount - * of data returned. + * of data returned. There are cases when controller + * returns zero dataLen with non zero data - do not set + * residual count in that case. */ - scsi_set_resid(cmd, scsi_bufflen(cmd) - e->dataLen); + if (e->dataLen && (e->dataLen < scsi_bufflen(cmd))) + scsi_set_resid(cmd, scsi_bufflen(cmd) - e->dataLen); cmd->result = (DID_OK << 16); break;