VirtualBox

Changeset 32944 in vbox


Ignore:
Timestamp:
Oct 6, 2010 1:46:06 PM (14 years ago)
Author:
vboxsync
Message:

Storage/ATAController: Clean up suspending the VM on certain errors, and make sure that a paused VM can be powered off straight away. This brings this code part in sync with DevATA.cpp. Some release logging changes for better consistency/readability.

File:
1 edited

Legend:

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

    r30723 r32944  
    77
    88/*
    9  * Copyright (C) 2006-2009 Oracle Corporation
     9 * Copyright (C) 2006-2010 Oracle Corporation
    1010 *
    1111 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    308308    rc = RTSemMutexRequest(pCtl->AsyncIORequestMutex, RT_INDEFINITE_WAIT);
    309309    AssertRC(rc);
    310     LogRel(("ATA: Ctl: request queue dump (topmost is current):\n"));
     310    LogRel(("AHCI ATA: Ctl: request queue dump (topmost is current):\n"));
    311311    curr = pCtl->AsyncIOReqTail;
    312312    do
    313313    {
    314314        if (curr == pCtl->AsyncIOReqHead)
    315             LogRel(("ATA: Ctl: processed requests (topmost is oldest):\n"));
     315            LogRel(("AHCI ATA: Ctl: processed requests (topmost is oldest):\n"));
    316316        switch (pCtl->aAsyncIORequests[curr].ReqType)
    317317        {
     
    963963
    964964
    965 static int ataReadSectors(AHCIATADevState *s, uint64_t u64Sector, void *pvBuf, uint32_t cSectors)
     965static void ataWarningDiskFull(PPDMDEVINS pDevIns)
     966{
     967    int rc;
     968    LogRel(("AHCI ATA: Host disk full\n"));
     969    rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevATA_DISKFULL",
     970                                    N_("Host system reported disk full. VM execution is suspended. You can resume after freeing some space"));
     971    AssertRC(rc);
     972}
     973
     974static void ataWarningFileTooBig(PPDMDEVINS pDevIns)
     975{
     976    int rc;
     977    LogRel(("AHCI ATA: File too big\n"));
     978    rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevATA_FILETOOBIG",
     979                                    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"));
     980    AssertRC(rc);
     981}
     982
     983static void ataWarningISCSI(PPDMDEVINS pDevIns)
     984{
     985    int rc;
     986    LogRel(("AHCI ATA: iSCSI target unavailable\n"));
     987    rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevATA_ISCSIDOWN",
     988                                    N_("The iSCSI target has stopped responding. VM execution is suspended. You can resume when it is available again"));
     989    AssertRC(rc);
     990}
     991
     992static bool ataIsRedoSetWarning(AHCIATADevState *s, int rc)
     993{
     994    PAHCIATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s);
     995    Assert(!PDMCritSectIsOwner(&pCtl->lock));
     996    if (rc == VERR_DISK_FULL)
     997    {
     998        pCtl->fRedoIdle = true;
     999        ataWarningDiskFull(ATADEVSTATE_2_DEVINS(s));
     1000        return true;
     1001    }
     1002    if (rc == VERR_FILE_TOO_BIG)
     1003    {
     1004        pCtl->fRedoIdle = true;
     1005        ataWarningFileTooBig(ATADEVSTATE_2_DEVINS(s));
     1006        return true;
     1007    }
     1008    if (rc == VERR_BROKEN_PIPE || rc == VERR_NET_CONNECTION_REFUSED)
     1009    {
     1010        pCtl->fRedoIdle = true;
     1011        /* iSCSI connection abort (first error) or failure to reestablish
     1012         * connection (second error). Pause VM. On resume we'll retry. */
     1013        ataWarningISCSI(ATADEVSTATE_2_DEVINS(s));
     1014        return true;
     1015    }
     1016    return false;
     1017}
     1018
     1019
     1020static int ataReadSectors(AHCIATADevState *s, uint64_t u64Sector, void *pvBuf,
     1021                          uint32_t cSectors, bool *pfRedo)
    9661022{
    9671023    PAHCIATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s);
     
    9781034    STAM_REL_COUNTER_ADD(s->pStatBytesRead, cSectors * 512);
    9791035
     1036    if (RT_SUCCESS(rc))
     1037        *pfRedo = false;
     1038    else
     1039        *pfRedo = ataIsRedoSetWarning(s, rc);
     1040
    9801041    STAM_PROFILE_START(&pCtl->StatLockWait, a);
    9811042    PDMCritSectEnter(&pCtl->lock, VINF_SUCCESS);
     
    9851046
    9861047
    987 static int ataWriteSectors(AHCIATADevState *s, uint64_t u64Sector, const void *pvBuf, uint32_t cSectors)
     1048static int ataWriteSectors(AHCIATADevState *s, uint64_t u64Sector,
     1049                           const void *pvBuf, uint32_t cSectors, bool *pfRedo)
    9881050{
    9891051    PAHCIATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s);
     
    9991061
    10001062    STAM_REL_COUNTER_ADD(s->pStatBytesWritten, cSectors * 512);
     1063
     1064    if (RT_SUCCESS(rc))
     1065        *pfRedo = false;
     1066    else
     1067        *pfRedo = ataIsRedoSetWarning(s, rc);
    10011068
    10021069    STAM_PROFILE_START(&pCtl->StatLockWait, a);
     
    10211088
    10221089
    1023 static void ataWarningDiskFull(PPDMDEVINS pDevIns)
    1024 {
    1025     int rc;
    1026     LogRel(("ATA: Host disk full\n"));
    1027     rc = PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "DevATA_DISKFULL",
    1028                                     N_("Host system reported disk full. VM execution is suspended. You can resume after freeing some space"));
    1029     AssertRC(rc);
    1030 }
    1031 
    1032 
    1033 static void ataWarningFileTooBig(PPDMDEVINS pDevIns)
    1034 {
    1035     int rc;
    1036     LogRel(("ATA: File too big\n"));
    1037     rc = PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "DevATA_FILETOOBIG",
    1038                                     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"));
    1039     AssertRC(rc);
    1040 }
    1041 
    1042 
    1043 static void ataWarningISCSI(PPDMDEVINS pDevIns)
    1044 {
    1045     int rc;
    1046     LogRel(("ATA: iSCSI target unavailable\n"));
    1047     rc = PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "DevATA_ISCSIDOWN",
    1048                                     N_("The iSCSI target has stopped responding. VM execution is suspended. You can resume when it is available again"));
    1049     AssertRC(rc);
    1050 }
    1051 
    1052 
    10531090static bool ataReadSectorsSS(AHCIATADevState *s)
    10541091{
     
    10561093    uint32_t cSectors;
    10571094    uint64_t iLBA;
     1095    bool fRedo;
    10581096
    10591097    cSectors = s->cbElementaryTransfer / 512;
     
    10611099    iLBA = ataGetSector(s);
    10621100    Log(("%s: %d sectors at LBA %d\n", __FUNCTION__, cSectors, iLBA));
    1063     rc = ataReadSectors(s, iLBA, s->CTXALLSUFF(pbIOBuffer), cSectors);
     1101    rc = ataReadSectors(s, iLBA, s->CTXALLSUFF(pbIOBuffer), cSectors, &fRedo);
    10641102    if (RT_SUCCESS(rc))
    10651103    {
     
    10711109    else
    10721110    {
    1073         if (rc == VERR_DISK_FULL)
    1074         {
    1075             ataWarningDiskFull(ATADEVSTATE_2_DEVINS(s));
     1111        if (fRedo)
    10761112            return true;
    1077         }
    1078         if (rc == VERR_FILE_TOO_BIG)
    1079         {
    1080             ataWarningFileTooBig(ATADEVSTATE_2_DEVINS(s));
    1081             return true;
    1082         }
    1083         if (rc == VERR_BROKEN_PIPE || rc == VERR_NET_CONNECTION_REFUSED)
    1084         {
    1085             /* iSCSI connection abort (first error) or failure to reestablish
    1086              * connection (second error). Pause VM. On resume we'll retry. */
    1087             ataWarningISCSI(ATADEVSTATE_2_DEVINS(s));
    1088             return true;
    1089         }
    10901113        if (s->cErrors++ < MAX_LOG_REL_ERRORS)
    10911114            LogRel(("AHCI ATA: LUN#%d: disk read error (rc=%Rrc iSector=%#RX64 cSectors=%#RX32)\n",
     
    10931116        ataCmdError(s, ID_ERR);
    10941117    }
    1095     /** @todo implement redo for iSCSI */
    10961118    return false;
    10971119}
     
    11031125    uint32_t cSectors;
    11041126    uint64_t iLBA;
     1127    bool fRedo;
    11051128
    11061129    cSectors = s->cbElementaryTransfer / 512;
     
    11081131    iLBA = ataGetSector(s);
    11091132    Log(("%s: %d sectors at LBA %d\n", __FUNCTION__, cSectors, iLBA));
    1110     rc = ataWriteSectors(s, iLBA, s->CTXALLSUFF(pbIOBuffer), cSectors);
     1133    rc = ataWriteSectors(s, iLBA, s->CTXALLSUFF(pbIOBuffer), cSectors, &fRedo);
    11111134    if (RT_SUCCESS(rc))
    11121135    {
     
    11181141    else
    11191142    {
    1120         if (rc == VERR_DISK_FULL)
    1121         {
    1122             ataWarningDiskFull(ATADEVSTATE_2_DEVINS(s));
     1143        if (fRedo)
    11231144            return true;
    1124         }
    1125         if (rc == VERR_FILE_TOO_BIG)
    1126         {
    1127             ataWarningFileTooBig(ATADEVSTATE_2_DEVINS(s));
    1128             return true;
    1129         }
    1130         if (rc == VERR_BROKEN_PIPE || rc == VERR_NET_CONNECTION_REFUSED)
    1131         {
    1132             /* iSCSI connection abort (first error) or failure to reestablish
    1133              * connection (second error). Pause VM. On resume we'll retry. */
    1134             ataWarningISCSI(ATADEVSTATE_2_DEVINS(s));
    1135             return true;
    1136         }
    11371145        if (s->cErrors++ < MAX_LOG_REL_ERRORS)
    11381146            LogRel(("AHCI ATA: LUN#%d: disk write error (rc=%Rrc iSector=%#RX64 cSectors=%#RX32)\n",
     
    11401148        ataCmdError(s, ID_ERR);
    11411149    }
    1142     /** @todo implement redo for iSCSI */
    11431150    return false;
    11441151}
     
    27672774        return;
    27682775
    2769     LogRel(("ATA: LUN#%d: CD/DVD, total number of sectors %Ld, passthrough unchanged\n", pIf->iLUN, pIf->cTotalSectors));
     2776    LogRel(("AHCI ATA: LUN#%d: CD/DVD, total number of sectors %Ld, passthrough unchanged\n", pIf->iLUN, pIf->cTotalSectors));
    27702777
    27712778    if (pIf->fATAPI)
     
    34053412        if (pCtl->aIfs[1].u64CmdTS)
    34063413            uCmdWait1 = (uNow - pCtl->aIfs[1].u64CmdTS) / 1000;
    3407         LogRel(("ATA: Ctl: RESET, DevSel=%d AIOIf=%d CmdIf0=%#04x (%d usec ago) CmdIf1=%#04x (%d usec ago)\n",
     3414        LogRel(("AHCI ATA: Ctl: RESET, DevSel=%d AIOIf=%d CmdIf0=%#04x (%d usec ago) CmdIf1=%#04x (%d usec ago)\n",
    34083415                    pCtl->iSelectedIf, pCtl->iAIOIf,
    34093416                    pCtl->aIfs[0].uATARegCommand, uCmdWait0,
     
    38233830        if (!(pCtl->BmDma.u8Cmd & BM_CMD_START) || pCtl->fReset)
    38243831        {
    3825             LogRel(("ATA: Ctl: ABORT DMA%s\n", pCtl->fReset ? " due to RESET" : ""));
     3832            LogRel(("AHCI ATA: Ctl: ABORT DMA%s\n", pCtl->fReset ? " due to RESET" : ""));
    38263833            if (!pCtl->fReset)
    38273834                ataDMATransferStop(s);
     
    38483855    s->iIOBufferCur = iIOBufferCur;
    38493856    s->iIOBufferEnd = iIOBufferEnd;
    3850 }
    3851 
    3852 
    3853 /**
    3854  * Suspend I/O operations on a controller. Also suspends EMT, because it's
    3855  * waiting for I/O to make progress. The next attempt to perform an I/O
    3856  * operation will be made when EMT is resumed up again (as the resume
    3857  * callback below restarts I/O).
    3858  *
    3859  * @param pCtl      Controller for which to suspend I/O.
    3860  */
    3861 static void ataSuspendRedo(PAHCIATACONTROLLER pCtl)
    3862 {
    3863     PPDMDEVINS  pDevIns = CONTROLLER_2_DEVINS(pCtl);
    3864     int         rc;
    3865 
    3866     pCtl->fRedoIdle = true;
    3867     rc = VMR3ReqCallWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY,
    3868                          (PFNRT)PDMDevHlpVMSuspend, 1, pDevIns);
    3869     AssertReleaseRC(rc);
    38703857}
    38713858
     
    40364023                            LogRel(("%s: Ctl: redo entire operation\n", __FUNCTION__));
    40374024                            ataAsyncIOPutRequest(pCtl, pReq);
    4038                             ataSuspendRedo(pCtl);
    40394025                            break;
    40404026                        }
     
    41394125                if (RT_UNLIKELY(pCtl->fRedo))
    41404126                {
    4141                     LogRel(("ATA: Ctl: redo DMA operation\n"));
     4127                    LogRel(("AHCI ATA: Ctl: redo DMA operation\n"));
    41424128                    ataAsyncIOPutRequest(pCtl, &ataDMARequest);
    4143                     ataSuspendRedo(pCtl);
    41444129                    break;
    41454130                }
     
    41854170                    if (RT_UNLIKELY(fRedo))
    41864171                    {
    4187                         LogRel(("ATA: Ctl#%d: redo PIO operation\n"));
     4172                        LogRel(("AHCI ATA: Ctl#%d: redo PIO operation\n"));
    41884173                        ataAsyncIOPutRequest(pCtl, &ataPIORequest);
    4189                         ataSuspendRedo(pCtl);
    41904174                        break;
    41914175                    }
     
    42584242                pCtl->uAsyncIOState = AHCIATA_AIO_NEW;
    42594243                pCtl->fReset = false;
    4260                 LogRel(("ATA: Ctl: finished processing RESET\n"));
     4244                LogRel(("AHCI ATA: Ctl: finished processing RESET\n"));
    42614245                for (uint32_t i = 0; i < RT_ELEMENTS(pCtl->aIfs); i++)
    42624246                {
     
    48684852
    48694853    if (!fAllIdle)
    4870         LogRel(("ATA: Ctl is still executing, DevSel=%d AIOIf=%d CmdIf0=%#04x CmdIf1=%#04x\n",
     4854        LogRel(("AHCI ATA: Ctl is still executing, DevSel=%d AIOIf=%d CmdIf0=%#04x CmdIf1=%#04x\n",
    48714855                pCtl->iSelectedIf, pCtl->iAIOIf,
    48724856                pCtl->aIfs[0].uATARegCommand, pCtl->aIfs[1].uATARegCommand));
     
    49214905        ASMAtomicWriteU32(&pCtl->fShutdown, true);
    49224906        rc = RTSemEventSignal(pCtl->AsyncIOSem);
     4907        AssertRC(rc);
     4908        rc = RTSemEventSignal(pCtl->SuspendIOSem);
    49234909        AssertRC(rc);
    49244910
     
    50835069        pIf->PCHSGeometry.cHeads     = 0; /* dummy */
    50845070        pIf->PCHSGeometry.cSectors   = 0; /* dummy */
    5085         LogRel(("ATA: LUN#%d: CD/DVD, total number of sectors %Ld, passthrough %s\n", pIf->iLUN, pIf->cTotalSectors, (pIf->fATAPIPassthrough ? "enabled" : "disabled")));
     5071        LogRel(("AHCI ATA: LUN#%d: CD/DVD, total number of sectors %Ld, passthrough %s\n", pIf->iLUN, pIf->cTotalSectors, (pIf->fATAPIPassthrough ? "enabled" : "disabled")));
    50865072    }
    50875073    else
     
    54035389            else
    54045390            {
    5405                 LogRel(("ATA: No buffer for %d\n", j));
     5391                LogRel(("AHCI ATA: No buffer for %d\n", j));
    54065392                if (SSMR3HandleGetAfter(pSSM) != SSMAFTER_DEBUG_IT)
    54075393                    return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("No buffer for %d"), j);
Note: See TracChangeset for help on using the changeset viewer.

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