VBOXDDU_DECL(int) VDDbgIoLogEventGetStart(VDIOLOGGER hIoLogger, uint64_t *pidEvent, bool *pfAsync, uint64_t *poff, size_t *pcbIo, size_t cbBuf, void *pvBuf) { int rc = VINF_SUCCESS; PVDIOLOGGERINT pIoLogger = hIoLogger; AssertPtrReturn(pIoLogger, VERR_INVALID_HANDLE); AssertPtrReturn(pidEvent, VERR_INVALID_POINTER); AssertPtrReturn(pfAsync, VERR_INVALID_POINTER); AssertPtrReturn(poff, VERR_INVALID_POINTER); AssertPtrReturn(pcbIo, VERR_INVALID_POINTER); rc = RTSemFastMutexRequest(pIoLogger->hMtx); AssertRCReturn(rc, rc); if (pIoLogger->u32EventTypeNext == VDIOLOG_EVENT_START) { IoLogEntryStart Entry; rc = RTFileReadAt(pIoLogger->hFile, pIoLogger->offReadNext, &Entry, sizeof(Entry), NULL); if (RT_SUCCESS(rc)) { *pfAsync = RT_BOOL(Entry.u8AsyncIo); *pidEvent = RT_LE2H_U64(Entry.u64Id); *poff = RT_LE2H_U64(Entry.Io.u64Off); *pcbIo = RT_LE2H_U64(Entry.Io.u64IoSize); if ( pIoLogger->enmReqTypeNext == VDDBGIOLOGREQ_WRITE && (pIoLogger->fFlags & VDDBG_IOLOG_LOG_DATA_WRITTEN)) { /* Read data. */ if (cbBuf < *pcbIo) rc = VERR_BUFFER_OVERFLOW; else rc = RTFileReadAt(pIoLogger->hFile, pIoLogger->offReadNext + sizeof(Entry), pvBuf, *pcbIo, NULL); if (rc != VERR_BUFFER_OVERFLOW) pIoLogger->offReadNext += *pcbIo + sizeof(Entry); } else pIoLogger->offReadNext += sizeof(Entry); } } else rc = VERR_INVALID_STATE; if (RT_SUCCESS(rc)) pIoLogger->u32EventTypeNext = 0; RTSemFastMutexRelease(pIoLogger->hMtx); return rc; }
VBOXDDU_DECL(int) VDDbgIoLogEventGetComplete(VDIOLOGGER hIoLogger, uint64_t *pidEvent, int *pRc, uint64_t *pmsDuration, size_t *pcbIo, size_t cbBuf, void *pvBuf) { int rc = VINF_SUCCESS; PVDIOLOGGERINT pIoLogger = hIoLogger; AssertPtrReturn(pIoLogger, VERR_INVALID_HANDLE); AssertPtrReturn(pidEvent, VERR_INVALID_POINTER); AssertPtrReturn(pmsDuration, VERR_INVALID_POINTER); AssertPtrReturn(pcbIo, VERR_INVALID_POINTER); rc = RTSemFastMutexRequest(pIoLogger->hMtx); AssertRCReturn(rc, rc); if (pIoLogger->u32EventTypeNext == VDIOLOG_EVENT_COMPLETE) { IoLogEntryComplete Entry; rc = RTFileReadAt(pIoLogger->hFile, pIoLogger->offReadNext, &Entry, sizeof(Entry), NULL); if (RT_SUCCESS(rc)) { *pidEvent = RT_LE2H_U64(Entry.u64Id); *pRc = (int)RT_LE2H_U32((int32_t)Entry.i32Rc); *pmsDuration = RT_LE2H_U64(Entry.msDuration); *pcbIo = RT_LE2H_U64(Entry.u64IoBuffer); if (*pcbIo) { /* Read data. */ if (cbBuf < *pcbIo) rc = VERR_BUFFER_OVERFLOW; else rc = RTFileReadAt(pIoLogger->hFile, pIoLogger->offReadNext + sizeof(Entry), pvBuf, *pcbIo, NULL); if (rc != VERR_BUFFER_OVERFLOW) pIoLogger->offReadNext += *pcbIo + sizeof(Entry); } else pIoLogger->offReadNext += sizeof(Entry); } } else rc = VERR_INVALID_STATE; if (RT_SUCCESS(rc)) pIoLogger->u32EventTypeNext = 0; RTSemFastMutexRelease(pIoLogger->hMtx); return rc; }
/** * Read bytes from a file at a given offset into a S/G buffer. * This function may modify the file position. * * @returns iprt status code. * @param hFile Handle to the file. * @param off Where to read. * @param pSgBuf Pointer to the S/G buffer to read into. * @param cbToRead How much to read. * @param pcbRead How much we actually read. * If NULL an error will be returned for a partial read. */ RTR3DECL(int) RTFileSgReadAt(RTFILE hFile, RTFOFF off, PRTSGBUF pSgBuf, size_t cbToRead, size_t *pcbRead) { int rc = VINF_SUCCESS; size_t cbRead = 0; while (cbToRead) { size_t cbThisRead = 0; size_t cbBuf = cbToRead; void *pvBuf = RTSgBufGetNextSegment(pSgBuf, &cbBuf); rc = RTFileReadAt(hFile, off, pvBuf, cbBuf, pcbRead ? &cbThisRead : NULL); if (RT_SUCCESS(rc)) cbRead += cbThisRead; if ( RT_FAILURE(rc) || ( cbThisRead < cbBuf && pcbRead)) break; cbToRead -= cbBuf; off += cbBuf; } if (pcbRead) *pcbRead = cbRead; return rc; }
static int dvmDiskRead(void *pvUser, uint64_t off, void *pvBuf, size_t cbRead) { PTSTRTDVMDISK pDisk = (PTSTRTDVMDISK)pvUser; if (pDisk->fUseImage) return RTFileReadAt(pDisk->hImage, off, pvBuf, cbRead, NULL); return RTDvmVolumeRead(pDisk->hVol, off, pvBuf, cbRead); }
static int fileReadSyncCallback(void * /* pvUser */, void *pvStorage, uint64_t uOffset, void *pvBuf, size_t cbRead, size_t *pcbRead) { /* Validate input. */ AssertPtrReturn(pvStorage, VERR_INVALID_POINTER); // DEBUG_PRINT_FLOW(); PFILESTORAGEINTERNAL pInt = (PFILESTORAGEINTERNAL)pvStorage; return RTFileReadAt(pInt->file, uOffset, pvBuf, cbRead, pcbRead); }
VBOXDDU_DECL(int) VDDbgIoLogEventTypeGetNext(VDIOLOGGER hIoLogger, VDIOLOGEVENT *penmEvent) { int rc = VINF_SUCCESS; PVDIOLOGGERINT pIoLogger = hIoLogger; AssertPtrReturn(pIoLogger, VERR_INVALID_HANDLE); AssertPtrReturn(penmEvent, VERR_INVALID_POINTER); rc = RTSemFastMutexRequest(pIoLogger->hMtx); AssertRCReturn(rc, rc); if (pIoLogger->offReadNext == pIoLogger->offWriteNext) { *penmEvent = VDIOLOGEVENT_END; RTSemFastMutexRelease(pIoLogger->hMtx); return VINF_SUCCESS; } if (!pIoLogger->u32EventTypeNext) { uint32_t abBuf[2]; rc = RTFileReadAt(pIoLogger->hFile, pIoLogger->offReadNext, &abBuf, sizeof(abBuf), NULL); if (RT_SUCCESS(rc)) { pIoLogger->u32EventTypeNext = abBuf[0]; pIoLogger->enmReqTypeNext = (VDDBGIOLOGREQ)abBuf[1]; } } if (RT_SUCCESS(rc)) { Assert(pIoLogger->u32EventTypeNext != VDIOLOGEVENT_INVALID); switch (pIoLogger->u32EventTypeNext) { case VDIOLOG_EVENT_START: *penmEvent = VDIOLOGEVENT_START; break; case VDIOLOG_EVENT_COMPLETE: *penmEvent = VDIOLOGEVENT_COMPLETE; break; default: AssertMsgFailed(("Invalid event type %d\n", pIoLogger->u32EventTypeNext)); } } RTSemFastMutexRelease(pIoLogger->hMtx); return rc; }
DECLHIDDEN(int) drvHostBaseReadOs(PDRVHOSTBASE pThis, uint64_t off, void *pvBuf, size_t cbRead) { return RTFileReadAt(pThis->Os.hFileDevice, off, pvBuf, cbRead, NULL); }
/** * Processes a given task list for assigned to the given endpoint. */ static int pdmacFileAioMgrFailsafeProcessEndpointTaskList(PPDMACEPFILEMGR pAioMgr, PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint, PPDMACTASKFILE pTasks) { int rc = VINF_SUCCESS; while (pTasks) { RTMSINTERVAL msWhenNext; PPDMACTASKFILE pCurr = pTasks; if (!pdmacEpIsTransferAllowed(&pEndpoint->Core, (uint32_t)pCurr->DataSeg.cbSeg, &msWhenNext)) { pAioMgr->msBwLimitExpired = RT_MIN(pAioMgr->msBwLimitExpired, msWhenNext); break; } pTasks = pTasks->pNext; switch (pCurr->enmTransferType) { case PDMACTASKFILETRANSFER_FLUSH: { rc = RTFileFlush(pEndpoint->hFile); break; } case PDMACTASKFILETRANSFER_READ: case PDMACTASKFILETRANSFER_WRITE: { if (pCurr->enmTransferType == PDMACTASKFILETRANSFER_READ) { rc = RTFileReadAt(pEndpoint->hFile, pCurr->Off, pCurr->DataSeg.pvSeg, pCurr->DataSeg.cbSeg, NULL); } else { if (RT_UNLIKELY((uint64_t)pCurr->Off + pCurr->DataSeg.cbSeg > pEndpoint->cbFile)) { ASMAtomicWriteU64(&pEndpoint->cbFile, pCurr->Off + pCurr->DataSeg.cbSeg); RTFileSetSize(pEndpoint->hFile, pCurr->Off + pCurr->DataSeg.cbSeg); } rc = RTFileWriteAt(pEndpoint->hFile, pCurr->Off, pCurr->DataSeg.pvSeg, pCurr->DataSeg.cbSeg, NULL); } break; } default: AssertMsgFailed(("Invalid transfer type %d\n", pTasks->enmTransferType)); } pCurr->pfnCompleted(pCurr, pCurr->pvUser, rc); pdmacFileTaskFree(pEndpoint, pCurr); } if (pTasks) { /* Add the rest of the tasks to the pending list */ pdmacFileAioMgrEpAddTaskList(pEndpoint, pTasks); } return VINF_SUCCESS; }
VBOXDDU_DECL(int) VDDbgIoLogEventGetStartDiscard(VDIOLOGGER hIoLogger, uint64_t *pidEvent, bool *pfAsync, PRTRANGE *ppaRanges, unsigned *pcRanges) { int rc = VINF_SUCCESS; PVDIOLOGGERINT pIoLogger = hIoLogger; AssertPtrReturn(pIoLogger, VERR_INVALID_HANDLE); AssertPtrReturn(pidEvent, VERR_INVALID_POINTER); AssertPtrReturn(pfAsync, VERR_INVALID_POINTER); rc = RTSemFastMutexRequest(pIoLogger->hMtx); AssertRCReturn(rc, rc); if ( pIoLogger->u32EventTypeNext == VDIOLOG_EVENT_START && pIoLogger->enmReqTypeNext == VDDBGIOLOGREQ_DISCARD) { IoLogEntryStart Entry; rc = RTFileReadAt(pIoLogger->hFile, pIoLogger->offReadNext, &Entry, sizeof(Entry), NULL); if (RT_SUCCESS(rc)) { PRTRANGE paRanges = NULL; IoLogEntryDiscard DiscardRange; pIoLogger->offReadNext += sizeof(Entry); *pfAsync = RT_BOOL(Entry.u8AsyncIo); *pidEvent = RT_LE2H_U64(Entry.u64Id); *pcRanges = RT_LE2H_U32(Entry.Discard.cRanges); paRanges = (PRTRANGE)RTMemAllocZ(*pcRanges * sizeof(RTRANGE)); if (paRanges) { for (unsigned i = 0; i < *pcRanges; i++) { rc = RTFileReadAt(pIoLogger->hFile, pIoLogger->offReadNext + i*sizeof(DiscardRange), &DiscardRange, sizeof(DiscardRange), NULL); if (RT_FAILURE(rc)) break; paRanges[i].offStart = RT_LE2H_U64(DiscardRange.u64Off); paRanges[i].cbRange = RT_LE2H_U32(DiscardRange.u32Discard); } if (RT_SUCCESS(rc)) { pIoLogger->offReadNext += *pcRanges * sizeof(DiscardRange); *ppaRanges = paRanges; } else { pIoLogger->offReadNext -= sizeof(Entry); RTMemFree(paRanges); } } else rc = VERR_NO_MEMORY; } } else rc = VERR_INVALID_STATE; if (RT_SUCCESS(rc)) pIoLogger->u32EventTypeNext = 0; RTSemFastMutexRelease(pIoLogger->hMtx); return rc; }