VirtualBox

Changeset 80575 in vbox for trunk/src/VBox/Devices/Storage


Ignore:
Timestamp:
Sep 4, 2019 6:51:34 AM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
133094
Message:

Storage/DevVirtioSCSI.cpp: Resolved issue of mem corruption hn when moving a large number of large phys bytes to virt bytes. Fixed more error handling / response. See bugref:9440 Comment#70

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Storage/DevVirtioSCSI.cpp

    r80571 r80575  
    511511        case VIRTIOSCSI_S_OK:                           return "OK";
    512512        case VIRTIOSCSI_S_OVERRUN:                      return "OVERRRUN";
     513        case VIRTIOSCSI_S_ABORTED:                      return "ABORTED";
    513514        case VIRTIOSCSI_S_BAD_TARGET:                   return "BAD TARGET";
     515        case VIRTIOSCSI_S_RESET:                        return "RESET";
     516        case VIRTIOSCSI_S_TRANSPORT_FAILURE:            return "TRANSPORT FAILURE";
     517        case VIRTIOSCSI_S_TARGET_FAILURE:               return "TARGET FAILURE";
     518        case VIRTIOSCSI_S_NEXUS_FAILURE:                return "NEXUS FAILURE";
    514519        case VIRTIOSCSI_S_BUSY:                         return "BUSY";
    515         case VIRTIOSCSI_S_RESET:                        return "RESET";
    516         case VIRTIOSCSI_S_ABORTED:                      return "ABORTED";
    517         case VIRTIOSCSI_S_NEXUS_FAILURE:                return "NEXUS FAILURE";
    518         case VIRTIOSCSI_S_TRANSPORT_FAILURE:            return "TRANSPORT FAILURE";
    519520        case VIRTIOSCSI_S_FAILURE:                      return "FAILURE";
    520521        default:                                        return "<unknown>";
     
    766767
    767768}
    768 
     769/** TBD: VirtIO 1.0 spec 5.6.6.1.1 requires some request actions on reset that are
     770 *       not implemented.  Specifically either canceling outstanding I/O or
     771 *       returning VIRTIOSCSI_S_FAILURE for those requests.  Since there's no
     772 *       way to cancel I/O on VSCSI at this time the only the only other
     773 *       possibility is to wait for the outstanding request count to drop
     774 *       and return the failure code for any-and-all until that's done before
     775 *       allowing a reset to continue.
     776 *
     777 *       In the absence of active I/O farmed out to VSCSI
     778 *       the device handles a guest driver unload/reload gracefully and has
     779 *       been tested.
     780 */
    769781static int virtioScsiReqFinish(PVIRTIOSCSI pThis, PVIRTIOSCSIREQ pReq, int rcReq)
    770782{
     
    786798    respHdr.uResidual = cbResidual;
    787799    respHdr.uStatus   = pReq->uStatus;
    788     respHdr.uResponse = rcReq;
    789 
    790     Log2Func(("status: %s    response: %s\n",
    791               SCSIStatusText(pReq->uStatus),  virtioGetReqRespText(respHdr.uResponse)));
     800
     801    /** VirtIO 1.0 spec 5.6.6.1.1 says device MUST return a VirtIO response byte value.
     802     *  Some are returned during the submit phase, and a few are not mapped at all,
     803     *  wherein anything that can't map specifically gets mapped to VIRTIOSCSI_S_FAILURE */
     804    switch(rcReq)
     805    {
     806        case SCSI_STATUS_OK:
     807            if (pReq->uStatus != SCSI_STATUS_CHECK_CONDITION)
     808            {
     809                respHdr.uResponse = VIRTIOSCSI_S_OK;
     810                break;
     811            }
     812            /* fallthrough */
     813        case SCSI_STATUS_BUSY:
     814            respHdr.uResponse = VIRTIOSCSI_S_BUSY;
     815            break;
     816        case SCSI_STATUS_DATA_UNDEROVER_RUN:
     817            respHdr.uResponse = VIRTIOSCSI_S_OVERRUN;
     818            break;
     819        case SCSI_STATUS_TASK_ABORTED:
     820            respHdr.uResponse = VIRTIOSCSI_S_ABORTED;
     821            break;
     822        case SCSI_STATUS_CHECK_CONDITION:
     823            {
     824                uint8_t uSenseKey = pReq->pbSense[2];
     825                switch (uSenseKey)
     826                {
     827                    case SCSI_SENSE_ABORTED_COMMAND:
     828                        respHdr.uResponse = VIRTIOSCSI_S_ABORTED;
     829                        break;
     830                    case SCSI_SENSE_COPY_ABORTED:
     831                        respHdr.uResponse = VIRTIOSCSI_S_ABORTED;
     832                        break;
     833                    case SCSI_SENSE_UNIT_ATTENTION:
     834                        respHdr.uResponse = VIRTIOSCSI_S_TARGET_FAILURE;
     835                        break;
     836                    case SCSI_SENSE_HARDWARE_ERROR:
     837                        respHdr.uResponse = VIRTIOSCSI_S_TARGET_FAILURE;
     838                        break;
     839                    case SCSI_SENSE_NOT_READY:
     840                        respHdr.uResponse = VIRTIOSCSI_S_BUSY; /* e.g. try again */
     841                        break;
     842                    default:
     843                        respHdr.uResponse = VIRTIOSCSI_S_FAILURE;
     844                        break;
     845                }
     846            }
     847            break;
     848
     849        default:
     850            respHdr.uResponse = VIRTIOSCSI_S_FAILURE;
     851            break;
     852    }
     853
     854    Log2Func(("status: %s,   response: (%x) %s\n",
     855              SCSIStatusText(pReq->uStatus), respHdr.uResponse, virtioGetReqRespText(respHdr.uResponse)));
     856
     857    if (RT_FAILURE(rcReq))
     858        Log2Func(("rcReq:  %s\n", RTErrGetDefine(rcReq)));
    792859
    793860    Log3Func(("status:%02x/resp:%02x, xfer=%d, residual: %u, sense (len=%d, alloc=%d)\n",
     
    795862              respHdr.uSenseLen, pThis->virtioScsiConfig.uSenseSize));
    796863
    797 
    798864    if (respHdr.uSenseLen && LogIs2Enabled())
    799865    {
    800866        Log2Func(("Sense: %s\n", SCSISenseText(pReq->pbSense[2])));
    801867        Log2Func(("Sense Ext3: %s\n", SCSISenseExtText(pReq->pbSense[12], pReq->pbSense[13])));
    802 
    803868    }
    804869
    805870    int cSegs = 0;
    806871
    807     Assert(pReq->cbDataIn >= cbXfer);
     872
     873//    Assert(pReq->cbDataIn >= cbXfer);
    808874    Assert(pReq->pbSense != NULL);
    809875
     
    870936 * @returns virtual box status code
    871937 */
    872 static int virtioScsiReqFinish(PVIRTIOSCSI pThis, uint16_t qIdx, struct REQ_RESP_HDR *respHdr, uint8_t *pbSense)
     938static int virtioScsiReqFinish(PVIRTIOSCSI pThis, uint16_t qIdx, struct REQ_RESP_HDR *pRespHdr, uint8_t *pbSense)
    873939{
    874940    uint8_t *abSenseBuf = (uint8_t *)RTMemAllocZ(pThis->virtioScsiConfig.uSenseSize);
    875941    AssertReturn(abSenseBuf, VERR_NO_MEMORY);
    876942
     943    Log2Func(("status: %s    response: %s\n",
     944              SCSIStatusText(pRespHdr->uStatus),  virtioGetReqRespText(pRespHdr->uResponse)));
     945
    877946    RTSGSEG aReqSegs[2];
    878     aReqSegs[0].cbSeg = sizeof(respHdr);
    879     aReqSegs[0].pvSeg = respHdr;
     947    aReqSegs[0].cbSeg = sizeof(pRespHdr);
     948    aReqSegs[0].pvSeg = pRespHdr;
    880949    aReqSegs[1].cbSeg = pThis->virtioScsiConfig.uSenseSize;
    881950    aReqSegs[1].pvSeg = abSenseBuf;
    882951
    883     if (pbSense && respHdr->uSenseLen)
    884         memcpy(abSenseBuf, pbSense, respHdr->uSenseLen);
     952    if (pbSense && pRespHdr->uSenseLen)
     953        memcpy(abSenseBuf, pbSense, pRespHdr->uSenseLen);
    885954    else
    886         respHdr->uSenseLen = 0;
     955        pRespHdr->uSenseLen = 0;
    887956
    888957    RTSGBUF reqSegBuf;
     
    894963    RTMemFree(abSenseBuf);
    895964
    896     LogFunc(("Response code: %s\n", virtioGetReqRespText(respHdr->uResponse)));
    897 
    898965    Log(("---------------------------------------------------------------------------------\n"));
    899966
     
    914981    AssertReturn(pVirtqReq, VERR_NO_MEMORY);
    915982
    916 Log(("cbOut = %d\n", cbOut));
    917 uint32_t seg = 0;
    918983    off_t cbOff = 0;
    919984    size_t cbCopy = cbOut;
     
    922987        size_t cbSeg = cbCopy;
    923988        RTGCPHYS GCPhys = (RTGCPHYS)RTSgBufGetNextSegment(pOutSgBuf, &cbSeg);
    924 Log(("seg:%03d, GCPhys:%p, virtAddr:%p, cbSeg:%6d, cbOff:%6d, cbCopy:%d\n",
    925          seg++, GCPhys,     pVirtqReq + cbOff, cbSeg, cbOff, cbCopy));
    926         PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhys, pVirtqReq + cbOff, cbSeg);
     989        PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhys, ((uint8_t *)pVirtqReq) + cbOff, cbSeg);
    927990        cbCopy -= cbSeg;
    928991        cbOff += cbSeg;
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette