Changeset 52358 in vbox
- Timestamp:
- Aug 12, 2014 8:43:35 AM (10 years ago)
- Location:
- trunk
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/list.h
r48782 r52358 403 403 } 404 404 405 /** 406 * List concatenation. 407 * 408 * @returns nothing. 409 * @param pListDst The destination list. 410 * @param pListSrc The source list to concatenate. 411 */ 412 DECLINLINE(void) RTListConcatenate(PRTLISTANCHOR pListDst, PRTLISTANCHOR pListSrc) 413 { 414 if (!RTListIsEmpty(pListSrc)) 415 { 416 PRTLISTNODE pFirst = pListSrc->pNext; 417 PRTLISTNODE pLast = pListSrc->pPrev; 418 419 pListDst->pPrev->pNext = pFirst; 420 pFirst->pPrev = pListDst->pPrev; 421 pLast->pNext = pListDst; 422 pListDst->pPrev = pLast; 423 424 /* Finally remove the elements from the source list */ 425 RTListInit(pListSrc); 426 } 427 } 428 405 429 RT_C_DECLS_END 406 430 -
trunk/src/VBox/Storage/VD.cpp
r52268 r52358 579 579 /** Size of the data stored with this entry. */ 580 580 size_t cbMeta; 581 /** Shadow buffer which is used in case a write is still active and other 582 * writes update the shadow buffer. */ 583 uint8_t *pbDataShw; 584 /** List of I/O contexts updating the shadow buffer while there is a write 585 * in progress. */ 586 RTLISTNODE ListIoCtxShwWrites; 581 587 /** Data stored - variable size. */ 582 588 uint8_t abData[1]; … … 1545 1551 pMetaXfer->pIoStorage = pIoStorage; 1546 1552 pMetaXfer->cRefs = 0; 1553 pMetaXfer->pbDataShw = NULL; 1547 1554 RTListInit(&pMetaXfer->ListIoCtxWaiting); 1555 RTListInit(&pMetaXfer->ListIoCtxShwWrites); 1548 1556 } 1549 1557 return pMetaXfer; … … 4013 4021 } 4014 4022 4023 static void vdIoCtxContinueDeferredList(PVDIOSTORAGE pIoStorage, PRTLISTANCHOR pListWaiting, 4024 PFNVDXFERCOMPLETED pfnComplete, void *pvUser, int rcReq) 4025 { 4026 LogFlowFunc(("pIoStorage=%#p pListWaiting=%#p pfnComplete=%#p pvUser=%#p rcReq=%Rrc\n", 4027 pIoStorage, pListWaiting, pfnComplete, pvUser, rcReq)); 4028 4029 /* Go through the waiting list and continue the I/O contexts. */ 4030 while (!RTListIsEmpty(pListWaiting)) 4031 { 4032 int rc = VINF_SUCCESS; 4033 bool fContinue = true; 4034 PVDIOCTXDEFERRED pDeferred = RTListGetFirst(pListWaiting, VDIOCTXDEFERRED, NodeDeferred); 4035 PVDIOCTX pIoCtx = pDeferred->pIoCtx; 4036 RTListNodeRemove(&pDeferred->NodeDeferred); 4037 4038 RTMemFree(pDeferred); 4039 ASMAtomicDecU32(&pIoCtx->cMetaTransfersPending); 4040 4041 if (pfnComplete) 4042 rc = pfnComplete(pIoStorage->pVDIo->pBackendData, pIoCtx, pvUser, rcReq); 4043 4044 LogFlow(("Completion callback for I/O context %#p returned %Rrc\n", pIoCtx, rc)); 4045 4046 if (RT_SUCCESS(rc)) 4047 { 4048 rc = vdIoCtxContinue(pIoCtx, rcReq); 4049 AssertRC(rc); 4050 } 4051 else 4052 Assert(rc == VERR_VD_ASYNC_IO_IN_PROGRESS); 4053 } 4054 } 4055 4015 4056 /** 4016 4057 * Internal - Called when a meta transfer completed. … … 4029 4070 4030 4071 fFlush = VDMETAXFER_TXDIR_GET(pMetaXfer->fFlags) == VDMETAXFER_TXDIR_FLUSH; 4031 VDMETAXFER_TXDIR_SET(pMetaXfer->fFlags, VDMETAXFER_TXDIR_NONE);4032 4072 4033 4073 if (!fFlush) … … 4041 4081 bool fRemoved = RTAvlrFileOffsetRemove(pIoStorage->pTreeMetaXfers, pMetaXfer->Core.Key) != NULL; 4042 4082 Assert(fRemoved); 4083 /* If this was a write check if there is a shadow buffer with updated data. */ 4084 if (pMetaXfer->pbDataShw) 4085 { 4086 Assert(VDMETAXFER_TXDIR_GET(pMetaXfer->fFlags) == VDMETAXFER_TXDIR_WRITE); 4087 Assert(!RTListIsEmpty(&pMetaXfer->ListIoCtxShwWrites)); 4088 RTListConcatenate(&ListIoCtxWaiting, &pMetaXfer->ListIoCtxShwWrites); 4089 RTMemFree(pMetaXfer->pbDataShw); 4090 pMetaXfer->pbDataShw = NULL; 4091 } 4043 4092 RTMemFree(pMetaXfer); 4044 4093 } … … 4052 4101 RTListMove(&ListIoCtxWaiting, &pMetaXfer->ListIoCtxWaiting); 4053 4102 4054 /* Go through the waiting list and continue the I/O contexts. */ 4055 while (!RTListIsEmpty(&ListIoCtxWaiting)) 4056 { 4057 int rc = VINF_SUCCESS; 4058 bool fContinue = true; 4059 PVDIOCTXDEFERRED pDeferred = RTListGetFirst(&ListIoCtxWaiting, VDIOCTXDEFERRED, NodeDeferred); 4060 PVDIOCTX pIoCtx = pDeferred->pIoCtx; 4061 RTListNodeRemove(&pDeferred->NodeDeferred); 4062 4063 RTMemFree(pDeferred); 4064 ASMAtomicDecU32(&pIoCtx->cMetaTransfersPending); 4065 4066 if (pfnComplete) 4067 rc = pfnComplete(pIoStorage->pVDIo->pBackendData, pIoCtx, pvUser, rcReq); 4068 4069 LogFlow(("Completion callback for I/O context %#p returned %Rrc\n", pIoCtx, rc)); 4070 4071 if (RT_SUCCESS(rc)) 4072 { 4073 rc = vdIoCtxContinue(pIoCtx, rcReq); 4074 AssertRC(rc); 4103 VDMETAXFER_TXDIR_SET(pMetaXfer->fFlags, VDMETAXFER_TXDIR_NONE); 4104 vdIoCtxContinueDeferredList(pIoStorage, &ListIoCtxWaiting, pfnComplete, pvUser, rcReq); 4105 4106 /* 4107 * If there is a shadow buffer and the previous write was successful update with the 4108 * new data and trigger a new write. 4109 */ 4110 if ( pMetaXfer->pbDataShw 4111 && RT_SUCCESS(rcReq) 4112 && VDMETAXFER_TXDIR_GET(pMetaXfer->fFlags) == VDMETAXFER_TXDIR_NONE) 4113 { 4114 LogFlowFunc(("pMetaXfer=%#p Updating from shadow buffer and triggering new write\n", pMetaXfer)); 4115 memcpy(pMetaXfer->abData, pMetaXfer->pbDataShw, pMetaXfer->cbMeta); 4116 RTMemFree(pMetaXfer->pbDataShw); 4117 pMetaXfer->pbDataShw = NULL; 4118 Assert(!RTListIsEmpty(&pMetaXfer->ListIoCtxShwWrites)); 4119 4120 /* Setup a new I/O write. */ 4121 PVDIOTASK pIoTask = vdIoTaskMetaAlloc(pIoStorage, pfnComplete, pvUser, pMetaXfer); 4122 if (RT_LIKELY(pIoTask)) 4123 { 4124 void *pvTask = NULL; 4125 RTSGSEG Seg; 4126 4127 Seg.cbSeg = pMetaXfer->cbMeta; 4128 Seg.pvSeg = pMetaXfer->abData; 4129 4130 VDMETAXFER_TXDIR_SET(pMetaXfer->fFlags, VDMETAXFER_TXDIR_WRITE); 4131 rcReq = pIoStorage->pVDIo->pInterfaceIo->pfnWriteAsync(pIoStorage->pVDIo->pInterfaceIo->Core.pvUser, 4132 pIoStorage->pStorage, 4133 pMetaXfer->Core.Key, &Seg, 1, 4134 pMetaXfer->cbMeta, pIoTask, 4135 &pvTask); 4136 if ( RT_SUCCESS(rcReq) 4137 || rcReq != VERR_VD_ASYNC_IO_IN_PROGRESS) 4138 { 4139 VDMETAXFER_TXDIR_SET(pMetaXfer->fFlags, VDMETAXFER_TXDIR_NONE); 4140 vdIoTaskFree(pDisk, pIoTask); 4141 } 4142 else 4143 RTListMove(&pMetaXfer->ListIoCtxWaiting, &pMetaXfer->ListIoCtxShwWrites); 4075 4144 } 4076 4145 else 4077 Assert(rc == VERR_VD_ASYNC_IO_IN_PROGRESS); 4146 rcReq = VERR_NO_MEMORY; 4147 4148 /* Cleanup if there was an error or the request completed already. */ 4149 if (rcReq != VERR_VD_ASYNC_IO_IN_PROGRESS) 4150 vdIoCtxContinueDeferredList(pIoStorage, &pMetaXfer->ListIoCtxShwWrites, pfnComplete, pvUser, rcReq); 4078 4151 } 4079 4152 4080 4153 /* Remove if not used anymore. */ 4081 if ( RT_SUCCESS(rcReq) &&!fFlush)4154 if (!fFlush) 4082 4155 { 4083 4156 pMetaXfer->cRefs--; … … 4683 4756 Assert(pMetaXfer->cbMeta >= cbRead); 4684 4757 Assert(pMetaXfer->Core.Key == (RTFOFF)uOffset); 4685 memcpy(pvBuf, pMetaXfer->abData, cbRead); 4758 if (pMetaXfer->pbDataShw) 4759 memcpy(pvBuf, pMetaXfer->pbDataShw, cbRead); 4760 else 4761 memcpy(pvBuf, pMetaXfer->abData, cbRead); 4686 4762 *ppMetaXfer = pMetaXfer; 4687 4763 } … … 4745 4821 } 4746 4822 4747 Assert(VDMETAXFER_TXDIR_GET(pMetaXfer->fFlags) == VDMETAXFER_TXDIR_NONE); 4748 4749 pIoTask = vdIoTaskMetaAlloc(pIoStorage, pfnComplete, pvCompleteUser, pMetaXfer); 4750 if (!pIoTask) 4751 { 4752 RTMemFree(pMetaXfer); 4753 return VERR_NO_MEMORY; 4754 } 4755 4756 memcpy(pMetaXfer->abData, pvBuf, cbWrite); 4757 Seg.cbSeg = cbWrite; 4758 Seg.pvSeg = pMetaXfer->abData; 4759 4760 ASMAtomicIncU32(&pIoCtx->cMetaTransfersPending); 4761 4762 VDMETAXFER_TXDIR_SET(pMetaXfer->fFlags, VDMETAXFER_TXDIR_WRITE); 4763 rc = pVDIo->pInterfaceIo->pfnWriteAsync(pVDIo->pInterfaceIo->Core.pvUser, 4764 pIoStorage->pStorage, 4765 uOffset, &Seg, 1, cbWrite, pIoTask, 4766 &pvTask); 4767 if (RT_SUCCESS(rc)) 4768 { 4769 VDMETAXFER_TXDIR_SET(pMetaXfer->fFlags, VDMETAXFER_TXDIR_NONE); 4770 ASMAtomicDecU32(&pIoCtx->cMetaTransfersPending); 4771 vdIoTaskFree(pDisk, pIoTask); 4772 if (fInTree && !pMetaXfer->cRefs) 4823 if (VDMETAXFER_TXDIR_GET(pMetaXfer->fFlags) == VDMETAXFER_TXDIR_NONE) 4824 { 4825 pIoTask = vdIoTaskMetaAlloc(pIoStorage, pfnComplete, pvCompleteUser, pMetaXfer); 4826 if (!pIoTask) 4773 4827 { 4774 LogFlow(("Removing meta xfer=%#p\n", pMetaXfer)); 4775 bool fRemoved = RTAvlrFileOffsetRemove(pIoStorage->pTreeMetaXfers, pMetaXfer->Core.Key) != NULL; 4776 AssertMsg(fRemoved, ("Metadata transfer wasn't removed\n")); 4828 RTMemFree(pMetaXfer); 4829 return VERR_NO_MEMORY; 4830 } 4831 4832 memcpy(pMetaXfer->abData, pvBuf, cbWrite); 4833 Seg.cbSeg = cbWrite; 4834 Seg.pvSeg = pMetaXfer->abData; 4835 4836 ASMAtomicIncU32(&pIoCtx->cMetaTransfersPending); 4837 4838 VDMETAXFER_TXDIR_SET(pMetaXfer->fFlags, VDMETAXFER_TXDIR_WRITE); 4839 rc = pVDIo->pInterfaceIo->pfnWriteAsync(pVDIo->pInterfaceIo->Core.pvUser, 4840 pIoStorage->pStorage, 4841 uOffset, &Seg, 1, cbWrite, pIoTask, 4842 &pvTask); 4843 if (RT_SUCCESS(rc)) 4844 { 4845 VDMETAXFER_TXDIR_SET(pMetaXfer->fFlags, VDMETAXFER_TXDIR_NONE); 4846 ASMAtomicDecU32(&pIoCtx->cMetaTransfersPending); 4847 vdIoTaskFree(pDisk, pIoTask); 4848 if (fInTree && !pMetaXfer->cRefs) 4849 { 4850 LogFlow(("Removing meta xfer=%#p\n", pMetaXfer)); 4851 bool fRemoved = RTAvlrFileOffsetRemove(pIoStorage->pTreeMetaXfers, pMetaXfer->Core.Key) != NULL; 4852 AssertMsg(fRemoved, ("Metadata transfer wasn't removed\n")); 4853 RTMemFree(pMetaXfer); 4854 pMetaXfer = NULL; 4855 } 4856 } 4857 else if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS) 4858 { 4859 PVDIOCTXDEFERRED pDeferred = (PVDIOCTXDEFERRED)RTMemAllocZ(sizeof(VDIOCTXDEFERRED)); 4860 AssertPtr(pDeferred); 4861 4862 RTListInit(&pDeferred->NodeDeferred); 4863 pDeferred->pIoCtx = pIoCtx; 4864 4865 if (!fInTree) 4866 { 4867 bool fInserted = RTAvlrFileOffsetInsert(pIoStorage->pTreeMetaXfers, &pMetaXfer->Core); 4868 Assert(fInserted); 4869 } 4870 4871 RTListAppend(&pMetaXfer->ListIoCtxWaiting, &pDeferred->NodeDeferred); 4872 } 4873 else 4874 { 4777 4875 RTMemFree(pMetaXfer); 4778 4876 pMetaXfer = NULL; 4779 4877 } 4780 4878 } 4781 else if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS) 4782 { 4783 PVDIOCTXDEFERRED pDeferred = (PVDIOCTXDEFERRED)RTMemAllocZ(sizeof(VDIOCTXDEFERRED)); 4784 AssertPtr(pDeferred); 4785 4786 RTListInit(&pDeferred->NodeDeferred); 4787 pDeferred->pIoCtx = pIoCtx; 4788 4789 if (!fInTree) 4879 else 4880 { 4881 /* I/O is in progress, update shadow buffer and add to waiting list. */ 4882 Assert(VDMETAXFER_TXDIR_GET(pMetaXfer->fFlags) == VDMETAXFER_TXDIR_WRITE); 4883 if (!pMetaXfer->pbDataShw) 4790 4884 { 4791 bool fInserted = RTAvlrFileOffsetInsert(pIoStorage->pTreeMetaXfers, &pMetaXfer->Core); 4792 Assert(fInserted); 4885 /* Allocate shadow buffer and set initial state. */ 4886 LogFlowFunc(("pMetaXfer=%#p Creating shadow buffer\n", pMetaXfer)); 4887 pMetaXfer->pbDataShw = (uint8_t *)RTMemAlloc(pMetaXfer->cbMeta); 4888 if (RT_LIKELY(pMetaXfer->pbDataShw)) 4889 memcpy(pMetaXfer->pbDataShw, pMetaXfer->abData, pMetaXfer->cbMeta); 4890 else 4891 rc = VERR_NO_MEMORY; 4793 4892 } 4794 4893 4795 RTListAppend(&pMetaXfer->ListIoCtxWaiting, &pDeferred->NodeDeferred); 4796 } 4797 else 4798 { 4799 RTMemFree(pMetaXfer); 4800 pMetaXfer = NULL; 4894 if (RT_SUCCESS(rc)) 4895 { 4896 /* Update with written data and append to waiting list. */ 4897 PVDIOCTXDEFERRED pDeferred = (PVDIOCTXDEFERRED)RTMemAllocZ(sizeof(VDIOCTXDEFERRED)); 4898 if (pDeferred) 4899 { 4900 LogFlowFunc(("pMetaXfer=%#p Updating shadow buffer\n", pMetaXfer)); 4901 4902 RTListInit(&pDeferred->NodeDeferred); 4903 pDeferred->pIoCtx = pIoCtx; 4904 ASMAtomicIncU32(&pIoCtx->cMetaTransfersPending); 4905 memcpy(pMetaXfer->pbDataShw, pvBuf, cbWrite); 4906 RTListAppend(&pMetaXfer->ListIoCtxShwWrites, &pDeferred->NodeDeferred); 4907 } 4908 else 4909 { 4910 /* 4911 * Free shadow buffer if there is no one depending on it, i.e. 4912 * we just allocated it. 4913 */ 4914 if (RTListIsEmpty(&pMetaXfer->ListIoCtxShwWrites)) 4915 { 4916 RTMemFree(pMetaXfer->pbDataShw); 4917 pMetaXfer->pbDataShw = NULL; 4918 } 4919 rc = VERR_NO_MEMORY; 4920 } 4921 } 4801 4922 } 4802 4923 } -
trunk/src/VBox/Storage/VHD.cpp
r52277 r52358 623 623 if (fFlags == VHDIMAGEEXPAND_ALL_SUCCESS) 624 624 { 625 pImage->pBlockAllocationTable[pExpand->idxBatAllocated] = RT_BE2H_U32(pExpand->idxBlockBe); 625 626 RTMemFree(pExpand); 626 627 } … … 1691 1692 */ 1692 1693 rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pImage->pStorage, 1693 pImage->uCurrentEndOfFile + pImage->cDataBlockBitmapSectors* VHD_SECTOR_SIZE,1694 pImage->uCurrentEndOfFile + (pImage->cDataBlockBitmapSectors + (cSector % pImage->cSectorsPerDataBlock)) * VHD_SECTOR_SIZE, 1694 1695 pIoCtx, cbWrite, 1695 1696 vhdAsyncExpansionDataComplete, … … 1729 1730 * Set the new end of the file and link the new block into the BAT. 1730 1731 */ 1731 pImage->pBlockAllocationTable[cBlockAllocationTableEntry] = pImage->uCurrentEndOfFile / VHD_SECTOR_SIZE;1732 1732 pImage->uCurrentEndOfFile += pImage->cDataBlockBitmapSectors * VHD_SECTOR_SIZE + pImage->cbDataBlock; 1733 1733
Note:
See TracChangeset
for help on using the changeset viewer.