Changeset 71775 in vbox for trunk/src/VBox/Devices/Storage
- Timestamp:
- Apr 9, 2018 2:54:57 PM (7 years ago)
- Location:
- trunk/src/VBox/Devices/Storage
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevAHCI.cpp
r70687 r71775 5412 5412 else 5413 5413 ASMAtomicWriteBool(&pThis->fSignalIdle, false); 5414 5415 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->ahciPort); i++) 5416 { 5417 PAHCIPort pThisPort = &pThis->ahciPort[i]; 5418 if (pThisPort->pDrvMediaEx) 5419 pThisPort->pDrvMediaEx->pfnNotifySuspend(pThisPort->pDrvMediaEx); 5420 } 5414 5421 } 5415 5422 -
trunk/src/VBox/Devices/Storage/DevBusLogic.cpp
r69500 r71775 3857 3857 AssertMsg(!pThis->fNotificationSent, ("The PDM Queue should be empty at this point\n")); 3858 3858 } 3859 3860 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aDeviceStates); i++) 3861 { 3862 PBUSLOGICDEVICE pThisDevice = &pThis->aDeviceStates[i]; 3863 if (pThisDevice->pDrvMediaEx) 3864 pThisDevice->pDrvMediaEx->pfnNotifySuspend(pThisDevice->pDrvMediaEx); 3865 } 3859 3866 } 3860 3867 -
trunk/src/VBox/Devices/Storage/DevLsiLogicSCSI.cpp
r69500 r71775 5137 5137 AssertMsg(!pThis->fNotificationSent, ("The PDM Queue should be empty at this point\n")); 5138 5138 } 5139 5140 for (uint32_t i = 0; i < pThis->cDeviceStates; i++) 5141 { 5142 PLSILOGICDEVICE pThisDevice = &pThis->paDeviceStates[i]; 5143 if (pThisDevice->pDrvMediaEx) 5144 pThisDevice->pDrvMediaEx->pfnNotifySuspend(pThisDevice->pDrvMediaEx); 5145 } 5139 5146 } 5140 5147 -
trunk/src/VBox/Devices/Storage/DrvVD.cpp
r70775 r71775 342 342 /** Flag whether this medium should be presented as non rotational. */ 343 343 bool fNonRotational; 344 /** Flag whether a suspend is in progress right now. */ 345 volatile bool fSuspending; 344 346 #ifdef VBOX_PERIODIC_FLUSH 345 347 /** HACK: Configuration value for number of bytes written after which to flush. */ … … 3151 3153 RTCritSectEnter(&pThis->CritSectIoReqsIoBufWait); 3152 3154 RTListAppend(&pThis->LstIoReqIoBufWait, &pIoReq->NdLstWait); 3155 ASMAtomicIncU32(&pThis->cIoReqsWaiting); 3156 if (ASMAtomicReadBool(&pThis->fSuspending)) 3157 pThis->pDrvMediaExPort->pfnIoReqStateChanged(pThis->pDrvMediaExPort, pIoReq, &pIoReq->abAlloc[0], 3158 PDMMEDIAEXIOREQSTATE_SUSPENDED); 3153 3159 RTCritSectLeave(&pThis->CritSectIoReqsIoBufWait); 3154 ASMAtomicIncU32(&pThis->cIoReqsWaiting);3155 3160 rc = VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS; 3156 3161 } … … 3412 3417 3413 3418 /** 3419 * Tries to process any requests waiting for available I/O memory. 3420 * 3421 * @returns nothing. 3422 * @param pThis VBox disk container instance data. 3423 */ 3424 static void drvvdMediaExIoReqProcessWaiting(PVBOXDISK pThis) 3425 { 3426 uint32_t cIoReqsWaiting = ASMAtomicXchgU32(&pThis->cIoReqsWaiting, 0); 3427 if (cIoReqsWaiting > 0) 3428 { 3429 RTLISTANCHOR LstIoReqProcess; 3430 RTLISTANCHOR LstIoReqCanceled; 3431 RTListInit(&LstIoReqProcess); 3432 RTListInit(&LstIoReqCanceled); 3433 3434 /* Try to process as many requests as possible. */ 3435 RTCritSectEnter(&pThis->CritSectIoReqsIoBufWait); 3436 PPDMMEDIAEXIOREQINT pIoReqCur, pIoReqNext; 3437 3438 RTListForEachSafe(&pThis->LstIoReqIoBufWait, pIoReqCur, pIoReqNext, PDMMEDIAEXIOREQINT, NdLstWait) 3439 { 3440 LogFlowFunc(("Found I/O request %#p on waiting list, trying to allocate buffer of size %zu bytes\n", 3441 pIoReqCur, pIoReqCur->ReadWrite.cbReq)); 3442 3443 /* Allocate a suitable I/O buffer for this request. */ 3444 int rc = IOBUFMgrAllocBuf(pThis->hIoBufMgr, &pIoReqCur->ReadWrite.IoBuf, pIoReqCur->ReadWrite.cbReq, 3445 &pIoReqCur->ReadWrite.cbIoBuf); 3446 if (rc == VINF_SUCCESS) 3447 { 3448 Assert(pIoReqCur->ReadWrite.cbIoBuf > 0); 3449 3450 cIoReqsWaiting--; 3451 RTListNodeRemove(&pIoReqCur->NdLstWait); 3452 3453 pIoReqCur->ReadWrite.fDirectBuf = false; 3454 pIoReqCur->ReadWrite.pSgBuf = &pIoReqCur->ReadWrite.IoBuf.SgBuf; 3455 3456 bool fXchg = ASMAtomicCmpXchgU32((volatile uint32_t *)&pIoReqCur->enmState, 3457 VDIOREQSTATE_ACTIVE, VDIOREQSTATE_ALLOCATED); 3458 if (RT_UNLIKELY(!fXchg)) 3459 { 3460 /* Must have been canceled inbetween. */ 3461 Assert(pIoReqCur->enmState == VDIOREQSTATE_CANCELED); 3462 3463 /* Free the buffer here already again to let other requests get a chance to allocate the memory. */ 3464 IOBUFMgrFreeBuf(&pIoReqCur->ReadWrite.IoBuf); 3465 pIoReqCur->ReadWrite.cbIoBuf = 0; 3466 RTListAppend(&LstIoReqCanceled, &pIoReqCur->NdLstWait); 3467 } 3468 else 3469 { 3470 ASMAtomicIncU32(&pThis->cIoReqsActive); 3471 RTListAppend(&LstIoReqProcess, &pIoReqCur->NdLstWait); 3472 } 3473 } 3474 else 3475 { 3476 Assert(rc == VERR_NO_MEMORY); 3477 break; 3478 } 3479 } 3480 RTCritSectLeave(&pThis->CritSectIoReqsIoBufWait); 3481 3482 ASMAtomicAddU32(&pThis->cIoReqsWaiting, cIoReqsWaiting); 3483 3484 /* Process the requests we could allocate memory for and the ones which got canceled outside the lock now. */ 3485 RTListForEachSafe(&LstIoReqCanceled, pIoReqCur, pIoReqNext, PDMMEDIAEXIOREQINT, NdLstWait) 3486 { 3487 RTListNodeRemove(&pIoReqCur->NdLstWait); 3488 drvvdMediaExIoReqCompleteWorker(pThis, pIoReqCur, VERR_PDM_MEDIAEX_IOREQ_CANCELED, true /* fUpNotify */); 3489 } 3490 3491 RTListForEachSafe(&LstIoReqProcess, pIoReqCur, pIoReqNext, PDMMEDIAEXIOREQINT, NdLstWait) 3492 { 3493 RTListNodeRemove(&pIoReqCur->NdLstWait); 3494 drvvdMediaExIoReqReadWriteProcess(pThis, pIoReqCur, true /* fUpNotify */); 3495 } 3496 } 3497 } 3498 3499 /** 3414 3500 * Frees a I/O memory buffer allocated previously. 3415 3501 * … … 3429 3515 IOBUFMgrFreeBuf(&pIoReq->ReadWrite.IoBuf); 3430 3516 3431 uint32_t cIoReqsWaiting = ASMAtomicXchgU32(&pThis->cIoReqsWaiting, 0); 3432 if (cIoReqsWaiting > 0) 3433 { 3434 RTLISTANCHOR LstIoReqProcess; 3435 RTLISTANCHOR LstIoReqCanceled; 3436 RTListInit(&LstIoReqProcess); 3437 RTListInit(&LstIoReqCanceled); 3438 3439 /* Try to process as many requests as possible. */ 3440 RTCritSectEnter(&pThis->CritSectIoReqsIoBufWait); 3441 PPDMMEDIAEXIOREQINT pIoReqCur, pIoReqNext; 3442 3443 RTListForEachSafe(&pThis->LstIoReqIoBufWait, pIoReqCur, pIoReqNext, PDMMEDIAEXIOREQINT, NdLstWait) 3444 { 3445 LogFlowFunc(("Found I/O request %#p on waiting list, trying to allocate buffer of size %zu bytes\n", 3446 pIoReqCur, pIoReqCur->ReadWrite.cbReq)); 3447 3448 /* Allocate a suitable I/O buffer for this request. */ 3449 int rc = IOBUFMgrAllocBuf(pThis->hIoBufMgr, &pIoReqCur->ReadWrite.IoBuf, pIoReqCur->ReadWrite.cbReq, 3450 &pIoReqCur->ReadWrite.cbIoBuf); 3451 if (rc == VINF_SUCCESS) 3452 { 3453 Assert(pIoReqCur->ReadWrite.cbIoBuf > 0); 3454 3455 cIoReqsWaiting--; 3456 RTListNodeRemove(&pIoReqCur->NdLstWait); 3457 3458 pIoReqCur->ReadWrite.fDirectBuf = false; 3459 pIoReqCur->ReadWrite.pSgBuf = &pIoReqCur->ReadWrite.IoBuf.SgBuf; 3460 3461 bool fXchg = ASMAtomicCmpXchgU32((volatile uint32_t *)&pIoReqCur->enmState, 3462 VDIOREQSTATE_ACTIVE, VDIOREQSTATE_ALLOCATED); 3463 if (RT_UNLIKELY(!fXchg)) 3464 { 3465 /* Must have been canceled inbetween. */ 3466 Assert(pIoReqCur->enmState == VDIOREQSTATE_CANCELED); 3467 3468 /* Free the buffer here already again to let other requests get a chance to allocate the memory. */ 3469 IOBUFMgrFreeBuf(&pIoReq->ReadWrite.IoBuf); 3470 pIoReqCur->ReadWrite.cbIoBuf = 0; 3471 RTListAppend(&LstIoReqCanceled, &pIoReqCur->NdLstWait); 3472 } 3473 else 3474 { 3475 ASMAtomicIncU32(&pThis->cIoReqsActive); 3476 RTListAppend(&LstIoReqProcess, &pIoReqCur->NdLstWait); 3477 } 3478 } 3479 else 3480 { 3481 Assert(rc == VERR_NO_MEMORY); 3482 break; 3483 } 3484 } 3485 RTCritSectLeave(&pThis->CritSectIoReqsIoBufWait); 3486 3487 ASMAtomicAddU32(&pThis->cIoReqsWaiting, cIoReqsWaiting); 3488 3489 /* Process the requests we could allocate memory for and the ones which got canceled outside the lock now. */ 3490 RTListForEachSafe(&LstIoReqCanceled, pIoReqCur, pIoReqNext, PDMMEDIAEXIOREQINT, NdLstWait) 3491 { 3492 RTListNodeRemove(&pIoReqCur->NdLstWait); 3493 drvvdMediaExIoReqCompleteWorker(pThis, pIoReqCur, VERR_PDM_MEDIAEX_IOREQ_CANCELED, true /* fUpNotify */); 3494 } 3495 3496 RTListForEachSafe(&LstIoReqProcess, pIoReqCur, pIoReqNext, PDMMEDIAEXIOREQINT, NdLstWait) 3497 { 3498 RTListNodeRemove(&pIoReqCur->NdLstWait); 3499 drvvdMediaExIoReqReadWriteProcess(pThis, pIoReqCur, true /* fUpNotify */); 3500 } 3501 } 3517 if (!ASMAtomicReadBool(&pThis->fSuspending)) 3518 drvvdMediaExIoReqProcessWaiting(pThis); 3502 3519 } 3503 3520 … … 3688 3705 3689 3706 /** 3707 * @interface_method_impl{PDMIMEDIAEX,pfnNotifySuspend} 3708 */ 3709 static DECLCALLBACK(void) drvvdNotifySuspend(PPDMIMEDIAEX pInterface) 3710 { 3711 PVBOXDISK pThis = RT_FROM_MEMBER(pInterface, VBOXDISK, IMediaEx); 3712 3713 ASMAtomicXchgBool(&pThis->fSuspending, true); 3714 3715 /* Mark all waiting requests as suspended so they don't get accounted for. */ 3716 RTCritSectEnter(&pThis->CritSectIoReqsIoBufWait); 3717 PPDMMEDIAEXIOREQINT pIoReqCur, pIoReqNext; 3718 RTListForEachSafe(&pThis->LstIoReqIoBufWait, pIoReqCur, pIoReqNext, PDMMEDIAEXIOREQINT, NdLstWait) 3719 { 3720 pThis->pDrvMediaExPort->pfnIoReqStateChanged(pThis->pDrvMediaExPort, pIoReqCur, &pIoReqCur->abAlloc[0], 3721 PDMMEDIAEXIOREQSTATE_SUSPENDED); 3722 } 3723 RTCritSectLeave(&pThis->CritSectIoReqsIoBufWait); 3724 } 3725 3726 3727 /** 3690 3728 * @interface_method_impl{PDMIMEDIAEX,pfnIoReqAllocSizeSet} 3691 3729 */ … … 4098 4136 RTCritSectLeave(&pThis->CritSectIoReqRedo); 4099 4137 4100 return cIoReqSuspended ;4138 return cIoReqSuspended + pThis->cIoReqsWaiting; 4101 4139 } 4102 4140 … … 4110 4148 4111 4149 AssertReturn(!drvvdMediaExIoReqIsVmRunning(pThis), VERR_INVALID_STATE); 4112 AssertReturn(!RTListIsEmpty(&pThis->LstIoReqRedo), VERR_NOT_FOUND); 4113 4114 RTCritSectEnter(&pThis->CritSectIoReqRedo); 4115 PPDMMEDIAEXIOREQINT pIoReq = RTListGetFirst(&pThis->LstIoReqRedo, PDMMEDIAEXIOREQINT, NdLstWait); 4150 AssertReturn(!( RTListIsEmpty(&pThis->LstIoReqRedo) 4151 && RTListIsEmpty(&pThis->LstIoReqIoBufWait)), VERR_NOT_FOUND); 4152 4153 PRTLISTANCHOR pLst; 4154 PRTCRITSECT pCritSect; 4155 if (!RTListIsEmpty(&pThis->LstIoReqRedo)) 4156 { 4157 pLst = &pThis->LstIoReqRedo; 4158 pCritSect = &pThis->CritSectIoReqRedo; 4159 } 4160 else 4161 { 4162 pLst = &pThis->LstIoReqIoBufWait; 4163 pCritSect = &pThis->CritSectIoReqsIoBufWait; 4164 } 4165 4166 RTCritSectEnter(pCritSect); 4167 PPDMMEDIAEXIOREQINT pIoReq = RTListGetFirst(pLst, PDMMEDIAEXIOREQINT, NdLstWait); 4116 4168 *phIoReq = pIoReq; 4117 4169 *ppvIoReqAlloc = &pIoReq->abAlloc[0]; 4118 RTCritSectLeave( &pThis->CritSectIoReqRedo);4170 RTCritSectLeave(pCritSect); 4119 4171 4120 4172 return VINF_SUCCESS; … … 4132 4184 AssertReturn(!drvvdMediaExIoReqIsVmRunning(pThis), VERR_INVALID_STATE); 4133 4185 AssertPtrReturn(pIoReq, VERR_INVALID_HANDLE); 4134 AssertReturn(!RTListNodeIsLast(&pThis->LstIoReqRedo, &pIoReq->NdLstWait), VERR_NOT_FOUND); 4135 4136 RTCritSectEnter(&pThis->CritSectIoReqRedo); 4137 PPDMMEDIAEXIOREQINT pIoReqNext = RTListNodeGetNext(&pIoReq->NdLstWait, PDMMEDIAEXIOREQINT, NdLstWait); 4186 AssertReturn( ( pIoReq->enmState == VDIOREQSTATE_SUSPENDED 4187 && ( !RTListNodeIsLast(&pThis->LstIoReqRedo, &pIoReq->NdLstWait) 4188 || !RTListIsEmpty(&pThis->LstIoReqIoBufWait))) 4189 || ( pIoReq->enmState == VDIOREQSTATE_ALLOCATED 4190 && !RTListNodeIsLast(&pThis->LstIoReqIoBufWait, &pIoReq->NdLstWait)), VERR_NOT_FOUND); 4191 4192 PPDMMEDIAEXIOREQINT pIoReqNext; 4193 if (pIoReq->enmState == VDIOREQSTATE_SUSPENDED) 4194 { 4195 if (!RTListNodeIsLast(&pThis->LstIoReqRedo, &pIoReq->NdLstWait)) 4196 { 4197 RTCritSectEnter(&pThis->CritSectIoReqRedo); 4198 pIoReqNext = RTListNodeGetNext(&pIoReq->NdLstWait, PDMMEDIAEXIOREQINT, NdLstWait); 4199 RTCritSectLeave(&pThis->CritSectIoReqRedo); 4200 } 4201 else 4202 { 4203 RTCritSectEnter(&pThis->CritSectIoReqsIoBufWait); 4204 pIoReqNext = RTListGetFirst(&pThis->LstIoReqIoBufWait, PDMMEDIAEXIOREQINT, NdLstWait); 4205 RTCritSectLeave(&pThis->CritSectIoReqsIoBufWait); 4206 } 4207 } 4208 else 4209 { 4210 RTCritSectEnter(&pThis->CritSectIoReqsIoBufWait); 4211 pIoReqNext = RTListNodeGetNext(&pIoReq->NdLstWait, PDMMEDIAEXIOREQINT, NdLstWait); 4212 RTCritSectLeave(&pThis->CritSectIoReqsIoBufWait); 4213 } 4214 4138 4215 *phIoReqNext = pIoReqNext; 4139 4216 *ppvIoReqAllocNext = &pIoReqNext->abAlloc[0]; 4140 RTCritSectLeave(&pThis->CritSectIoReqRedo);4141 4217 4142 4218 return VINF_SUCCESS; … … 4153 4229 AssertReturn(!drvvdMediaExIoReqIsVmRunning(pThis), VERR_INVALID_STATE); 4154 4230 AssertPtrReturn(pIoReq, VERR_INVALID_HANDLE); 4155 AssertReturn(pIoReq->enmState == VDIOREQSTATE_SUSPENDED, VERR_INVALID_STATE); 4231 AssertReturn( pIoReq->enmState == VDIOREQSTATE_SUSPENDED 4232 || pIoReq->enmState == VDIOREQSTATE_ALLOCATED, VERR_INVALID_STATE); 4156 4233 4157 4234 SSMR3PutU32(pSSM, DRVVD_IOREQ_SAVED_STATE_VERSION); … … 4649 4726 4650 4727 drvvdSetWritable(pThis); 4651 pThis->f ErrorUseRuntime = true;4728 pThis->fSuspending = false; 4652 4729 4653 4730 if (pThis->pBlkCache) … … 4659 4736 if (pThis->pDrvMediaExPort) 4660 4737 { 4738 /* Mark all requests waiting for I/O memory as active again so they get accounted for. */ 4739 RTCritSectEnter(&pThis->CritSectIoReqsIoBufWait); 4740 PPDMMEDIAEXIOREQINT pIoReq, pIoReqNext; 4741 RTListForEachSafe(&pThis->LstIoReqIoBufWait, pIoReq, pIoReqNext, PDMMEDIAEXIOREQINT, NdLstWait) 4742 { 4743 pThis->pDrvMediaExPort->pfnIoReqStateChanged(pThis->pDrvMediaExPort, pIoReq, &pIoReq->abAlloc[0], 4744 PDMMEDIAEXIOREQSTATE_ACTIVE); 4745 ASMAtomicIncU32(&pThis->cIoReqsActive); 4746 } 4747 RTCritSectLeave(&pThis->CritSectIoReqsIoBufWait); 4748 4661 4749 /* Kick of any request we have to redo. */ 4662 PPDMMEDIAEXIOREQINT pIoReq, pIoReqNext;4663 4750 RTCritSectEnter(&pThis->CritSectIoReqRedo); 4664 4751 RTListForEachSafe(&pThis->LstIoReqRedo, pIoReq, pIoReqNext, PDMMEDIAEXIOREQINT, NdLstWait) … … 4719 4806 RTCritSectLeave(&pThis->CritSectIoReqRedo); 4720 4807 } 4808 4809 /* Try to process any requests waiting for I/O memory now. */ 4810 drvvdMediaExIoReqProcessWaiting(pThis); 4811 pThis->fErrorUseRuntime = true; 4721 4812 } 4722 4813 … … 4869 4960 pThis->hIoBufMgr = NIL_IOBUFMGR; 4870 4961 pThis->pRegionList = NULL; 4962 pThis->fSuspending = false; 4871 4963 4872 4964 for (unsigned i = 0; i < RT_ELEMENTS(pThis->aIoReqAllocBins); i++) … … 4906 4998 /* IMediaEx */ 4907 4999 pThis->IMediaEx.pfnQueryFeatures = drvvdQueryFeatures; 5000 pThis->IMediaEx.pfnNotifySuspend = drvvdNotifySuspend; 4908 5001 pThis->IMediaEx.pfnIoReqAllocSizeSet = drvvdIoReqAllocSizeSet; 4909 5002 pThis->IMediaEx.pfnIoReqAlloc = drvvdIoReqAlloc;
Note:
See TracChangeset
for help on using the changeset viewer.