VirtualBox

Changeset 32983 in vbox for trunk/src


Ignore:
Timestamp:
Oct 7, 2010 3:14:54 PM (14 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
66493
Message:

LsiLogic: Suspend the VM on a recoverable error without changing the saved state format

Location:
trunk/src/VBox/Devices/Storage
Files:
11 edited

Legend:

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

    r30809 r32983  
    20132013}
    20142014
    2015 static DECLCALLBACK(int) buslogicDeviceSCSIRequestCompleted(PPDMISCSIPORT pInterface, PPDMSCSIREQUEST pSCSIRequest, int rcCompletion)
     2015static DECLCALLBACK(int) buslogicDeviceSCSIRequestCompleted(PPDMISCSIPORT pInterface, PPDMSCSIREQUEST pSCSIRequest,
     2016                                                            int rcCompletion, bool fRedo, int rcReq)
    20162017{
    20172018    int rc;
  • trunk/src/VBox/Devices/Storage/DevLsiLogicSCSI.cpp

    r32938 r32983  
    103103} LSILOGICDEVICE, *PLSILOGICDEVICE;
    104104
     105/** Pointer to a task state. */
     106typedef struct LSILOGICTASKSTATE *PLSILOGICTASKSTATE;
     107
    105108/**
    106109 * Device instance data for the emulated
     
    290293     * a port is entering the idle state. */
    291294    bool volatile                  fSignalIdle;
     295    /** Flag whether we have tasks which need to be processed again- */
     296    bool volatile                  fRedo;
     297    /** List of tasks which can be redone. */
     298    R3PTRTYPE(volatile PLSILOGICTASKSTATE) pTasksRedoHead;
    292299
    293300} LSILOGISCSI, *PLSILOGICSCSI;
     
    325332typedef struct LSILOGICTASKSTATE
    326333{
     334    /** Next in the redo list. */
     335    PLSILOGICTASKSTATE         pRedoNext;
    327336    /** Target device. */
    328337    PLSILOGICDEVICE            pTargetDevice;
     
    360369    /** Flag whether the request was issued from the BIOS. */
    361370    bool                       fBIOS;
    362 } LSILOGICTASKSTATE, *PLSILOGICTASKSTATE;
     371} LSILOGICTASKSTATE;
    363372
    364373#ifndef VBOX_DEVICE_STRUCT_TESTCASE
     
    18931902#endif
    18941903
     1904static void lsilogicWarningDiskFull(PPDMDEVINS pDevIns)
     1905{
     1906    int rc;
     1907    LogRel(("LsiLogic#%d: Host disk full\n", pDevIns->iInstance));
     1908    rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevLsiLogic_DISKFULL",
     1909                                    N_("Host system reported disk full. VM execution is suspended. You can resume after freeing some space"));
     1910    AssertRC(rc);
     1911}
     1912
     1913static void lsilogicWarningFileTooBig(PPDMDEVINS pDevIns)
     1914{
     1915    int rc;
     1916    LogRel(("LsiLogic#%d: File too big\n", pDevIns->iInstance));
     1917    rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevLsiLogic_FILETOOBIG",
     1918                                    N_("Host system reported that the file size limit of the host file system has been exceeded. VM execution is suspended. You need to move your virtual hard disk to a filesystem which allows bigger files"));
     1919    AssertRC(rc);
     1920}
     1921
     1922static void lsilogicWarningISCSI(PPDMDEVINS pDevIns)
     1923{
     1924    int rc;
     1925    LogRel(("LsiLogic#%d: iSCSI target unavailable\n", pDevIns->iInstance));
     1926    rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevLsiLogic_ISCSIDOWN",
     1927                                    N_("The iSCSI target has stopped responding. VM execution is suspended. You can resume when it is available again"));
     1928    AssertRC(rc);
     1929}
     1930
     1931static void lsilogicWarningUnknown(PPDMDEVINS pDevIns, int rc)
     1932{
     1933    int rc2;
     1934    LogRel(("LsiLogic#%d: Unknown but recoverable error has occurred (rc=%Rrc)\n", pDevIns->iInstance, rc));
     1935    rc2 = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevLsiLogic_UNKNOWN",
     1936                                     N_("An unknown but recoverable I/O error has occurred (rc=%Rrc). VM execution is suspended. You can resume when the error is fixed"), rc);
     1937    AssertRC(rc2);
     1938}
     1939
     1940static void lsilogicRedoSetWarning(PLSILOGICSCSI pThis, int rc)
     1941{
     1942    if (rc == VERR_DISK_FULL)
     1943        lsilogicWarningDiskFull(pThis->CTX_SUFF(pDevIns));
     1944    else if (rc == VERR_FILE_TOO_BIG)
     1945        lsilogicWarningFileTooBig(pThis->CTX_SUFF(pDevIns));
     1946    else if (rc == VERR_BROKEN_PIPE || rc == VERR_NET_CONNECTION_REFUSED)
     1947    {
     1948        /* iSCSI connection abort (first error) or failure to reestablish
     1949         * connection (second error). Pause VM. On resume we'll retry. */
     1950        lsilogicWarningISCSI(pThis->CTX_SUFF(pDevIns));
     1951    }
     1952    else
     1953        lsilogicWarningUnknown(pThis->CTX_SUFF(pDevIns), rc);
     1954}
     1955
    18951956/**
    18961957 * Processes a SCSI I/O request by setting up the request
     
    20192080}
    20202081
    2021 /**
    2022  * Called upon completion of the request from the SCSI driver below.
    2023  * This function frees all allocated ressources and notifies the guest
    2024  * that the process finished by asserting an interrupt.
    2025  *
    2026  * @returns VBox status code.
    2027  * @param   pInterface    Pointer to the interface the called funtion belongs to.
    2028  * @param   pSCSIRequest  Pointer to the SCSI request which finished.
    2029  */
    2030 static DECLCALLBACK(int) lsilogicDeviceSCSIRequestCompleted(PPDMISCSIPORT pInterface, PPDMSCSIREQUEST pSCSIRequest, int rcCompletion)
     2082
     2083static DECLCALLBACK(int) lsilogicDeviceSCSIRequestCompleted(PPDMISCSIPORT pInterface, PPDMSCSIREQUEST pSCSIRequest,
     2084                                                            int rcCompletion, bool fRedo, int rcReq)
    20312085{
    20322086    PLSILOGICTASKSTATE pTaskState      = (PLSILOGICTASKSTATE)pSCSIRequest->pvUser;
     
    20342088    PLSILOGICSCSI      pLsiLogic       = pLsiLogicDevice->CTX_SUFF(pLsiLogic);
    20352089
     2090    /* If the task failed but it is possible to redo it again after a suspend
     2091     * add it to the list. */
     2092    if (fRedo)
     2093    {
     2094        if (!pTaskState->fBIOS)
     2095            lsilogicScatterGatherListDestroy(pLsiLogic, pTaskState);
     2096
     2097        /* Add to the list. */
     2098        do
     2099        {
     2100            pTaskState->pRedoNext = ASMAtomicReadPtrT(&pLsiLogic->pTasksRedoHead, PLSILOGICTASKSTATE);
     2101        } while (!ASMAtomicCmpXchgPtr(&pLsiLogic->pTasksRedoHead, pTaskState, pTaskState->pRedoNext));
     2102
     2103        /* Suspend the VM if not done already. */
     2104        if (!ASMAtomicXchgBool(&pLsiLogic->fRedo, true))
     2105            lsilogicRedoSetWarning(pLsiLogic, rcReq);
     2106    }
     2107    else
     2108    {
     2109        if (RT_UNLIKELY(pTaskState->fBIOS))
     2110        {
     2111            int rc = vboxscsiRequestFinished(&pLsiLogic->VBoxSCSI, pSCSIRequest);
     2112            AssertMsgRC(rc, ("Finishing BIOS SCSI request failed rc=%Rrc\n", rc));
     2113        }
     2114        else
     2115        {
     2116#if 0
     2117            lsilogicFreeGCSenseBuffer(pLsiLogic, pTaskState);
     2118#else
     2119            RTGCPHYS GCPhysAddrSenseBuffer;
     2120
     2121            GCPhysAddrSenseBuffer = pTaskState->GuestRequest.SCSIIO.u32SenseBufferLowAddress;
     2122            GCPhysAddrSenseBuffer |= ((uint64_t)pLsiLogic->u32SenseBufferHighAddr << 32);
     2123
     2124            /* Copy the sense buffer over. */
     2125            PDMDevHlpPhysWrite(pLsiLogic->CTX_SUFF(pDevIns), GCPhysAddrSenseBuffer, pTaskState->abSenseBuffer,
     2126                                 RT_UNLIKELY(pTaskState->GuestRequest.SCSIIO.u8SenseBufferLength < pTaskState->PDMScsiRequest.cbSenseBuffer)
     2127                               ? pTaskState->GuestRequest.SCSIIO.u8SenseBufferLength
     2128                               : pTaskState->PDMScsiRequest.cbSenseBuffer);
     2129#endif
     2130            lsilogicScatterGatherListDestroy(pLsiLogic, pTaskState);
     2131
     2132
     2133            if (RT_LIKELY(rcCompletion == SCSI_STATUS_OK))
     2134                lsilogicFinishContextReply(pLsiLogic, pTaskState->GuestRequest.SCSIIO.u32MessageContext);
     2135            else
     2136            {
     2137                /* The SCSI target encountered an error during processing post a reply. */
     2138                memset(&pTaskState->IOCReply, 0, sizeof(MptReplyUnion));
     2139                pTaskState->IOCReply.SCSIIOError.u8TargetID          = pTaskState->GuestRequest.SCSIIO.u8TargetID;
     2140                pTaskState->IOCReply.SCSIIOError.u8Bus               = pTaskState->GuestRequest.SCSIIO.u8Bus;
     2141                pTaskState->IOCReply.SCSIIOError.u8MessageLength     = 8;
     2142                pTaskState->IOCReply.SCSIIOError.u8Function          = pTaskState->GuestRequest.SCSIIO.u8Function;
     2143                pTaskState->IOCReply.SCSIIOError.u8CDBLength         = pTaskState->GuestRequest.SCSIIO.u8CDBLength;
     2144                pTaskState->IOCReply.SCSIIOError.u8SenseBufferLength = pTaskState->GuestRequest.SCSIIO.u8SenseBufferLength;
     2145                pTaskState->IOCReply.SCSIIOError.u8MessageFlags      = pTaskState->GuestRequest.SCSIIO.u8MessageFlags;
     2146                pTaskState->IOCReply.SCSIIOError.u32MessageContext   = pTaskState->GuestRequest.SCSIIO.u32MessageContext;
     2147                pTaskState->IOCReply.SCSIIOError.u8SCSIStatus        = rcCompletion;
     2148                pTaskState->IOCReply.SCSIIOError.u8SCSIState         = MPT_SCSI_IO_ERROR_SCSI_STATE_AUTOSENSE_VALID;
     2149                pTaskState->IOCReply.SCSIIOError.u16IOCStatus        = 0;
     2150                pTaskState->IOCReply.SCSIIOError.u32IOCLogInfo       = 0;
     2151                pTaskState->IOCReply.SCSIIOError.u32TransferCount    = 0;
     2152                pTaskState->IOCReply.SCSIIOError.u32SenseCount       = sizeof(pTaskState->abSenseBuffer);
     2153                pTaskState->IOCReply.SCSIIOError.u32ResponseInfo     = 0;
     2154
     2155                lsilogicFinishAddressReply(pLsiLogic, &pTaskState->IOCReply, true);
     2156            }
     2157        }
     2158
     2159        RTMemCacheFree(pLsiLogic->hTaskCache, pTaskState);
     2160    }
     2161
    20362162    ASMAtomicDecU32(&pLsiLogicDevice->cOutstandingRequests);
    2037 
    2038     if (RT_UNLIKELY(pTaskState->fBIOS))
    2039     {
    2040         int rc = vboxscsiRequestFinished(&pLsiLogic->VBoxSCSI, pSCSIRequest);
    2041         AssertMsgRC(rc, ("Finishing BIOS SCSI request failed rc=%Rrc\n", rc));
    2042     }
    2043     else
    2044     {
    2045 #if 0
    2046         lsilogicFreeGCSenseBuffer(pLsiLogic, pTaskState);
    2047 #else
    2048         RTGCPHYS GCPhysAddrSenseBuffer;
    2049 
    2050         GCPhysAddrSenseBuffer = pTaskState->GuestRequest.SCSIIO.u32SenseBufferLowAddress;
    2051         GCPhysAddrSenseBuffer |= ((uint64_t)pLsiLogic->u32SenseBufferHighAddr << 32);
    2052 
    2053         /* Copy the sense buffer over. */
    2054         PDMDevHlpPhysWrite(pLsiLogic->CTX_SUFF(pDevIns), GCPhysAddrSenseBuffer, pTaskState->abSenseBuffer,
    2055                              RT_UNLIKELY(pTaskState->GuestRequest.SCSIIO.u8SenseBufferLength < pTaskState->PDMScsiRequest.cbSenseBuffer)
    2056                            ? pTaskState->GuestRequest.SCSIIO.u8SenseBufferLength
    2057                            : pTaskState->PDMScsiRequest.cbSenseBuffer);
    2058 #endif
    2059         lsilogicScatterGatherListDestroy(pLsiLogic, pTaskState);
    2060 
    2061 
    2062         if (RT_LIKELY(rcCompletion == SCSI_STATUS_OK))
    2063             lsilogicFinishContextReply(pLsiLogic, pTaskState->GuestRequest.SCSIIO.u32MessageContext);
    2064         else
    2065         {
    2066             /* The SCSI target encountered an error during processing post a reply. */
    2067             memset(&pTaskState->IOCReply, 0, sizeof(MptReplyUnion));
    2068             pTaskState->IOCReply.SCSIIOError.u8TargetID          = pTaskState->GuestRequest.SCSIIO.u8TargetID;
    2069             pTaskState->IOCReply.SCSIIOError.u8Bus               = pTaskState->GuestRequest.SCSIIO.u8Bus;
    2070             pTaskState->IOCReply.SCSIIOError.u8MessageLength     = 8;
    2071             pTaskState->IOCReply.SCSIIOError.u8Function          = pTaskState->GuestRequest.SCSIIO.u8Function;
    2072             pTaskState->IOCReply.SCSIIOError.u8CDBLength         = pTaskState->GuestRequest.SCSIIO.u8CDBLength;
    2073             pTaskState->IOCReply.SCSIIOError.u8SenseBufferLength = pTaskState->GuestRequest.SCSIIO.u8SenseBufferLength;
    2074             pTaskState->IOCReply.SCSIIOError.u8MessageFlags      = pTaskState->GuestRequest.SCSIIO.u8MessageFlags;
    2075             pTaskState->IOCReply.SCSIIOError.u32MessageContext   = pTaskState->GuestRequest.SCSIIO.u32MessageContext;
    2076             pTaskState->IOCReply.SCSIIOError.u8SCSIStatus        = rcCompletion;
    2077             pTaskState->IOCReply.SCSIIOError.u8SCSIState         = MPT_SCSI_IO_ERROR_SCSI_STATE_AUTOSENSE_VALID;
    2078             pTaskState->IOCReply.SCSIIOError.u16IOCStatus        = 0;
    2079             pTaskState->IOCReply.SCSIIOError.u32IOCLogInfo       = 0;
    2080             pTaskState->IOCReply.SCSIIOError.u32TransferCount    = 0;
    2081             pTaskState->IOCReply.SCSIIOError.u32SenseCount       = sizeof(pTaskState->abSenseBuffer);
    2082             pTaskState->IOCReply.SCSIIOError.u32ResponseInfo     = 0;
    2083 
    2084             lsilogicFinishAddressReply(pLsiLogic, &pTaskState->IOCReply, true);
    2085         }
    2086     }
    2087 
    2088     RTMemCacheFree(pLsiLogic->hTaskCache, pTaskState);
    20892163
    20902164    if (pLsiLogicDevice->cOutstandingRequests == 0 && pLsiLogic->fSignalIdle)
     
    39744048}
    39754049
     4050/**
     4051 * Kicks the controller to process pending tasks after the VM was resumed
     4052 * or loaded from a saved state.
     4053 *
     4054 * @returns nothing.
     4055 * @param   pThis    The LsiLogic device instance.
     4056 */
     4057static void lsilogicKick(PLSILOGICSCSI pThis)
     4058{
     4059    if (pThis->fNotificationSend)
     4060    {
     4061        /* Send a notifier to the PDM queue that there are pending requests. */
     4062        PPDMQUEUEITEMCORE pItem = PDMQueueAlloc(pThis->CTX_SUFF(pNotificationQueue));
     4063        AssertMsg(pItem, ("Allocating item for queue failed\n"));
     4064        PDMQueueInsert(pThis->CTX_SUFF(pNotificationQueue), (PPDMQUEUEITEMCORE)pItem);
     4065    }
     4066    else if (pThis->VBoxSCSI.fBusy)
     4067    {
     4068        /* The BIOS had a request active when we got suspended. Resume it. */
     4069        int rc = lsilogicPrepareBIOSSCSIRequest(pThis);
     4070        AssertRC(rc);
     4071    }
     4072
     4073}
     4074
    39764075static DECLCALLBACK(int) lsilogicLiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass)
    39774076{
     
    41384237    SSMR3PutBool  (pSSM, pLsiLogic->VBoxSCSI.fBusy);
    41394238    SSMR3PutU8    (pSSM, pLsiLogic->VBoxSCSI.enmState);
    4140     if (pLsiLogic->VBoxSCSI.cbCDB)
     4239    if (pLsiLogic->VBoxSCSI.cbBuf)
    41414240        SSMR3PutMem(pSSM, pLsiLogic->VBoxSCSI.pBuf, pLsiLogic->VBoxSCSI.cbBuf);
    41424241
    41434242    return SSMR3PutU32(pSSM, ~0);
     4243}
     4244
     4245static DECLCALLBACK(int) lsilogicLoadDone(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
     4246{
     4247    PLSILOGICSCSI pThis = PDMINS_2_DATA(pDevIns, PLSILOGICSCSI);
     4248
     4249    lsilogicKick(pThis);
     4250    return VINF_SUCCESS;
    41444251}
    41454252
     
    44124519    SSMR3GetBool(pSSM, (bool *)&pLsiLogic->VBoxSCSI.fBusy);
    44134520    SSMR3GetU8  (pSSM, (uint8_t *)&pLsiLogic->VBoxSCSI.enmState);
    4414     if (pLsiLogic->VBoxSCSI.cbCDB)
    4415     {
    4416         pLsiLogic->VBoxSCSI.pBuf = (uint8_t *)RTMemAllocZ(pLsiLogic->VBoxSCSI.cbCDB);
     4521    if (pLsiLogic->VBoxSCSI.cbBuf)
     4522    {
     4523        pLsiLogic->VBoxSCSI.pBuf = (uint8_t *)RTMemAllocZ(pLsiLogic->VBoxSCSI.cbBuf);
    44174524        if (!pLsiLogic->VBoxSCSI.pBuf)
    44184525        {
     
    45534660        PDMDevHlpSetAsyncNotification(pDevIns, lsilogicR3IsAsyncSuspendOrPowerOffDone);
    45544661    else
     4662    {
    45554663        ASMAtomicWriteBool(&pThis->fSignalIdle, false);
     4664
     4665        AssertMsg(!pThis->fNotificationSend, ("The PDM Queue should be empty at this point\n"));
     4666
     4667        if (pThis->fRedo)
     4668        {
     4669            /*
     4670             * We have tasks which we need to redo. Put the message frame addresses
     4671             * into the request queue (we save the requests).
     4672             * Guest execution is suspended at this point so there is no race between us and
     4673             * lsilogicRegisterWrite.
     4674             */
     4675            PLSILOGICTASKSTATE pTaskState = pThis->pTasksRedoHead;
     4676
     4677            pThis->pTasksRedoHead = NULL;
     4678
     4679            while (pTaskState)
     4680            {
     4681                PLSILOGICTASKSTATE pFree;
     4682
     4683                if (!pTaskState->fBIOS)
     4684                {
     4685                    /* Write only the lower 32bit part of the address. */
     4686                    ASMAtomicWriteU32(&pThis->CTX_SUFF(pRequestQueueBase)[pThis->uRequestQueueNextEntryFreeWrite],
     4687                                      pTaskState->GCPhysMessageFrameAddr & UINT32_C(0xffffffff));
     4688
     4689                    pThis->uRequestQueueNextEntryFreeWrite++;
     4690                    pThis->uRequestQueueNextEntryFreeWrite %= pThis->cRequestQueueEntries;
     4691
     4692                    pThis->fNotificationSend = true;
     4693                }
     4694                else
     4695                {
     4696                    AssertMsg(!pTaskState->pRedoNext, ("Only one BIOS task can be active!\n"));
     4697                    vboxscsiSetRequestRedo(&pThis->VBoxSCSI, &pTaskState->PDMScsiRequest);
     4698                }
     4699
     4700                pFree = pTaskState;
     4701                pTaskState = pTaskState->pRedoNext;
     4702
     4703                RTMemCacheFree(pThis->hTaskCache, pFree);
     4704            }
     4705            pThis->fRedo = false;
     4706        }
     4707    }
    45564708}
    45574709
     
    45654717    Log(("lsilogicSuspend\n"));
    45664718    lsilogicR3SuspendOrPowerOff(pDevIns);
     4719}
     4720
     4721/**
     4722 * Resume notification.
     4723 *
     4724 * @param   pDevIns     The device instance data.
     4725 */
     4726static DECLCALLBACK(void) lsilogicResume(PPDMDEVINS pDevIns)
     4727{
     4728    PLSILOGICSCSI pThis = PDMINS_2_DATA(pDevIns, PLSILOGICSCSI);
     4729
     4730    Log(("lsilogicResume\n"));
     4731
     4732    lsilogicKick(pThis);
    45674733}
    45684734
     
    50345200
    50355201    /* Register save state handlers. */
    5036     rc = PDMDevHlpSSMRegister3(pDevIns, LSILOGIC_SAVED_STATE_VERSION, sizeof(*pThis),
    5037                                lsilogicLiveExec, lsilogicSaveExec, lsilogicLoadExec);
     5202    rc = PDMDevHlpSSMRegisterEx(pDevIns, LSILOGIC_SAVED_STATE_VERSION, sizeof(*pThis), NULL,
     5203                                NULL, lsilogicLiveExec, NULL,
     5204                                NULL, lsilogicSaveExec, NULL,
     5205                                NULL, lsilogicLoadExec, lsilogicLoadDone);
    50385206    if (RT_FAILURE(rc))
    50395207        return PDMDEV_SET_ERROR(pDevIns, rc, N_("LsiLogic cannot register save state handlers"));
     
    50975265    lsilogicSuspend,
    50985266    /* pfnResume */
    5099     NULL,
     5267    lsilogicResume,
    51005268    /* pfnAttach */
    51015269    lsilogicAttach,
     
    51535321    lsilogicSuspend,
    51545322    /* pfnResume */
    5155     NULL,
     5323    lsilogicResume,
    51565324    /* pfnAttach */
    51575325    lsilogicAttach,
  • trunk/src/VBox/Devices/Storage/DrvSCSI.cpp

    r30384 r32983  
    112112#define PDMIBLOCKASYNCPORT_2_DRVSCSI(pInterface) ( (PDRVSCSI)((uintptr_t)pInterface - RT_OFFSETOF(DRVSCSI, IPortAsync)) )
    113113
     114static int drvscsiIsRedoPossible(int rc)
     115{
     116    if (   rc == VERR_DISK_FULL
     117        || rc == VERR_FILE_TOO_BIG
     118        || rc == VERR_BROKEN_PIPE
     119        || rc == VERR_NET_CONNECTION_REFUSED)
     120        return true;
     121
     122    return false;
     123}
     124
    114125static int drvscsiProcessRequestOne(PDRVSCSI pThis, VSCSIIOREQ hVScsiIoReq)
    115126{
     
    152163                    pThis->pLed->Actual.s.fReading = 0;
    153164                    if (RT_FAILURE(rc))
    154                         AssertMsgFailed(("%s: Failed to read data %Rrc\n", __FUNCTION__, rc));
     165                        break;
    155166                    STAM_REL_COUNTER_ADD(&pThis->StatBytesRead, cbProcess);
    156167                }
     
    162173                    pThis->pLed->Actual.s.fWriting = 0;
    163174                    if (RT_FAILURE(rc))
    164                         AssertMsgFailed(("%s: Failed to write data %Rrc\n", __FUNCTION__, rc));
     175                        break;
    165176                    STAM_REL_COUNTER_ADD(&pThis->StatBytesWritten, cbProcess);
    166177                }
     
    179190    }
    180191
    181     VSCSIIoReqCompleted(hVScsiIoReq, rc);
     192    if (RT_SUCCESS(rc))
     193        VSCSIIoReqCompleted(hVScsiIoReq, rc, false /* fRedoPossible */);
     194    else
     195        VSCSIIoReqCompleted(hVScsiIoReq, rc, drvscsiIsRedoPossible(rc));
    182196
    183197    return VINF_SUCCESS;
     
    208222        AssertMsg(enmTxDir == VSCSIIOREQTXDIR_FLUSH, ("Invalid transfer direction %u\n", enmTxDir));
    209223
    210     VSCSIIoReqCompleted(hVScsiIoReq, rc);
     224    if (RT_SUCCESS(rc))
     225        VSCSIIoReqCompleted(hVScsiIoReq, rc, false /* fRedoPossible */);
     226    else
     227        VSCSIIoReqCompleted(hVScsiIoReq, rc, drvscsiIsRedoPossible(rc));
    211228
    212229    return VINF_SUCCESS;
     
    296313                AssertMsg(enmTxDir == VSCSIIOREQTXDIR_FLUSH, ("Invalid transfer direction %u\n", enmTxDir));
    297314
    298             VSCSIIoReqCompleted(hVScsiIoReq, VINF_SUCCESS);
     315            VSCSIIoReqCompleted(hVScsiIoReq, VINF_SUCCESS, false);
    299316        }
    300317        else if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
     
    309326                AssertMsg(enmTxDir == VSCSIIOREQTXDIR_FLUSH, ("Invalid transfer direction %u\n", enmTxDir));
    310327
    311             VSCSIIoReqCompleted(hVScsiIoReq, rc);
     328            VSCSIIoReqCompleted(hVScsiIoReq, rc, drvscsiIsRedoPossible(rc));
    312329            rc = VINF_SUCCESS;
    313330        }
     
    326343
    327344static void drvscsiVScsiReqCompleted(VSCSIDEVICE hVScsiDevice, void *pVScsiDeviceUser,
    328                                      void *pVScsiReqUser, int rcReq)
     345                                     void *pVScsiReqUser, int rcScsiCode, bool fRedoPossible,
     346                                     int rcReq)
    329347{
    330348    PDRVSCSI pThis = (PDRVSCSI)pVScsiDeviceUser;
     
    333351
    334352    pThis->pDevScsiPort->pfnSCSIRequestCompleted(pThis->pDevScsiPort, (PPDMSCSIREQUEST)pVScsiReqUser,
    335                                                  rcReq);
     353                                                 rcScsiCode, fRedoPossible, rcReq);
    336354
    337355    if (RT_UNLIKELY(pThis->fDummySignal) && !pThis->StatIoDepth)
  • trunk/src/VBox/Devices/Storage/DrvSCSIHost.cpp

    r28800 r32983  
    316316    }
    317317    /* Notify device that request finished. */
    318     rc = pThis->pDevScsiPort->pfnSCSIRequestCompleted(pThis->pDevScsiPort, pRequest, SCSI_STATUS_OK);
     318    rc = pThis->pDevScsiPort->pfnSCSIRequestCompleted(pThis->pDevScsiPort, pRequest, SCSI_STATUS_OK, false, VINF_SUCCESS);
    319319    AssertMsgRC(rc, ("Notifying device above failed rc=%Rrc\n", rc));
    320320
  • trunk/src/VBox/Devices/Storage/UsbMsd.cpp

    r28800 r32983  
    746746 * @interface_method_impl{PDMISCSIPORT,pfnSCSIRequestCompleted}
    747747 */
    748 static DECLCALLBACK(int) usbMsdLun0ScsiRequestCompleted(PPDMISCSIPORT pInterface, PPDMSCSIREQUEST pSCSIRequest, int rcCompletion)
     748static DECLCALLBACK(int) usbMsdLun0ScsiRequestCompleted(PPDMISCSIPORT pInterface, PPDMSCSIREQUEST pSCSIRequest,
     749                                                        int rcCompletion, bool fRedo, int rcReq)
    749750{
    750751    PUSBMSD     pThis = RT_FROM_MEMBER(pInterface, USBMSD, Lun0.IScsiPort);
     
    894895    pReq->ScsiReqSense[13] = 0; /* Should be ASCQ but it has the same value for success. */
    895896
    896     usbMsdLun0ScsiRequestCompleted(&pThis->Lun0.IScsiPort, &pReq->ScsiReq, SCSI_STATUS_CHECK_CONDITION);
     897    usbMsdLun0ScsiRequestCompleted(&pThis->Lun0.IScsiPort, &pReq->ScsiReq, SCSI_STATUS_CHECK_CONDITION, false, VINF_SUCCESS);
    897898    return VINF_SUCCESS;
    898899}
     
    946947
    947948    /* Do normal completion.  */
    948     usbMsdLun0ScsiRequestCompleted(&pThis->Lun0.IScsiPort, &pReq->ScsiReq, SCSI_STATUS_OK);
     949    usbMsdLun0ScsiRequestCompleted(&pThis->Lun0.IScsiPort, &pReq->ScsiReq, SCSI_STATUS_OK, false, VINF_SUCCESS);
    949950    return VINF_SUCCESS;
    950951}
     
    12741275                LogFlow(("usbMsdHandleBulkDevToHost: Added %p:%s to the to-host queue\n", pUrb, pUrb->pszDesc));
    12751276
    1276                 usbMsdLun0ScsiRequestCompleted(&pThis->Lun0.IScsiPort, &pReq->ScsiReq, SCSI_STATUS_OK);
     1277                usbMsdLun0ScsiRequestCompleted(&pThis->Lun0.IScsiPort, &pReq->ScsiReq, SCSI_STATUS_OK, false, VINF_SUCCESS);
    12771278                return VINF_SUCCESS;
    12781279            }
  • trunk/src/VBox/Devices/Storage/VBoxSCSI.cpp

    r28800 r32983  
    271271    if (pVBoxSCSI->uTxDir == VBOXSCSI_TXDIR_FROM_DEVICE)
    272272    {
    273         Assert(!pVBoxSCSI->pBuf);
     273        if (pVBoxSCSI->pBuf)
     274            RTMemFree(pVBoxSCSI->pBuf);
     275
    274276        pVBoxSCSI->pBuf = (uint8_t *)RTMemAllocZ(pVBoxSCSI->cbBuf);
    275277        if (!pVBoxSCSI->pBuf)
     
    277279    }
    278280
    279     /** Allocate scatter gather element. */
     281    /* Allocate scatter gather element. */
    280282    pScsiRequest->paScatterGatherHead = (PRTSGSEG)RTMemAllocZ(sizeof(RTSGSEG) * 1); /* Only one element. */
    281283    if (!pScsiRequest->paScatterGatherHead)
     
    286288    }
    287289
    288     /** Allocate sense buffer. */
     290    /* Allocate sense buffer. */
    289291    pScsiRequest->cbSenseBuffer = 18;
    290292    pScsiRequest->pbSenseBuffer = (uint8_t *)RTMemAllocZ(pScsiRequest->cbSenseBuffer);
     
    385387}
    386388
     389void vboxscsiSetRequestRedo(PVBOXSCSI pVBoxSCSI, PPDMSCSIREQUEST pScsiRequest)
     390{
     391    AssertMsg(pVBoxSCSI->fBusy, ("No request to redo\n"));
     392
     393    RTMemFree(pScsiRequest->paScatterGatherHead);
     394    RTMemFree(pScsiRequest->pbSenseBuffer);
     395
     396    if (pVBoxSCSI->uTxDir == VBOXSCSI_TXDIR_FROM_DEVICE)
     397    {
     398        AssertPtr(pVBoxSCSI->pBuf);
     399    }
     400}
     401
  • trunk/src/VBox/Devices/Storage/VBoxSCSI.h

    r28800 r32983  
    124124int vboxscsiSetupRequest(PVBOXSCSI pVBoxSCSI, PPDMSCSIREQUEST pScsiRequest, uint32_t *puTargetDevice);
    125125int vboxscsiRequestFinished(PVBOXSCSI pVBoxSCSI, PPDMSCSIREQUEST pScsiRequest);
     126void vboxscsiSetRequestRedo(PVBOXSCSI pVBoxSCSI, PPDMSCSIREQUEST pScsiRequest);
    126127int vboxscsiWriteString(PPDMDEVINS pDevIns, PVBOXSCSI pVBoxSCSI, uint8_t iRegister,
    127128                        RTGCPTR *pGCPtrSrc, PRTGCUINTREG pcTransfer, unsigned cb);
  • trunk/src/VBox/Devices/Storage/VSCSI/VSCSIDevice.cpp

    r28800 r32983  
    109109}
    110110
    111 /**
    112  * Completesa SCSI request and calls the completion handler.
    113  *
    114  * @returns nothing.
    115  * @param   pVScsiDevice    The virtual SCSI device.
    116  * @param   pVScsiReq       The request which completed.
    117  * @param   rcReq           The status code
    118  *                          One of the SCSI_STATUS_* #defines.
    119  */
     111
    120112void vscsiDeviceReqComplete(PVSCSIDEVICEINT pVScsiDevice, PVSCSIREQINT pVScsiReq,
    121                             int rcReq)
     113                            int rcScsiCode, bool fRedoPossible, int rcReq)
    122114{
    123115    pVScsiDevice->pfnVScsiReqCompleted(pVScsiDevice, pVScsiDevice->pvVScsiDeviceUser,
    124                                        pVScsiReq->pvVScsiReqUser, rcReq);
     116                                       pVScsiReq->pvVScsiReqUser, rcScsiCode, fRedoPossible,
     117                                       rcReq);
    125118
    126119    RTMemCacheFree(pVScsiDevice->hCacheReq, pVScsiReq);
     
    294287
    295288            vscsiDeviceReqComplete(pVScsiDevice, pVScsiReq,
    296                                    SCSI_STATUS_CHECK_CONDITION);
     289                                   SCSI_STATUS_CHECK_CONDITION, false, VINF_SUCCESS);
    297290        }
    298291    }
    299292    else
    300293        vscsiDeviceReqComplete(pVScsiDevice, pVScsiReq,
    301                                rcReq);
     294                               rcReq, false, VINF_SUCCESS);
    302295
    303296    return rc;
  • trunk/src/VBox/Devices/Storage/VSCSI/VSCSIInternal.h

    r28800 r32983  
    189189 * @param   pVScsiDevice    The virtual SCSI device.
    190190 * @param   pVScsiReq       The request which completed.
    191  * @param   rcReq           The status code
     191 * @param   rcScsiCode      The status code
    192192 *                          One of the SCSI_STATUS_* #defines.
     193 * @param   fRedoPossible   Flag whether redo is possible.
     194 * @param   rcReq           Informational return code of the request.
    193195 */
    194196void vscsiDeviceReqComplete(PVSCSIDEVICEINT pVScsiDevice, PVSCSIREQINT pVScsiReq,
    195                             int rcReq);
     197                            int rcScsiCode, bool fRedoPossible, int rcReq);
    196198
    197199/**
  • trunk/src/VBox/Devices/Storage/VSCSI/VSCSIIoReq.cpp

    r28800 r32983  
    9393
    9494
    95 VBOXDDU_DECL(int) VSCSIIoReqCompleted(VSCSIIOREQ hVScsiIoReq, int rcIoReq)
     95VBOXDDU_DECL(int) VSCSIIoReqCompleted(VSCSIIOREQ hVScsiIoReq, int rcIoReq, bool fRedoPossible)
    9696{
    9797    PVSCSIIOREQINT pVScsiIoReq = hVScsiIoReq;
     
    115115    if (RT_SUCCESS(rcIoReq))
    116116        rcReq = vscsiReqSenseOkSet(pVScsiReq);
     117    else if (!fRedoPossible)
     118    {
     119        /** @todo Not 100% correct for the write case as the 0x00 ASCQ for write errors
     120         * is not used for SBC devices. */
     121        rcReq = vscsiReqSenseErrorSet(pVScsiReq, SCSI_SENSE_MEDIUM_ERROR,
     122                                      pVScsiIoReq->enmTxDir == VSCSIIOREQTXDIR_READ
     123                                      ? SCSI_ASC_READ_ERROR
     124                                      : SCSI_ASC_WRITE_ERROR);
     125    }
     126    else
     127        rcReq = SCSI_STATUS_CHECK_CONDITION;
    117128
    118129    /* Free the I/O request */
     
    120131
    121132    /* Notify completion of the SCSI request. */
    122     vscsiDeviceReqComplete(pVScsiLun->pVScsiDevice, pVScsiReq, rcReq);
     133    vscsiDeviceReqComplete(pVScsiLun->pVScsiDevice, pVScsiReq, rcReq, fRedoPossible, rcIoReq);
    123134
    124135    return VINF_SUCCESS;
  • trunk/src/VBox/Devices/Storage/VSCSI/VSCSILunSbc.cpp

    r30174 r32983  
    302302        {
    303303            rcReq = vscsiReqSenseErrorSet(pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
    304             vscsiDeviceReqComplete(pVScsiLun->pVScsiDevice, pVScsiReq, rcReq);
     304            vscsiDeviceReqComplete(pVScsiLun->pVScsiDevice, pVScsiReq, rcReq, false, VINF_SUCCESS);
    305305        }
    306306        else
     
    317317    }
    318318    else /* Request completed */
    319         vscsiDeviceReqComplete(pVScsiLun->pVScsiDevice, pVScsiReq, rcReq);
     319        vscsiDeviceReqComplete(pVScsiLun->pVScsiDevice, pVScsiReq, rcReq, false, VINF_SUCCESS);
    320320
    321321    return rc;
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